зеркало из https://github.com/mozilla/gecko-dev.git
Bug 856829 - Add optimized stubs for GetProp-getter and SetProp-setter calling JSNative targets. r=jandem
This commit is contained in:
Родитель
833d84e579
Коммит
f851cf4a9e
|
@ -310,6 +310,14 @@ ICStub::trace(JSTracer *trc)
|
||||||
MarkObject(trc, &callStub->getter(), "baseline-getpropcallscripted-stub-getter");
|
MarkObject(trc, &callStub->getter(), "baseline-getpropcallscripted-stub-getter");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ICStub::GetProp_CallNative: {
|
||||||
|
ICGetProp_CallNative *callStub = toGetProp_CallNative();
|
||||||
|
MarkShape(trc, &callStub->shape(), "baseline-getpropcallnative-stub-shape");
|
||||||
|
MarkObject(trc, &callStub->holder(), "baseline-getpropcallnative-stub-holder");
|
||||||
|
MarkShape(trc, &callStub->holderShape(), "baseline-getpropcallnative-stub-holdershape");
|
||||||
|
MarkObject(trc, &callStub->getter(), "baseline-getpropcallnative-stub-getter");
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ICStub::SetProp_Native: {
|
case ICStub::SetProp_Native: {
|
||||||
ICSetProp_Native *propStub = toSetProp_Native();
|
ICSetProp_Native *propStub = toSetProp_Native();
|
||||||
MarkShape(trc, &propStub->shape(), "baseline-setpropnative-stub-shape");
|
MarkShape(trc, &propStub->shape(), "baseline-setpropnative-stub-shape");
|
||||||
|
@ -339,6 +347,14 @@ ICStub::trace(JSTracer *trc)
|
||||||
MarkObject(trc, &callStub->setter(), "baseline-setpropcallscripted-stub-setter");
|
MarkObject(trc, &callStub->setter(), "baseline-setpropcallscripted-stub-setter");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ICStub::SetProp_CallNative: {
|
||||||
|
ICSetProp_CallNative *callStub = toSetProp_CallNative();
|
||||||
|
MarkShape(trc, &callStub->shape(), "baseline-setpropcallnative-stub-shape");
|
||||||
|
MarkObject(trc, &callStub->holder(), "baseline-setpropcallnative-stub-holder");
|
||||||
|
MarkShape(trc, &callStub->holderShape(), "baseline-setpropcallnative-stub-holdershape");
|
||||||
|
MarkObject(trc, &callStub->setter(), "baseline-setpropcallnative-stub-setter");
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -579,7 +595,8 @@ ICStubCompiler::guardProfilingEnabled(MacroAssembler &masm, Register scratch, La
|
||||||
// This should only be called from the following stubs.
|
// This should only be called from the following stubs.
|
||||||
JS_ASSERT(kind == ICStub::Call_Scripted || kind == ICStub::Call_AnyScripted ||
|
JS_ASSERT(kind == ICStub::Call_Scripted || kind == ICStub::Call_AnyScripted ||
|
||||||
kind == ICStub::Call_Native || kind == ICStub::GetProp_CallScripted ||
|
kind == ICStub::Call_Native || kind == ICStub::GetProp_CallScripted ||
|
||||||
kind == ICStub::SetProp_CallScripted);
|
kind == ICStub::GetProp_CallNative || kind == ICStub::SetProp_CallScripted ||
|
||||||
|
kind == ICStub::SetProp_CallNative);
|
||||||
|
|
||||||
// Guard on bit in frame that indicates if the SPS frame was pushed in the first
|
// Guard on bit in frame that indicates if the SPS frame was pushed in the first
|
||||||
// place. This code is expected to be called from within a stub that has already
|
// place. This code is expected to be called from within a stub that has already
|
||||||
|
@ -3031,8 +3048,10 @@ IsCacheableGetPropReadSlot(JSObject *obj, JSObject *holder, Shape *shape)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
IsCacheableGetPropCallScripted(JSObject *obj, JSObject *holder, Shape *shape)
|
IsCacheableGetPropCall(JSObject *obj, JSObject *holder, Shape *shape, bool *isScripted)
|
||||||
{
|
{
|
||||||
|
JS_ASSERT(isScripted);
|
||||||
|
|
||||||
// Currently we only optimize getter calls for getters bound on prototypes.
|
// Currently we only optimize getter calls for getters bound on prototypes.
|
||||||
if (obj == holder)
|
if (obj == holder)
|
||||||
return false;
|
return false;
|
||||||
|
@ -3043,15 +3062,27 @@ IsCacheableGetPropCallScripted(JSObject *obj, JSObject *holder, Shape *shape)
|
||||||
if (shape->hasSlot() || shape->hasDefaultGetter())
|
if (shape->hasSlot() || shape->hasDefaultGetter())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!shape->hasGetterValue() || !shape->getterObject()->isFunction())
|
if (!shape->hasGetterValue())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!shape->getterValue().isObject() || !shape->getterObject()->isFunction())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
JSFunction *func = shape->getterObject()->toFunction();
|
JSFunction *func = shape->getterObject()->toFunction();
|
||||||
|
if (func->isNative()) {
|
||||||
|
*isScripted = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!func->hasScript())
|
if (!func->hasScript())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
JSScript *script = func->nonLazyScript();
|
JSScript *script = func->nonLazyScript();
|
||||||
return script->hasIonScript() || script->hasBaselineScript();
|
if (!script->hasIonScript() && !script->hasBaselineScript())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*isScripted = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -3132,8 +3163,10 @@ IsCacheableSetPropAddSlot(JSContext *cx, HandleObject obj, HandleShape oldShape,
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
IsCacheableSetPropCallScripted(JSObject *obj, JSObject *holder, Shape *shape)
|
IsCacheableSetPropCall(JSObject *obj, JSObject *holder, Shape *shape, bool *isScripted)
|
||||||
{
|
{
|
||||||
|
JS_ASSERT(isScripted);
|
||||||
|
|
||||||
// Currently we only optimize setter calls for setters bound on prototypes.
|
// Currently we only optimize setter calls for setters bound on prototypes.
|
||||||
if (obj == holder)
|
if (obj == holder)
|
||||||
return false;
|
return false;
|
||||||
|
@ -3144,15 +3177,27 @@ IsCacheableSetPropCallScripted(JSObject *obj, JSObject *holder, Shape *shape)
|
||||||
if (shape->hasSlot() || shape->hasDefaultSetter())
|
if (shape->hasSlot() || shape->hasDefaultSetter())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!shape->hasSetterValue() || !shape->setterObject()->isFunction())
|
if (!shape->hasSetterValue())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!shape->setterValue().isObject() || !shape->setterObject()->isFunction())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
JSFunction *func = shape->setterObject()->toFunction();
|
JSFunction *func = shape->setterObject()->toFunction();
|
||||||
|
if (func->isNative()) {
|
||||||
|
*isScripted = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!func->hasScript())
|
if (!func->hasScript())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
JSScript *script = func->nonLazyScript();
|
JSScript *script = func->nonLazyScript();
|
||||||
return script->hasIonScript() || script->hasBaselineScript();
|
if (!script->hasIonScript() && !script->hasBaselineScript())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*isScripted = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -4711,14 +4756,16 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only handle CallGetter stubs on prototypes for now, not direct getters.
|
bool isScripted = false;
|
||||||
if (IsCacheableGetPropCallScripted(obj, holder, shape)) {
|
bool cacheableCall = IsCacheableGetPropCall(obj, holder, shape, &isScripted);
|
||||||
|
|
||||||
|
// Try handling scripted getters.
|
||||||
|
if (cacheableCall && isScripted) {
|
||||||
RootedFunction callee(cx, shape->getterObject()->toFunction());
|
RootedFunction callee(cx, shape->getterObject()->toFunction());
|
||||||
JS_ASSERT(obj != holder);
|
JS_ASSERT(obj != holder);
|
||||||
JS_ASSERT(callee->hasScript());
|
JS_ASSERT(callee->hasScript());
|
||||||
|
|
||||||
IonSpew(IonSpew_BaselineIC, " Generating GetProp(Native %s Getter %s:%d) stub",
|
IonSpew(IonSpew_BaselineIC, " Generating GetProp(NativeObj/ScriptedGetter %s:%d) stub",
|
||||||
(obj == holder) ? "direct" : "prototype",
|
|
||||||
callee->nonLazyScript()->filename(), callee->nonLazyScript()->lineno);
|
callee->nonLazyScript()->filename(), callee->nonLazyScript()->lineno);
|
||||||
|
|
||||||
ICGetProp_CallScripted::Compiler compiler(cx, monitorStub, obj, holder, callee,
|
ICGetProp_CallScripted::Compiler compiler(cx, monitorStub, obj, holder, callee,
|
||||||
|
@ -4732,6 +4779,26 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try handling JSNative getters.
|
||||||
|
if (cacheableCall && !isScripted) {
|
||||||
|
RootedFunction callee(cx, shape->getterObject()->toFunction());
|
||||||
|
JS_ASSERT(obj != holder);
|
||||||
|
JS_ASSERT(callee->isNative());
|
||||||
|
|
||||||
|
IonSpew(IonSpew_BaselineIC, " Generating GetProp(NativeObj/NativeGetter %p) stub",
|
||||||
|
callee->native());
|
||||||
|
|
||||||
|
ICGetProp_CallNative::Compiler compiler(cx, monitorStub, obj, holder, callee,
|
||||||
|
pc - script->code);
|
||||||
|
ICStub *newStub = compiler.getStub(compiler.getStubSpace(script));
|
||||||
|
if (!newStub)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
stub->addNewStub(newStub);
|
||||||
|
*attached = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5137,6 +5204,99 @@ ICGetProp_CallScripted::Compiler::generateStubCode(MacroAssembler &masm)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
DoCallNativeGetter(JSContext *cx, HandleFunction callee, HandleObject obj,
|
||||||
|
MutableHandleValue result)
|
||||||
|
{
|
||||||
|
JS_ASSERT(callee->isNative());
|
||||||
|
JSNative natfun = callee->native();
|
||||||
|
|
||||||
|
Value vp[2] = { ObjectValue(*callee.get()), ObjectValue(*obj.get()) };
|
||||||
|
AutoValueArray rootVp(cx, vp, 2);
|
||||||
|
|
||||||
|
if (!natfun(cx, 0, vp))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
result.set(vp[0]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef bool (*DoCallNativeGetterFn)(JSContext *, HandleFunction, HandleObject, MutableHandleValue);
|
||||||
|
static const VMFunction DoCallNativeGetterInfo =
|
||||||
|
FunctionInfo<DoCallNativeGetterFn>(DoCallNativeGetter);
|
||||||
|
|
||||||
|
bool
|
||||||
|
ICGetProp_CallNative::Compiler::generateStubCode(MacroAssembler &masm)
|
||||||
|
{
|
||||||
|
Label failure;
|
||||||
|
GeneralRegisterSet regs(availableGeneralRegs(1));
|
||||||
|
Register scratch;
|
||||||
|
if (regs.has(BaselineTailCallReg)) {
|
||||||
|
regs.take(BaselineTailCallReg);
|
||||||
|
scratch = regs.takeAny();
|
||||||
|
regs.add(BaselineTailCallReg);
|
||||||
|
} else {
|
||||||
|
scratch = regs.takeAny();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Guard input is an object.
|
||||||
|
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
|
||||||
|
|
||||||
|
// Unbox and shape guard.
|
||||||
|
Register objReg = masm.extractObject(R0, ExtractTemp0);
|
||||||
|
masm.loadPtr(Address(BaselineStubReg, ICGetProp_CallNative::offsetOfShape()), scratch);
|
||||||
|
masm.branchTestObjShape(Assembler::NotEqual, objReg, scratch, &failure);
|
||||||
|
|
||||||
|
Register holderReg = regs.takeAny();
|
||||||
|
masm.loadPtr(Address(BaselineStubReg, ICGetProp_CallNative::offsetOfHolder()), holderReg);
|
||||||
|
masm.loadPtr(Address(BaselineStubReg, ICGetProp_CallNative::offsetOfHolderShape()), scratch);
|
||||||
|
masm.branchTestObjShape(Assembler::NotEqual, holderReg, scratch, &failure);
|
||||||
|
regs.add(holderReg);
|
||||||
|
|
||||||
|
// Push a stub frame so that we can perform a non-tail call.
|
||||||
|
enterStubFrame(masm, scratch);
|
||||||
|
|
||||||
|
// Load callee function.
|
||||||
|
Register callee = regs.takeAny();
|
||||||
|
masm.loadPtr(Address(BaselineStubReg, ICGetProp_CallNative::offsetOfGetter()), callee);
|
||||||
|
|
||||||
|
// Push args for vm call.
|
||||||
|
masm.push(objReg);
|
||||||
|
masm.push(callee);
|
||||||
|
|
||||||
|
// Don't to preserve R0 anymore.
|
||||||
|
regs.add(R0);
|
||||||
|
|
||||||
|
// If needed, update SPS Profiler frame entry.
|
||||||
|
{
|
||||||
|
Label skipProfilerUpdate;
|
||||||
|
Register scratch = regs.takeAny();
|
||||||
|
Register pcIdx = regs.takeAny();
|
||||||
|
|
||||||
|
// Check if profiling is enabled.
|
||||||
|
guardProfilingEnabled(masm, scratch, &skipProfilerUpdate);
|
||||||
|
|
||||||
|
// Update profiling entry before leaving function.
|
||||||
|
masm.load32(Address(BaselineStubReg, ICGetProp_CallNative::offsetOfPCOffset()), pcIdx);
|
||||||
|
masm.spsUpdatePCIdx(&cx->runtime->spsProfiler, pcIdx, scratch);
|
||||||
|
|
||||||
|
masm.bind(&skipProfilerUpdate);
|
||||||
|
regs.add(scratch);
|
||||||
|
regs.add(pcIdx);
|
||||||
|
}
|
||||||
|
if (!callVM(DoCallNativeGetterInfo, masm))
|
||||||
|
return false;
|
||||||
|
leaveStubFrame(masm);
|
||||||
|
|
||||||
|
// Enter type monitor IC to type-check result.
|
||||||
|
EmitEnterTypeMonitorIC(masm);
|
||||||
|
|
||||||
|
// Failure case - jump to next stub
|
||||||
|
masm.bind(&failure);
|
||||||
|
EmitStubGuardFailure(masm);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// SetProp_Fallback
|
// SetProp_Fallback
|
||||||
//
|
//
|
||||||
|
@ -5198,13 +5358,16 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsCacheableSetPropCallScripted(obj, holder, shape)) {
|
bool isScripted = false;
|
||||||
|
bool cacheableCall = IsCacheableSetPropCall(obj, holder, shape, &isScripted);
|
||||||
|
|
||||||
|
// Try handling scripted setters.
|
||||||
|
if (cacheableCall && isScripted) {
|
||||||
RootedFunction callee(cx, shape->setterObject()->toFunction());
|
RootedFunction callee(cx, shape->setterObject()->toFunction());
|
||||||
JS_ASSERT(obj != holder);
|
JS_ASSERT(obj != holder);
|
||||||
JS_ASSERT(callee->hasScript());
|
JS_ASSERT(callee->hasScript());
|
||||||
|
|
||||||
IonSpew(IonSpew_BaselineIC, " Generating SetProp(Native %s Setter %s:%d) stub",
|
IonSpew(IonSpew_BaselineIC, " Generating SetProp(NativeObj/ScriptedSetter %s:%d) stub",
|
||||||
(obj == holder) ? "direct" : "prototype",
|
|
||||||
callee->nonLazyScript()->filename(), callee->nonLazyScript()->lineno);
|
callee->nonLazyScript()->filename(), callee->nonLazyScript()->lineno);
|
||||||
|
|
||||||
ICSetProp_CallScripted::Compiler compiler(cx, obj, holder, callee, pc - script->code);
|
ICSetProp_CallScripted::Compiler compiler(cx, obj, holder, callee, pc - script->code);
|
||||||
|
@ -5217,6 +5380,25 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try handling JSNative setters.
|
||||||
|
if (cacheableCall && !isScripted) {
|
||||||
|
RootedFunction callee(cx, shape->setterObject()->toFunction());
|
||||||
|
JS_ASSERT(obj != holder);
|
||||||
|
JS_ASSERT(callee->isNative());
|
||||||
|
|
||||||
|
IonSpew(IonSpew_BaselineIC, " Generating SetProp(NativeObj/NativeSetter %p) stub",
|
||||||
|
callee->native());
|
||||||
|
|
||||||
|
ICSetProp_CallNative::Compiler compiler(cx, obj, holder, callee, pc - script->code);
|
||||||
|
ICStub *newStub = compiler.getStub(compiler.getStubSpace(script));
|
||||||
|
if (!newStub)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
stub->addNewStub(newStub);
|
||||||
|
*attached = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5587,6 +5769,110 @@ ICSetProp_CallScripted::Compiler::generateStubCode(MacroAssembler &masm)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
DoCallNativeSetter(JSContext *cx, HandleFunction callee, HandleObject obj, HandleValue val)
|
||||||
|
{
|
||||||
|
JS_ASSERT(callee->isNative());
|
||||||
|
JSNative natfun = callee->native();
|
||||||
|
|
||||||
|
Value vp[3] = { ObjectValue(*callee.get()), ObjectValue(*obj.get()), val };
|
||||||
|
AutoValueArray rootVp(cx, vp, 3);
|
||||||
|
|
||||||
|
return natfun(cx, 1, vp);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef bool (*DoCallNativeSetterFn)(JSContext *, HandleFunction, HandleObject, HandleValue);
|
||||||
|
static const VMFunction DoCallNativeSetterInfo =
|
||||||
|
FunctionInfo<DoCallNativeSetterFn>(DoCallNativeSetter);
|
||||||
|
|
||||||
|
bool
|
||||||
|
ICSetProp_CallNative::Compiler::generateStubCode(MacroAssembler &masm)
|
||||||
|
{
|
||||||
|
Label failure;
|
||||||
|
Label failureUnstow;
|
||||||
|
|
||||||
|
// Guard input is an object.
|
||||||
|
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
|
||||||
|
|
||||||
|
// Stow R0 and R1 to free up registers.
|
||||||
|
EmitStowICValues(masm, 2);
|
||||||
|
|
||||||
|
GeneralRegisterSet regs(availableGeneralRegs(1));
|
||||||
|
Register scratch;
|
||||||
|
if (regs.has(BaselineTailCallReg)) {
|
||||||
|
regs.take(BaselineTailCallReg);
|
||||||
|
scratch = regs.takeAny();
|
||||||
|
regs.add(BaselineTailCallReg);
|
||||||
|
} else {
|
||||||
|
scratch = regs.takeAny();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unbox and shape guard.
|
||||||
|
Register objReg = masm.extractObject(R0, ExtractTemp0);
|
||||||
|
masm.loadPtr(Address(BaselineStubReg, ICSetProp_CallNative::offsetOfShape()), scratch);
|
||||||
|
masm.branchTestObjShape(Assembler::NotEqual, objReg, scratch, &failureUnstow);
|
||||||
|
|
||||||
|
Register holderReg = regs.takeAny();
|
||||||
|
masm.loadPtr(Address(BaselineStubReg, ICSetProp_CallNative::offsetOfHolder()), holderReg);
|
||||||
|
masm.loadPtr(Address(BaselineStubReg, ICSetProp_CallNative::offsetOfHolderShape()), scratch);
|
||||||
|
masm.branchTestObjShape(Assembler::NotEqual, holderReg, scratch, &failureUnstow);
|
||||||
|
regs.add(holderReg);
|
||||||
|
|
||||||
|
// Push a stub frame so that we can perform a non-tail call.
|
||||||
|
enterStubFrame(masm, scratch);
|
||||||
|
|
||||||
|
// Load callee function and code. To ensure that |code| doesn't end up being
|
||||||
|
// ArgumentsRectifierReg, if it's available we assign it to |callee| instead.
|
||||||
|
Register callee = regs.takeAny();
|
||||||
|
masm.loadPtr(Address(BaselineStubReg, ICSetProp_CallNative::offsetOfSetter()), callee);
|
||||||
|
|
||||||
|
// To Push R1, read it off of the stowed values on stack.
|
||||||
|
// Stack: [ ..., R0, R1, ..STUBFRAME-HEADER.. ]
|
||||||
|
masm.movePtr(BaselineStackReg, scratch);
|
||||||
|
masm.pushValue(Address(scratch, STUB_FRAME_SIZE));
|
||||||
|
masm.push(objReg);
|
||||||
|
masm.push(callee);
|
||||||
|
|
||||||
|
// Don't need to preserve R0 anymore.
|
||||||
|
regs.add(R0);
|
||||||
|
|
||||||
|
// If needed, update SPS Profiler frame entry.
|
||||||
|
{
|
||||||
|
Label skipProfilerUpdate;
|
||||||
|
Register scratch = regs.takeAny();
|
||||||
|
Register pcIdx = regs.takeAny();
|
||||||
|
|
||||||
|
// Check if profiling is enabled.
|
||||||
|
guardProfilingEnabled(masm, scratch, &skipProfilerUpdate);
|
||||||
|
|
||||||
|
// Update profiling entry before leaving function.
|
||||||
|
masm.load32(Address(BaselineStubReg, ICSetProp_CallNative::offsetOfPCOffset()), pcIdx);
|
||||||
|
masm.spsUpdatePCIdx(&cx->runtime->spsProfiler, pcIdx, scratch);
|
||||||
|
|
||||||
|
masm.bind(&skipProfilerUpdate);
|
||||||
|
regs.add(scratch);
|
||||||
|
regs.add(pcIdx);
|
||||||
|
}
|
||||||
|
if (!callVM(DoCallNativeSetterInfo, masm))
|
||||||
|
return false;
|
||||||
|
leaveStubFrame(masm);
|
||||||
|
|
||||||
|
// Do not care about return value from function. The original RHS should be returned
|
||||||
|
// as the result of this operation.
|
||||||
|
EmitUnstowICValues(masm, 2);
|
||||||
|
masm.moveValue(R1, R0);
|
||||||
|
EmitReturnFromIC(masm);
|
||||||
|
|
||||||
|
// Unstow R0 and R1
|
||||||
|
masm.bind(&failureUnstow);
|
||||||
|
EmitUnstowICValues(masm, 2);
|
||||||
|
|
||||||
|
// Failure case - jump to next stub
|
||||||
|
masm.bind(&failure);
|
||||||
|
EmitStubGuardFailure(masm);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Call_Fallback
|
// Call_Fallback
|
||||||
//
|
//
|
||||||
|
|
|
@ -362,11 +362,13 @@ class ICEntry
|
||||||
_(GetProp_Native) \
|
_(GetProp_Native) \
|
||||||
_(GetProp_NativePrototype) \
|
_(GetProp_NativePrototype) \
|
||||||
_(GetProp_CallScripted) \
|
_(GetProp_CallScripted) \
|
||||||
|
_(GetProp_CallNative) \
|
||||||
\
|
\
|
||||||
_(SetProp_Fallback) \
|
_(SetProp_Fallback) \
|
||||||
_(SetProp_Native) \
|
_(SetProp_Native) \
|
||||||
_(SetProp_NativeAdd) \
|
_(SetProp_NativeAdd) \
|
||||||
_(SetProp_CallScripted) \
|
_(SetProp_CallScripted) \
|
||||||
|
_(SetProp_CallNative) \
|
||||||
\
|
\
|
||||||
_(TableSwitch) \
|
_(TableSwitch) \
|
||||||
\
|
\
|
||||||
|
@ -721,7 +723,9 @@ class ICStub
|
||||||
case Call_Fallback:
|
case Call_Fallback:
|
||||||
case UseCount_Fallback:
|
case UseCount_Fallback:
|
||||||
case GetProp_CallScripted:
|
case GetProp_CallScripted:
|
||||||
|
case GetProp_CallNative:
|
||||||
case SetProp_CallScripted:
|
case SetProp_CallScripted:
|
||||||
|
case SetProp_CallNative:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -4005,8 +4009,8 @@ class ICGetPropNativeCompiler : public ICStubCompiler
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Stub for calling a scripted getter on a native object.
|
// Stub for calling a getter (native or scripted) on a native object.
|
||||||
class ICGetProp_CallScripted : public ICMonitoredStub
|
class ICGetPropCallGetter : public ICMonitoredStub
|
||||||
{
|
{
|
||||||
friend class ICStubSpace;
|
friend class ICStubSpace;
|
||||||
|
|
||||||
|
@ -4024,15 +4028,83 @@ class ICGetProp_CallScripted : public ICMonitoredStub
|
||||||
// PC offset of call
|
// PC offset of call
|
||||||
uint32_t pcOffset_;
|
uint32_t pcOffset_;
|
||||||
|
|
||||||
ICGetProp_CallScripted(IonCode *stubCode, ICStub *firstMonitorStub,
|
ICGetPropCallGetter(Kind kind, IonCode *stubCode, ICStub *firstMonitorStub,
|
||||||
HandleShape shape, HandleObject holder, HandleShape holderShape,
|
HandleShape shape, HandleObject holder, HandleShape holderShape,
|
||||||
HandleFunction getter, uint32_t pcOffset)
|
HandleFunction getter, uint32_t pcOffset)
|
||||||
: ICMonitoredStub(GetProp_CallScripted, stubCode, firstMonitorStub),
|
: ICMonitoredStub(kind, stubCode, firstMonitorStub),
|
||||||
shape_(shape),
|
shape_(shape),
|
||||||
holder_(holder),
|
holder_(holder),
|
||||||
holderShape_(holderShape),
|
holderShape_(holderShape),
|
||||||
getter_(getter),
|
getter_(getter),
|
||||||
pcOffset_(pcOffset)
|
pcOffset_(pcOffset)
|
||||||
|
{
|
||||||
|
JS_ASSERT(kind == ICStub::GetProp_CallScripted || kind == ICStub::GetProp_CallNative);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
HeapPtrShape &shape() {
|
||||||
|
return shape_;
|
||||||
|
}
|
||||||
|
HeapPtrObject &holder() {
|
||||||
|
return holder_;
|
||||||
|
}
|
||||||
|
HeapPtrShape &holderShape() {
|
||||||
|
return holderShape_;
|
||||||
|
}
|
||||||
|
HeapPtrFunction &getter() {
|
||||||
|
return getter_;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t offsetOfShape() {
|
||||||
|
return offsetof(ICGetPropCallGetter, shape_);
|
||||||
|
}
|
||||||
|
static size_t offsetOfHolder() {
|
||||||
|
return offsetof(ICGetPropCallGetter, holder_);
|
||||||
|
}
|
||||||
|
static size_t offsetOfHolderShape() {
|
||||||
|
return offsetof(ICGetPropCallGetter, holderShape_);
|
||||||
|
}
|
||||||
|
static size_t offsetOfGetter() {
|
||||||
|
return offsetof(ICGetPropCallGetter, getter_);
|
||||||
|
}
|
||||||
|
static size_t offsetOfPCOffset() {
|
||||||
|
return offsetof(ICGetPropCallGetter, pcOffset_);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Compiler : public ICStubCompiler {
|
||||||
|
protected:
|
||||||
|
ICStub *firstMonitorStub_;
|
||||||
|
RootedObject obj_;
|
||||||
|
RootedObject holder_;
|
||||||
|
RootedFunction getter_;
|
||||||
|
uint32_t pcOffset_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Compiler(JSContext *cx, ICStub::Kind kind, ICStub *firstMonitorStub, HandleObject obj,
|
||||||
|
HandleObject holder, HandleFunction getter, uint32_t pcOffset)
|
||||||
|
: ICStubCompiler(cx, kind),
|
||||||
|
firstMonitorStub_(firstMonitorStub),
|
||||||
|
obj_(cx, obj),
|
||||||
|
holder_(cx, holder),
|
||||||
|
getter_(cx, getter),
|
||||||
|
pcOffset_(pcOffset)
|
||||||
|
{
|
||||||
|
JS_ASSERT(kind == ICStub::GetProp_CallScripted || kind == ICStub::GetProp_CallNative);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Stub for calling a scripted getter on a native object.
|
||||||
|
class ICGetProp_CallScripted : public ICGetPropCallGetter
|
||||||
|
{
|
||||||
|
friend class ICStubSpace;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ICGetProp_CallScripted(IonCode *stubCode, ICStub *firstMonitorStub,
|
||||||
|
HandleShape shape, HandleObject holder, HandleShape holderShape,
|
||||||
|
HandleFunction getter, uint32_t pcOffset)
|
||||||
|
: ICGetPropCallGetter(GetProp_CallScripted, stubCode, firstMonitorStub,
|
||||||
|
shape, holder, holderShape, getter, pcOffset)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -4048,53 +4120,15 @@ class ICGetProp_CallScripted : public ICMonitoredStub
|
||||||
pcOffset);
|
pcOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapPtrShape &shape() {
|
class Compiler : public ICGetPropCallGetter::Compiler {
|
||||||
return shape_;
|
protected:
|
||||||
}
|
|
||||||
HeapPtrObject &holder() {
|
|
||||||
return holder_;
|
|
||||||
}
|
|
||||||
HeapPtrShape &holderShape() {
|
|
||||||
return holderShape_;
|
|
||||||
}
|
|
||||||
HeapPtrFunction &getter() {
|
|
||||||
return getter_;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t offsetOfShape() {
|
|
||||||
return offsetof(ICGetProp_CallScripted, shape_);
|
|
||||||
}
|
|
||||||
static size_t offsetOfHolder() {
|
|
||||||
return offsetof(ICGetProp_CallScripted, holder_);
|
|
||||||
}
|
|
||||||
static size_t offsetOfHolderShape() {
|
|
||||||
return offsetof(ICGetProp_CallScripted, holderShape_);
|
|
||||||
}
|
|
||||||
static size_t offsetOfGetter() {
|
|
||||||
return offsetof(ICGetProp_CallScripted, getter_);
|
|
||||||
}
|
|
||||||
static size_t offsetOfPCOffset() {
|
|
||||||
return offsetof(ICGetProp_CallScripted, pcOffset_);
|
|
||||||
}
|
|
||||||
|
|
||||||
class Compiler : public ICStubCompiler {
|
|
||||||
ICStub *firstMonitorStub_;
|
|
||||||
RootedObject obj_;
|
|
||||||
RootedObject holder_;
|
|
||||||
RootedFunction getter_;
|
|
||||||
uint32_t pcOffset_;
|
|
||||||
|
|
||||||
bool generateStubCode(MacroAssembler &masm);
|
bool generateStubCode(MacroAssembler &masm);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Compiler(JSContext *cx, ICStub *firstMonitorStub, HandleObject obj,
|
Compiler(JSContext *cx, ICStub *firstMonitorStub, HandleObject obj,
|
||||||
HandleObject holder, HandleFunction getter, uint32_t pcOffset)
|
HandleObject holder, HandleFunction getter, uint32_t pcOffset)
|
||||||
: ICStubCompiler(cx, ICStub::GetProp_CallScripted),
|
: ICGetPropCallGetter::Compiler(cx, ICStub::GetProp_CallScripted, firstMonitorStub,
|
||||||
firstMonitorStub_(firstMonitorStub),
|
obj, holder, getter, pcOffset)
|
||||||
obj_(cx, obj),
|
|
||||||
holder_(cx, holder),
|
|
||||||
getter_(cx, getter),
|
|
||||||
pcOffset_(pcOffset)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
ICStub *getStub(ICStubSpace *space) {
|
ICStub *getStub(ICStubSpace *space) {
|
||||||
|
@ -4106,6 +4140,52 @@ class ICGetProp_CallScripted : public ICMonitoredStub
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Stub for calling a native getter on a native object.
|
||||||
|
class ICGetProp_CallNative : public ICGetPropCallGetter
|
||||||
|
{
|
||||||
|
friend class ICStubSpace;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ICGetProp_CallNative(IonCode *stubCode, ICStub *firstMonitorStub,
|
||||||
|
HandleShape shape, HandleObject holder, HandleShape holderShape,
|
||||||
|
HandleFunction getter, uint32_t pcOffset)
|
||||||
|
: ICGetPropCallGetter(GetProp_CallNative, stubCode, firstMonitorStub,
|
||||||
|
shape, holder, holderShape, getter, pcOffset)
|
||||||
|
{}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static inline ICGetProp_CallNative *New(
|
||||||
|
ICStubSpace *space, IonCode *code, ICStub *firstMonitorStub,
|
||||||
|
HandleShape shape, HandleObject holder, HandleShape holderShape,
|
||||||
|
HandleFunction getter, uint32_t pcOffset)
|
||||||
|
{
|
||||||
|
if (!code)
|
||||||
|
return NULL;
|
||||||
|
return space->allocate<ICGetProp_CallNative>(code, firstMonitorStub,
|
||||||
|
shape, holder, holderShape, getter,
|
||||||
|
pcOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Compiler : public ICGetPropCallGetter::Compiler {
|
||||||
|
protected:
|
||||||
|
bool generateStubCode(MacroAssembler &masm);
|
||||||
|
|
||||||
|
public:
|
||||||
|
Compiler(JSContext *cx, ICStub *firstMonitorStub, HandleObject obj,
|
||||||
|
HandleObject holder, HandleFunction getter, uint32_t pcOffset)
|
||||||
|
: ICGetPropCallGetter::Compiler(cx, ICStub::GetProp_CallNative, firstMonitorStub,
|
||||||
|
obj, holder, getter, pcOffset)
|
||||||
|
{}
|
||||||
|
|
||||||
|
ICStub *getStub(ICStubSpace *space) {
|
||||||
|
RootedShape shape(cx, obj_->lastProperty());
|
||||||
|
RootedShape holderShape(cx, holder_->lastProperty());
|
||||||
|
return ICGetProp_CallNative::New(space, getStubCode(), firstMonitorStub_, shape,
|
||||||
|
holder_, holderShape, getter_, pcOffset_);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// SetProp
|
// SetProp
|
||||||
// JSOP_SETPROP
|
// JSOP_SETPROP
|
||||||
// JSOP_SETNAME
|
// JSOP_SETNAME
|
||||||
|
@ -4356,8 +4436,8 @@ class ICSetPropNativeAddCompiler : public ICStubCompiler {
|
||||||
ICUpdatedStub *getStub(ICStubSpace *space);
|
ICUpdatedStub *getStub(ICStubSpace *space);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Stub for calling a scripted setter on a native object.
|
// Base stub for calling a setters on a native object.
|
||||||
class ICSetProp_CallScripted : public ICStub
|
class ICSetPropCallSetter : public ICStub
|
||||||
{
|
{
|
||||||
friend class ICStubSpace;
|
friend class ICStubSpace;
|
||||||
|
|
||||||
|
@ -4375,28 +4455,19 @@ class ICSetProp_CallScripted : public ICStub
|
||||||
// PC of call, for profiler
|
// PC of call, for profiler
|
||||||
uint32_t pcOffset_;
|
uint32_t pcOffset_;
|
||||||
|
|
||||||
ICSetProp_CallScripted(IonCode *stubCode, HandleShape shape, HandleObject holder,
|
ICSetPropCallSetter(Kind kind, IonCode *stubCode, HandleShape shape, HandleObject holder,
|
||||||
HandleShape holderShape, HandleFunction setter, uint32_t pcOffset)
|
HandleShape holderShape, HandleFunction setter, uint32_t pcOffset)
|
||||||
: ICStub(SetProp_CallScripted, stubCode),
|
: ICStub(kind, stubCode),
|
||||||
shape_(shape),
|
shape_(shape),
|
||||||
holder_(holder),
|
holder_(holder),
|
||||||
holderShape_(holderShape),
|
holderShape_(holderShape),
|
||||||
setter_(setter),
|
setter_(setter),
|
||||||
pcOffset_(pcOffset)
|
pcOffset_(pcOffset)
|
||||||
{}
|
|
||||||
|
|
||||||
public:
|
|
||||||
static inline ICSetProp_CallScripted *New(ICStubSpace *space, IonCode *code,
|
|
||||||
HandleShape shape, HandleObject holder,
|
|
||||||
HandleShape holderShape, HandleFunction setter,
|
|
||||||
uint32_t pcOffset)
|
|
||||||
{
|
{
|
||||||
if (!code)
|
JS_ASSERT(kind == ICStub::SetProp_CallScripted || kind == ICStub::SetProp_CallNative);
|
||||||
return NULL;
|
|
||||||
return space->allocate<ICSetProp_CallScripted>(code, shape, holder, holderShape, setter,
|
|
||||||
pcOffset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
HeapPtrShape &shape() {
|
HeapPtrShape &shape() {
|
||||||
return shape_;
|
return shape_;
|
||||||
}
|
}
|
||||||
|
@ -4411,37 +4482,75 @@ class ICSetProp_CallScripted : public ICStub
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t offsetOfShape() {
|
static size_t offsetOfShape() {
|
||||||
return offsetof(ICSetProp_CallScripted, shape_);
|
return offsetof(ICSetPropCallSetter, shape_);
|
||||||
}
|
}
|
||||||
static size_t offsetOfHolder() {
|
static size_t offsetOfHolder() {
|
||||||
return offsetof(ICSetProp_CallScripted, holder_);
|
return offsetof(ICSetPropCallSetter, holder_);
|
||||||
}
|
}
|
||||||
static size_t offsetOfHolderShape() {
|
static size_t offsetOfHolderShape() {
|
||||||
return offsetof(ICSetProp_CallScripted, holderShape_);
|
return offsetof(ICSetPropCallSetter, holderShape_);
|
||||||
}
|
}
|
||||||
static size_t offsetOfSetter() {
|
static size_t offsetOfSetter() {
|
||||||
return offsetof(ICSetProp_CallScripted, setter_);
|
return offsetof(ICSetPropCallSetter, setter_);
|
||||||
}
|
}
|
||||||
static size_t offsetOfPCOffset() {
|
static size_t offsetOfPCOffset() {
|
||||||
return offsetof(ICSetProp_CallScripted, pcOffset_);
|
return offsetof(ICSetPropCallSetter, pcOffset_);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Compiler : public ICStubCompiler {
|
class Compiler : public ICStubCompiler {
|
||||||
|
protected:
|
||||||
RootedObject obj_;
|
RootedObject obj_;
|
||||||
RootedObject holder_;
|
RootedObject holder_;
|
||||||
RootedFunction setter_;
|
RootedFunction setter_;
|
||||||
uint32_t pcOffset_;
|
uint32_t pcOffset_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Compiler(JSContext *cx, ICStub::Kind kind, HandleObject obj, HandleObject holder,
|
||||||
|
HandleFunction setter, uint32_t pcOffset)
|
||||||
|
: ICStubCompiler(cx, kind),
|
||||||
|
obj_(cx, obj),
|
||||||
|
holder_(cx, holder),
|
||||||
|
setter_(cx, setter),
|
||||||
|
pcOffset_(pcOffset)
|
||||||
|
{
|
||||||
|
JS_ASSERT(kind == ICStub::SetProp_CallScripted || kind == ICStub::SetProp_CallNative);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Stub for calling a scripted setter on a native object.
|
||||||
|
class ICSetProp_CallScripted : public ICSetPropCallSetter
|
||||||
|
{
|
||||||
|
friend class ICStubSpace;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ICSetProp_CallScripted(IonCode *stubCode, HandleShape shape, HandleObject holder,
|
||||||
|
HandleShape holderShape, HandleFunction setter, uint32_t pcOffset)
|
||||||
|
: ICSetPropCallSetter(SetProp_CallScripted, stubCode, shape, holder, holderShape,
|
||||||
|
setter, pcOffset)
|
||||||
|
{}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static inline ICSetProp_CallScripted *New(ICStubSpace *space, IonCode *code,
|
||||||
|
HandleShape shape, HandleObject holder,
|
||||||
|
HandleShape holderShape, HandleFunction setter,
|
||||||
|
uint32_t pcOffset)
|
||||||
|
{
|
||||||
|
if (!code)
|
||||||
|
return NULL;
|
||||||
|
return space->allocate<ICSetProp_CallScripted>(code, shape, holder, holderShape, setter,
|
||||||
|
pcOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Compiler : public ICSetPropCallSetter::Compiler {
|
||||||
|
protected:
|
||||||
bool generateStubCode(MacroAssembler &masm);
|
bool generateStubCode(MacroAssembler &masm);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Compiler(JSContext *cx, HandleObject obj, HandleObject holder, HandleFunction setter,
|
Compiler(JSContext *cx, HandleObject obj, HandleObject holder, HandleFunction setter,
|
||||||
uint32_t pcOffset)
|
uint32_t pcOffset)
|
||||||
: ICStubCompiler(cx, ICStub::SetProp_CallScripted),
|
: ICSetPropCallSetter::Compiler(cx, ICStub::SetProp_CallScripted,
|
||||||
obj_(cx, obj),
|
obj, holder, setter, pcOffset)
|
||||||
holder_(cx, holder),
|
|
||||||
setter_(cx, setter),
|
|
||||||
pcOffset_(pcOffset)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
ICStub *getStub(ICStubSpace *space) {
|
ICStub *getStub(ICStubSpace *space) {
|
||||||
|
@ -4453,6 +4562,50 @@ class ICSetProp_CallScripted : public ICStub
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Stub for calling a native setter on a native object.
|
||||||
|
class ICSetProp_CallNative : public ICSetPropCallSetter
|
||||||
|
{
|
||||||
|
friend class ICStubSpace;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ICSetProp_CallNative(IonCode *stubCode, HandleShape shape, HandleObject holder,
|
||||||
|
HandleShape holderShape, HandleFunction setter, uint32_t pcOffset)
|
||||||
|
: ICSetPropCallSetter(SetProp_CallNative, stubCode, shape, holder, holderShape,
|
||||||
|
setter, pcOffset)
|
||||||
|
{}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static inline ICSetProp_CallNative *New(ICStubSpace *space, IonCode *code,
|
||||||
|
HandleShape shape, HandleObject holder,
|
||||||
|
HandleShape holderShape, HandleFunction setter,
|
||||||
|
uint32_t pcOffset)
|
||||||
|
{
|
||||||
|
if (!code)
|
||||||
|
return NULL;
|
||||||
|
return space->allocate<ICSetProp_CallNative>(code, shape, holder, holderShape, setter,
|
||||||
|
pcOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Compiler : public ICSetPropCallSetter::Compiler {
|
||||||
|
protected:
|
||||||
|
bool generateStubCode(MacroAssembler &masm);
|
||||||
|
|
||||||
|
public:
|
||||||
|
Compiler(JSContext *cx, HandleObject obj, HandleObject holder, HandleFunction setter,
|
||||||
|
uint32_t pcOffset)
|
||||||
|
: ICSetPropCallSetter::Compiler(cx, ICStub::SetProp_CallNative,
|
||||||
|
obj, holder, setter, pcOffset)
|
||||||
|
{}
|
||||||
|
|
||||||
|
ICStub *getStub(ICStubSpace *space) {
|
||||||
|
RootedShape shape(cx, obj_->lastProperty());
|
||||||
|
RootedShape holderShape(cx, holder_->lastProperty());
|
||||||
|
return ICSetProp_CallNative::New(space, getStubCode(), shape, holder_, holderShape,
|
||||||
|
setter_, pcOffset_);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// Call
|
// Call
|
||||||
// JSOP_CALL
|
// JSOP_CALL
|
||||||
// JSOP_FUNAPPLY
|
// JSOP_FUNAPPLY
|
||||||
|
|
Загрузка…
Ссылка в новой задаче