зеркало из 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");
|
||||
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: {
|
||||
ICSetProp_Native *propStub = toSetProp_Native();
|
||||
MarkShape(trc, &propStub->shape(), "baseline-setpropnative-stub-shape");
|
||||
|
@ -339,6 +347,14 @@ ICStub::trace(JSTracer *trc)
|
|||
MarkObject(trc, &callStub->setter(), "baseline-setpropcallscripted-stub-setter");
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
@ -572,14 +588,15 @@ ICStubCompiler::leaveStubFrame(MacroAssembler &masm, bool calledIntoIon)
|
|||
JS_ASSERT(entersStubFrame_);
|
||||
EmitLeaveStubFrame(masm, calledIntoIon);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ICStubCompiler::guardProfilingEnabled(MacroAssembler &masm, Register scratch, Label *skip)
|
||||
{
|
||||
// This should only be called from the following stubs.
|
||||
JS_ASSERT(kind == ICStub::Call_Scripted || kind == ICStub::Call_AnyScripted ||
|
||||
kind == ICStub::Call_Native || kind == ICStub::GetProp_CallScripted ||
|
||||
kind == ICStub::SetProp_CallScripted);
|
||||
JS_ASSERT(kind == ICStub::Call_Scripted || kind == ICStub::Call_AnyScripted ||
|
||||
kind == ICStub::Call_Native || kind == ICStub::GetProp_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
|
||||
// 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
|
||||
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.
|
||||
if (obj == holder)
|
||||
return false;
|
||||
|
@ -3043,15 +3062,27 @@ IsCacheableGetPropCallScripted(JSObject *obj, JSObject *holder, Shape *shape)
|
|||
if (shape->hasSlot() || shape->hasDefaultGetter())
|
||||
return false;
|
||||
|
||||
if (!shape->hasGetterValue() || !shape->getterObject()->isFunction())
|
||||
if (!shape->hasGetterValue())
|
||||
return false;
|
||||
|
||||
if (!shape->getterValue().isObject() || !shape->getterObject()->isFunction())
|
||||
return false;
|
||||
|
||||
JSFunction *func = shape->getterObject()->toFunction();
|
||||
if (func->isNative()) {
|
||||
*isScripted = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!func->hasScript())
|
||||
return false;
|
||||
|
||||
JSScript *script = func->nonLazyScript();
|
||||
return script->hasIonScript() || script->hasBaselineScript();
|
||||
if (!script->hasIonScript() && !script->hasBaselineScript())
|
||||
return false;
|
||||
|
||||
*isScripted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -3132,8 +3163,10 @@ IsCacheableSetPropAddSlot(JSContext *cx, HandleObject obj, HandleShape oldShape,
|
|||
}
|
||||
|
||||
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.
|
||||
if (obj == holder)
|
||||
return false;
|
||||
|
@ -3144,15 +3177,27 @@ IsCacheableSetPropCallScripted(JSObject *obj, JSObject *holder, Shape *shape)
|
|||
if (shape->hasSlot() || shape->hasDefaultSetter())
|
||||
return false;
|
||||
|
||||
if (!shape->hasSetterValue() || !shape->setterObject()->isFunction())
|
||||
if (!shape->hasSetterValue())
|
||||
return false;
|
||||
|
||||
if (!shape->setterValue().isObject() || !shape->setterObject()->isFunction())
|
||||
return false;
|
||||
|
||||
JSFunction *func = shape->setterObject()->toFunction();
|
||||
if (func->isNative()) {
|
||||
*isScripted = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!func->hasScript())
|
||||
return false;
|
||||
|
||||
JSScript *script = func->nonLazyScript();
|
||||
return script->hasIonScript() || script->hasBaselineScript();
|
||||
if (!script->hasIonScript() && !script->hasBaselineScript())
|
||||
return false;
|
||||
|
||||
*isScripted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -4711,14 +4756,16 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
|||
return true;
|
||||
}
|
||||
|
||||
// Only handle CallGetter stubs on prototypes for now, not direct getters.
|
||||
if (IsCacheableGetPropCallScripted(obj, holder, shape)) {
|
||||
bool isScripted = false;
|
||||
bool cacheableCall = IsCacheableGetPropCall(obj, holder, shape, &isScripted);
|
||||
|
||||
// Try handling scripted getters.
|
||||
if (cacheableCall && isScripted) {
|
||||
RootedFunction callee(cx, shape->getterObject()->toFunction());
|
||||
JS_ASSERT(obj != holder);
|
||||
JS_ASSERT(callee->hasScript());
|
||||
|
||||
IonSpew(IonSpew_BaselineIC, " Generating GetProp(Native %s Getter %s:%d) stub",
|
||||
(obj == holder) ? "direct" : "prototype",
|
||||
IonSpew(IonSpew_BaselineIC, " Generating GetProp(NativeObj/ScriptedGetter %s:%d) stub",
|
||||
callee->nonLazyScript()->filename(), callee->nonLazyScript()->lineno);
|
||||
|
||||
ICGetProp_CallScripted::Compiler compiler(cx, monitorStub, obj, holder, callee,
|
||||
|
@ -4732,6 +4779,26 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -5137,6 +5204,99 @@ ICGetProp_CallScripted::Compiler::generateStubCode(MacroAssembler &masm)
|
|||
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
|
||||
//
|
||||
|
@ -5198,13 +5358,16 @@ TryAttachSetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc, ICSetPr
|
|||
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());
|
||||
JS_ASSERT(obj != holder);
|
||||
JS_ASSERT(callee->hasScript());
|
||||
|
||||
IonSpew(IonSpew_BaselineIC, " Generating SetProp(Native %s Setter %s:%d) stub",
|
||||
(obj == holder) ? "direct" : "prototype",
|
||||
IonSpew(IonSpew_BaselineIC, " Generating SetProp(NativeObj/ScriptedSetter %s:%d) stub",
|
||||
callee->nonLazyScript()->filename(), callee->nonLazyScript()->lineno);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -5587,6 +5769,110 @@ ICSetProp_CallScripted::Compiler::generateStubCode(MacroAssembler &masm)
|
|||
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
|
||||
//
|
||||
|
@ -5631,7 +5917,7 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
|
|||
|
||||
if (stub->scriptedStubCount() >= ICCall_Fallback::MAX_SCRIPTED_STUBS) {
|
||||
// Create a Call_AnyScripted stub.
|
||||
IonSpew(IonSpew_BaselineIC, " Generating Call_AnyScripted stub (cons=%s)",
|
||||
IonSpew(IonSpew_BaselineIC, " Generating Call_AnyScripted stub (cons=%s)",
|
||||
constructing ? "yes" : "no");
|
||||
|
||||
ICCallScriptedCompiler compiler(cx, stub->fallbackMonitorStub()->firstMonitorStub(),
|
||||
|
|
|
@ -362,11 +362,13 @@ class ICEntry
|
|||
_(GetProp_Native) \
|
||||
_(GetProp_NativePrototype) \
|
||||
_(GetProp_CallScripted) \
|
||||
_(GetProp_CallNative) \
|
||||
\
|
||||
_(SetProp_Fallback) \
|
||||
_(SetProp_Native) \
|
||||
_(SetProp_NativeAdd) \
|
||||
_(SetProp_CallScripted) \
|
||||
_(SetProp_CallNative) \
|
||||
\
|
||||
_(TableSwitch) \
|
||||
\
|
||||
|
@ -721,7 +723,9 @@ class ICStub
|
|||
case Call_Fallback:
|
||||
case UseCount_Fallback:
|
||||
case GetProp_CallScripted:
|
||||
case GetProp_CallNative:
|
||||
case SetProp_CallScripted:
|
||||
case SetProp_CallNative:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -4005,8 +4009,8 @@ class ICGetPropNativeCompiler : public ICStubCompiler
|
|||
}
|
||||
};
|
||||
|
||||
// Stub for calling a scripted getter on a native object.
|
||||
class ICGetProp_CallScripted : public ICMonitoredStub
|
||||
// Stub for calling a getter (native or scripted) on a native object.
|
||||
class ICGetPropCallGetter : public ICMonitoredStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
|
@ -4024,15 +4028,83 @@ class ICGetProp_CallScripted : public ICMonitoredStub
|
|||
// PC offset of call
|
||||
uint32_t pcOffset_;
|
||||
|
||||
ICGetProp_CallScripted(IonCode *stubCode, ICStub *firstMonitorStub,
|
||||
HandleShape shape, HandleObject holder, HandleShape holderShape,
|
||||
HandleFunction getter, uint32_t pcOffset)
|
||||
: ICMonitoredStub(GetProp_CallScripted, stubCode, firstMonitorStub),
|
||||
ICGetPropCallGetter(Kind kind, IonCode *stubCode, ICStub *firstMonitorStub,
|
||||
HandleShape shape, HandleObject holder, HandleShape holderShape,
|
||||
HandleFunction getter, uint32_t pcOffset)
|
||||
: ICMonitoredStub(kind, stubCode, firstMonitorStub),
|
||||
shape_(shape),
|
||||
holder_(holder),
|
||||
holderShape_(holderShape),
|
||||
getter_(getter),
|
||||
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:
|
||||
|
@ -4048,60 +4120,68 @@ class ICGetProp_CallScripted : public ICMonitoredStub
|
|||
pcOffset);
|
||||
}
|
||||
|
||||
HeapPtrShape &shape() {
|
||||
return shape_;
|
||||
}
|
||||
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_;
|
||||
|
||||
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)
|
||||
: ICStubCompiler(cx, ICStub::GetProp_CallScripted),
|
||||
firstMonitorStub_(firstMonitorStub),
|
||||
obj_(cx, obj),
|
||||
holder_(cx, holder),
|
||||
getter_(cx, getter),
|
||||
pcOffset_(pcOffset)
|
||||
: ICGetPropCallGetter::Compiler(cx, ICStub::GetProp_CallScripted, firstMonitorStub,
|
||||
obj, holder, getter, pcOffset)
|
||||
{}
|
||||
|
||||
ICStub *getStub(ICStubSpace *space) {
|
||||
RootedShape shape(cx, obj_->lastProperty());
|
||||
RootedShape holderShape(cx, holder_->lastProperty());
|
||||
return ICGetProp_CallScripted::New(space, getStubCode(), firstMonitorStub_, shape,
|
||||
holder_, holderShape, getter_, pcOffset_);
|
||||
holder_, holderShape, getter_, pcOffset_);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// 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_);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -4356,8 +4436,8 @@ class ICSetPropNativeAddCompiler : public ICStubCompiler {
|
|||
ICUpdatedStub *getStub(ICStubSpace *space);
|
||||
};
|
||||
|
||||
// Stub for calling a scripted setter on a native object.
|
||||
class ICSetProp_CallScripted : public ICStub
|
||||
// Base stub for calling a setters on a native object.
|
||||
class ICSetPropCallSetter : public ICStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
|
@ -4375,28 +4455,19 @@ class ICSetProp_CallScripted : public ICStub
|
|||
// PC of call, for profiler
|
||||
uint32_t pcOffset_;
|
||||
|
||||
ICSetProp_CallScripted(IonCode *stubCode, HandleShape shape, HandleObject holder,
|
||||
HandleShape holderShape, HandleFunction setter, uint32_t pcOffset)
|
||||
: ICStub(SetProp_CallScripted, stubCode),
|
||||
ICSetPropCallSetter(Kind kind, IonCode *stubCode, HandleShape shape, HandleObject holder,
|
||||
HandleShape holderShape, HandleFunction setter, uint32_t pcOffset)
|
||||
: ICStub(kind, stubCode),
|
||||
shape_(shape),
|
||||
holder_(holder),
|
||||
holderShape_(holderShape),
|
||||
setter_(setter),
|
||||
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)
|
||||
return NULL;
|
||||
return space->allocate<ICSetProp_CallScripted>(code, shape, holder, holderShape, setter,
|
||||
pcOffset);
|
||||
JS_ASSERT(kind == ICStub::SetProp_CallScripted || kind == ICStub::SetProp_CallNative);
|
||||
}
|
||||
|
||||
public:
|
||||
HeapPtrShape &shape() {
|
||||
return shape_;
|
||||
}
|
||||
|
@ -4411,44 +4482,126 @@ class ICSetProp_CallScripted : public ICStub
|
|||
}
|
||||
|
||||
static size_t offsetOfShape() {
|
||||
return offsetof(ICSetProp_CallScripted, shape_);
|
||||
return offsetof(ICSetPropCallSetter, shape_);
|
||||
}
|
||||
static size_t offsetOfHolder() {
|
||||
return offsetof(ICSetProp_CallScripted, holder_);
|
||||
return offsetof(ICSetPropCallSetter, holder_);
|
||||
}
|
||||
static size_t offsetOfHolderShape() {
|
||||
return offsetof(ICSetProp_CallScripted, holderShape_);
|
||||
return offsetof(ICSetPropCallSetter, holderShape_);
|
||||
}
|
||||
static size_t offsetOfSetter() {
|
||||
return offsetof(ICSetProp_CallScripted, setter_);
|
||||
return offsetof(ICSetPropCallSetter, setter_);
|
||||
}
|
||||
static size_t offsetOfPCOffset() {
|
||||
return offsetof(ICSetProp_CallScripted, pcOffset_);
|
||||
return offsetof(ICSetPropCallSetter, pcOffset_);
|
||||
}
|
||||
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
RootedObject obj_;
|
||||
RootedObject holder_;
|
||||
RootedFunction setter_;
|
||||
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);
|
||||
|
||||
public:
|
||||
Compiler(JSContext *cx, HandleObject obj, HandleObject holder, HandleFunction setter,
|
||||
uint32_t pcOffset)
|
||||
: ICStubCompiler(cx, ICStub::SetProp_CallScripted),
|
||||
obj_(cx, obj),
|
||||
holder_(cx, holder),
|
||||
setter_(cx, setter),
|
||||
pcOffset_(pcOffset)
|
||||
: ICSetPropCallSetter::Compiler(cx, ICStub::SetProp_CallScripted,
|
||||
obj, holder, setter, pcOffset)
|
||||
{}
|
||||
|
||||
ICStub *getStub(ICStubSpace *space) {
|
||||
RootedShape shape(cx, obj_->lastProperty());
|
||||
RootedShape holderShape(cx, holder_->lastProperty());
|
||||
return ICSetProp_CallScripted::New(space, getStubCode(), shape, holder_, holderShape,
|
||||
setter_, pcOffset_);
|
||||
setter_, pcOffset_);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// 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_);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче