mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 765454 - IonMonkey: Inline common scripted accessors. (r=djvj,jandem)
This commit is contained in:
parent
0018137a74
commit
bedf8a05fc
@ -367,6 +367,25 @@ struct BaselineStackBuilder
|
||||
}
|
||||
};
|
||||
|
||||
static inline bool
|
||||
IsInlinableFallback(ICFallbackStub *icEntry)
|
||||
{
|
||||
return icEntry->isCall_Fallback() || icEntry->isGetProp_Fallback() ||
|
||||
icEntry->isSetProp_Fallback();
|
||||
}
|
||||
|
||||
static inline void*
|
||||
GetStubReturnAddress(JSContext *cx, jsbytecode *pc)
|
||||
{
|
||||
if (IsGetterPC(pc))
|
||||
return cx->compartment()->ionCompartment()->baselineGetPropReturnAddr();
|
||||
if (IsSetterPC(pc))
|
||||
return cx->compartment()->ionCompartment()->baselineSetPropReturnAddr();
|
||||
// This should be a call op of some kind, now.
|
||||
JS_ASSERT(js_CodeSpec[JSOp(*pc)].format & JOF_INVOKE);
|
||||
return cx->compartment()->ionCompartment()->baselineCallReturnAddr();
|
||||
}
|
||||
|
||||
// For every inline frame, we write out the following data:
|
||||
//
|
||||
// | ... |
|
||||
@ -626,18 +645,20 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
||||
JSOp op = JSOp(*pc);
|
||||
bool resumeAfter = iter.resumeAfter();
|
||||
|
||||
// Fixup inlined JSOP_FUNCALL and JSOP_FUNAPPLY on the caller side.
|
||||
// Fixup inlined JSOP_FUNCALL, JSOP_FUNAPPLY, and accessors on the caller side.
|
||||
// On the caller side this must represent like the function wasn't inlined.
|
||||
uint32_t pushedSlots = 0;
|
||||
AutoValueVector funapplyargs(cx);
|
||||
if (iter.moreFrames() &&
|
||||
(op == JSOP_FUNCALL || op == JSOP_FUNAPPLY))
|
||||
AutoValueVector savedCallerArgs(cx);
|
||||
bool needToSaveArgs = op == JSOP_FUNAPPLY || IsGetterPC(pc) || IsSetterPC(pc);
|
||||
if (iter.moreFrames() && (op == JSOP_FUNCALL || needToSaveArgs))
|
||||
{
|
||||
uint32_t inlined_args = 0;
|
||||
if (op == JSOP_FUNCALL)
|
||||
inlined_args = 2 + GET_ARGC(pc) - 1;
|
||||
else
|
||||
else if (op == JSOP_FUNAPPLY)
|
||||
inlined_args = 2 + blFrame->numActualArgs();
|
||||
else
|
||||
inlined_args = 2 + IsSetterPC(pc);
|
||||
|
||||
JS_ASSERT(exprStackSlots >= inlined_args);
|
||||
pushedSlots = exprStackSlots - inlined_args;
|
||||
@ -662,7 +683,11 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (op == JSOP_FUNAPPLY) {
|
||||
if (needToSaveArgs) {
|
||||
// When an accessor is inlined, the whole thing is a lie. There
|
||||
// should never have been a call there. Fix the caller's stack to
|
||||
// forget it ever happened.
|
||||
|
||||
// When funapply gets inlined we take all arguments out of the
|
||||
// arguments array. So the stack state is incorrect. To restore
|
||||
// correctly it must look like js_fun_apply was actually called.
|
||||
@ -670,22 +695,36 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
||||
// to |js_fun_apply, target, this, argObject|.
|
||||
// Since the information is never read, we can just push undefined
|
||||
// for all values.
|
||||
IonSpew(IonSpew_BaselineBailouts, " pushing 4x undefined to fixup funapply");
|
||||
if (!builder.writeValue(UndefinedValue(), "StackValue"))
|
||||
return false;
|
||||
if (!builder.writeValue(UndefinedValue(), "StackValue"))
|
||||
return false;
|
||||
if (!builder.writeValue(UndefinedValue(), "StackValue"))
|
||||
return false;
|
||||
if (!builder.writeValue(UndefinedValue(), "StackValue"))
|
||||
return false;
|
||||
|
||||
if (op == JSOP_FUNAPPLY) {
|
||||
IonSpew(IonSpew_BaselineBailouts, " pushing 4x undefined to fixup funapply");
|
||||
if (!builder.writeValue(UndefinedValue(), "StackValue"))
|
||||
return false;
|
||||
if (!builder.writeValue(UndefinedValue(), "StackValue"))
|
||||
return false;
|
||||
if (!builder.writeValue(UndefinedValue(), "StackValue"))
|
||||
return false;
|
||||
if (!builder.writeValue(UndefinedValue(), "StackValue"))
|
||||
return false;
|
||||
}
|
||||
// Save the actual arguments. They are needed on the callee side
|
||||
// as the arguments. Else we can't recover them.
|
||||
if (!funapplyargs.resize(inlined_args))
|
||||
if (!savedCallerArgs.resize(inlined_args))
|
||||
return false;
|
||||
for (uint32_t i = 0; i < inlined_args; i++)
|
||||
funapplyargs[i] = iter.read();
|
||||
savedCallerArgs[i] = iter.read();
|
||||
|
||||
if (IsSetterPC(pc)) {
|
||||
// We would love to just save all the arguments and leave them
|
||||
// in the stub frame pushed below, but we will lose the inital
|
||||
// argument which the function was called with, which we must
|
||||
// return to the caller, even if the setter internally modifies
|
||||
// its arguments. Stash the initial argument on the stack, to be
|
||||
// later retrieved by the SetProp_Fallback stub.
|
||||
Value initialArg = savedCallerArgs[inlined_args - 1];
|
||||
IonSpew(IonSpew_BaselineBailouts, " pushing setter's initial argument");
|
||||
if (!builder.writeValue(initialArg, "StackValue"))
|
||||
return false;
|
||||
}
|
||||
pushedSlots = exprStackSlots;
|
||||
}
|
||||
}
|
||||
@ -742,6 +781,16 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
||||
// include the this. When inlining that is not included.
|
||||
// So the exprStackSlots will be one less.
|
||||
JS_ASSERT(expectedDepth - exprStackSlots <= 1);
|
||||
} else if (iter.moreFrames() && (IsGetterPC(pc) || IsSetterPC(pc))) {
|
||||
// Accessors coming out of ion are inlined via a complete
|
||||
// lie perpetrated by the compiler internally. Ion just rearranges
|
||||
// the stack, and pretends that it looked like a call all along.
|
||||
// This means that the depth is actually one *more* than expected
|
||||
// by the interpreter, as there is now a JSFunction, |this| and [arg],
|
||||
// rather than the expected |this| and [arg]
|
||||
// Note that none of that was pushed, but it's still reflected
|
||||
// in exprStackSlots.
|
||||
JS_ASSERT(exprStackSlots - expectedDepth == 1);
|
||||
} else {
|
||||
// For fun.apply({}, arguments) the reconstructStackDepth will
|
||||
// have stackdepth 4, but it could be that we inlined the
|
||||
@ -913,9 +962,9 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
||||
return false;
|
||||
|
||||
// Calculate and write out return address.
|
||||
// The icEntry in question MUST have a ICCall_Fallback as its fallback stub.
|
||||
// The icEntry in question MUST have an inlinable fallback stub.
|
||||
ICEntry &icEntry = baselineScript->icEntryFromPCOffset(pcOff);
|
||||
JS_ASSERT(icEntry.firstStub()->getChainFallback()->isCall_Fallback());
|
||||
JS_ASSERT(IsInlinableFallback(icEntry.firstStub()->getChainFallback()));
|
||||
if (!builder.writePtr(baselineScript->returnAddressForIC(icEntry), "ReturnAddr"))
|
||||
return false;
|
||||
|
||||
@ -947,7 +996,7 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
||||
size_t startOfBaselineStubFrame = builder.framePushed();
|
||||
|
||||
// Write stub pointer.
|
||||
JS_ASSERT(icEntry.fallbackStub()->isCall_Fallback());
|
||||
JS_ASSERT(IsInlinableFallback(icEntry.fallbackStub()));
|
||||
if (!builder.writePtr(icEntry.fallbackStub(), "StubPtr"))
|
||||
return false;
|
||||
|
||||
@ -958,21 +1007,25 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
||||
|
||||
// Write out actual arguments (and thisv), copied from unpacked stack of BaselineJS frame.
|
||||
// Arguments are reversed on the BaselineJS frame's stack values.
|
||||
JS_ASSERT(isCall);
|
||||
unsigned actualArgc = GET_ARGC(pc);
|
||||
if (op == JSOP_FUNAPPLY) {
|
||||
// For FUNAPPLY the arguments are not on the stack anymore,
|
||||
JS_ASSERT(isCall || IsGetterPC(pc) || IsSetterPC(pc));
|
||||
unsigned actualArgc;
|
||||
if (needToSaveArgs) {
|
||||
// For FUNAPPLY or an accessor, the arguments are not on the stack anymore,
|
||||
// but they are copied in a vector and are written here.
|
||||
actualArgc = blFrame->numActualArgs();
|
||||
if (op == JSOP_FUNAPPLY)
|
||||
actualArgc = blFrame->numActualArgs();
|
||||
else
|
||||
actualArgc = IsSetterPC(pc);
|
||||
|
||||
JS_ASSERT(actualArgc + 2 <= exprStackSlots);
|
||||
JS_ASSERT(funapplyargs.length() == actualArgc + 2);
|
||||
JS_ASSERT(savedCallerArgs.length() == actualArgc + 2);
|
||||
for (unsigned i = 0; i < actualArgc + 1; i++) {
|
||||
size_t arg = funapplyargs.length() - (i + 1);
|
||||
if (!builder.writeValue(funapplyargs[arg], "ArgVal"))
|
||||
size_t arg = savedCallerArgs.length() - (i + 1);
|
||||
if (!builder.writeValue(savedCallerArgs[arg], "ArgVal"))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
actualArgc = GET_ARGC(pc);
|
||||
if (op == JSOP_FUNCALL) {
|
||||
JS_ASSERT(actualArgc > 0);
|
||||
actualArgc--;
|
||||
@ -1001,10 +1054,10 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
||||
|
||||
// Push callee token (must be a JS Function)
|
||||
Value callee;
|
||||
if (op == JSOP_FUNAPPLY) {
|
||||
// The arguments of FUNAPPLY are not writen to the stack.
|
||||
if (needToSaveArgs) {
|
||||
// The arguments of FUNAPPLY or inlined accessors are not writen to the stack.
|
||||
// So get the callee from the specially saved vector.
|
||||
callee = funapplyargs[0];
|
||||
callee = savedCallerArgs[0];
|
||||
} else {
|
||||
uint32_t calleeStackSlot = exprStackSlots - uint32_t(actualArgc + 2);
|
||||
size_t calleeOffset = (builder.framePushed() - endOfBaselineJSFrameStack)
|
||||
@ -1024,7 +1077,7 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
||||
return false;
|
||||
|
||||
// Push return address into ICCall_Scripted stub, immediately after the call.
|
||||
void *baselineCallReturnAddr = cx->compartment()->ionCompartment()->baselineCallReturnAddr();
|
||||
void *baselineCallReturnAddr = GetStubReturnAddress(cx, pc);
|
||||
JS_ASSERT(baselineCallReturnAddr);
|
||||
if (!builder.writePtr(baselineCallReturnAddr, "ReturnAddr"))
|
||||
return false;
|
||||
|
@ -5509,7 +5509,36 @@ ICGetProp_Fallback::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
masm.push(BaselineStubReg);
|
||||
masm.pushBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
|
||||
|
||||
return tailCallVM(DoGetPropFallbackInfo, masm);
|
||||
if (!tailCallVM(DoGetPropFallbackInfo, masm))
|
||||
return false;
|
||||
|
||||
// What follows is bailout-only code for inlined scripted getters
|
||||
// The return address pointed to by the baseline stack points here.
|
||||
returnOffset_ = masm.currentOffset();
|
||||
|
||||
// Even though the fallback frame doesn't enter a stub frame, the CallScripted
|
||||
// frame that we are emulating does. Again, we lie.
|
||||
entersStubFrame_ = true;
|
||||
|
||||
leaveStubFrame(masm, true);
|
||||
|
||||
// When we get here, BaselineStubReg contains the ICGetProp_Fallback stub,
|
||||
// which we can't use to enter the TypeMonitor IC, because it's a MonitoredFallbackStub
|
||||
// instead of a MonitoredStub. So, we cheat.
|
||||
masm.loadPtr(Address(BaselineStubReg, ICMonitoredFallbackStub::offsetOfFallbackMonitorStub()),
|
||||
BaselineStubReg);
|
||||
EmitEnterTypeMonitorIC(masm, ICTypeMonitor_Fallback::offsetOfFirstMonitorStub());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ICGetProp_Fallback::Compiler::postGenerateStubCode(MacroAssembler &masm, Handle<IonCode *> code)
|
||||
{
|
||||
CodeOffsetLabel offset(returnOffset_);
|
||||
offset.fixup(&masm);
|
||||
cx->compartment()->ionCompartment()->initBaselineGetPropReturnAddr(code->raw() + offset.offset());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -6348,7 +6377,33 @@ ICSetProp_Fallback::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
masm.push(BaselineStubReg);
|
||||
masm.pushBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
|
||||
|
||||
return tailCallVM(DoSetPropFallbackInfo, masm);
|
||||
if (!tailCallVM(DoSetPropFallbackInfo, masm))
|
||||
return false;
|
||||
|
||||
// What follows is bailout-only code for inlined scripted getters
|
||||
// The return address pointed to by the baseline stack points here.
|
||||
returnOffset_ = masm.currentOffset();
|
||||
|
||||
// Even though the fallback frame doesn't enter a stub frame, the CallScripted
|
||||
// frame that we are emulating does. Again, we lie.
|
||||
entersStubFrame_ = true;
|
||||
|
||||
leaveStubFrame(masm, true);
|
||||
|
||||
// Retrieve the stashed initial argument from the caller's frame before returning
|
||||
EmitUnstowICValues(masm, 1);
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ICSetProp_Fallback::Compiler::postGenerateStubCode(MacroAssembler &masm, Handle<IonCode *> code)
|
||||
{
|
||||
CodeOffsetLabel offset(returnOffset_);
|
||||
offset.fixup(&masm);
|
||||
cx->compartment()->ionCompartment()->initBaselineSetPropReturnAddr(code->raw() + offset.offset());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -743,6 +743,11 @@ class ICStub
|
||||
case SetProp_CallScripted:
|
||||
case SetProp_CallNative:
|
||||
case RetSub_Fallback:
|
||||
// These two fallback stubs don't actually make non-tail calls,
|
||||
// but the fallback code for the bailout path needs to pop the stub frame
|
||||
// pushed during the bailout.
|
||||
case GetProp_Fallback:
|
||||
case SetProp_Fallback:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@ -979,9 +984,9 @@ class ICStubCompiler
|
||||
// Prevent GC in the middle of stub compilation.
|
||||
js::gc::AutoSuppressGC suppressGC;
|
||||
|
||||
mozilla::DebugOnly<bool> entersStubFrame_;
|
||||
|
||||
protected:
|
||||
mozilla::DebugOnly<bool> entersStubFrame_;
|
||||
JSContext *cx;
|
||||
ICStub::Kind kind;
|
||||
|
||||
@ -3748,7 +3753,9 @@ class ICGetProp_Fallback : public ICMonitoredFallbackStub
|
||||
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
uint32_t returnOffset_;
|
||||
bool generateStubCode(MacroAssembler &masm);
|
||||
bool postGenerateStubCode(MacroAssembler &masm, Handle<IonCode *> code);
|
||||
|
||||
public:
|
||||
Compiler(JSContext *cx)
|
||||
@ -4538,7 +4545,9 @@ class ICSetProp_Fallback : public ICFallbackStub
|
||||
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
uint32_t returnOffset_;
|
||||
bool generateStubCode(MacroAssembler &masm);
|
||||
bool postGenerateStubCode(MacroAssembler &masm, Handle<IonCode *> code);
|
||||
|
||||
public:
|
||||
Compiler(JSContext *cx)
|
||||
|
@ -308,6 +308,8 @@ IonCompartment::IonCompartment(IonRuntime *rt)
|
||||
: rt(rt),
|
||||
stubCodes_(NULL),
|
||||
baselineCallReturnAddr_(NULL),
|
||||
baselineGetPropReturnAddr_(NULL),
|
||||
baselineSetPropReturnAddr_(NULL),
|
||||
stringConcatStub_(NULL),
|
||||
parallelStringConcatStub_(NULL)
|
||||
{
|
||||
@ -414,6 +416,11 @@ IonCompartment::sweep(FreeOp *fop)
|
||||
// If the sweep removed the ICCall_Fallback stub, NULL the baselineCallReturnAddr_ field.
|
||||
if (!stubCodes_->lookup(static_cast<uint32_t>(ICStub::Call_Fallback)))
|
||||
baselineCallReturnAddr_ = NULL;
|
||||
// Similarly for the ICGetProp_Fallback stub.
|
||||
if (!stubCodes_->lookup(static_cast<uint32_t>(ICStub::GetProp_Fallback)))
|
||||
baselineGetPropReturnAddr_ = NULL;
|
||||
if (!stubCodes_->lookup(static_cast<uint32_t>(ICStub::SetProp_Fallback)))
|
||||
baselineSetPropReturnAddr_ = NULL;
|
||||
|
||||
if (stringConcatStub_ && !IsIonCodeMarked(stringConcatStub_.unsafeGet()))
|
||||
stringConcatStub_ = NULL;
|
||||
|
@ -3557,6 +3557,9 @@ IonBuilder::patchInlinedReturn(CallInfo &callInfo, MBasicBlock *exit, MBasicBloc
|
||||
// Known non-object return: force |this|.
|
||||
rdef = callInfo.thisArg();
|
||||
}
|
||||
} else if (callInfo.isSetter()) {
|
||||
// Setters return their argument, not whatever value is returned.
|
||||
rdef = callInfo.getArg(0);
|
||||
}
|
||||
|
||||
MGoto *replacement = MGoto::New(bottom);
|
||||
@ -7823,8 +7826,15 @@ IonBuilder::getPropTryCommonGetter(bool *emitted, HandleId id,
|
||||
CallInfo callInfo(cx, false);
|
||||
if (!callInfo.init(current, 0))
|
||||
return false;
|
||||
if (!makeCall(getter, callInfo, false))
|
||||
return false;
|
||||
|
||||
// Inline if we can, otherwise, forget it and just generate a call.
|
||||
if (makeInliningDecision(getter, callInfo) && getter->isInterpreted()) {
|
||||
if (!inlineScriptedCall(callInfo, getter))
|
||||
return false;
|
||||
} else {
|
||||
if (!makeCall(getter, callInfo, false))
|
||||
return false;
|
||||
}
|
||||
|
||||
*emitted = true;
|
||||
return true;
|
||||
@ -8047,6 +8057,13 @@ IonBuilder::jsop_setprop(HandlePropertyName name)
|
||||
CallInfo callInfo(cx, false);
|
||||
if (!callInfo.init(current, 1))
|
||||
return false;
|
||||
// Ensure that we know we are calling a setter in case we inline it.
|
||||
callInfo.markAsSetter();
|
||||
|
||||
// Inline the setter if we can.
|
||||
if (makeInliningDecision(setter, callInfo) && setter->isInterpreted())
|
||||
return inlineScriptedCall(callInfo, setter);
|
||||
|
||||
MCall *call = makeCallHelper(setter, callInfo, false);
|
||||
if (!call)
|
||||
return false;
|
||||
|
@ -658,13 +658,15 @@ class CallInfo
|
||||
Vector<MDefinition *> args_;
|
||||
|
||||
bool constructing_;
|
||||
bool setter_;
|
||||
|
||||
public:
|
||||
CallInfo(JSContext *cx, bool constructing)
|
||||
: fun_(NULL),
|
||||
thisArg_(NULL),
|
||||
args_(cx),
|
||||
constructing_(constructing)
|
||||
constructing_(constructing),
|
||||
setter_(false)
|
||||
{ }
|
||||
|
||||
bool init(CallInfo &callInfo) {
|
||||
@ -751,6 +753,13 @@ class CallInfo
|
||||
return constructing_;
|
||||
}
|
||||
|
||||
bool isSetter() const {
|
||||
return setter_;
|
||||
}
|
||||
void markAsSetter() {
|
||||
setter_ = true;
|
||||
}
|
||||
|
||||
void wrapArgs(MBasicBlock *current) {
|
||||
thisArg_ = wrap(current, thisArg_);
|
||||
for (uint32_t i = 0; i < argc(); i++)
|
||||
|
@ -224,9 +224,11 @@ class IonCompartment
|
||||
typedef WeakValueCache<uint32_t, ReadBarriered<IonCode> > ICStubCodeMap;
|
||||
ICStubCodeMap *stubCodes_;
|
||||
|
||||
// Keep track of offset into baseline ICCall_Scripted stub's code at return
|
||||
// Keep track of offset into various baseline stubs' code at return
|
||||
// point from called script.
|
||||
void *baselineCallReturnAddr_;
|
||||
void *baselineGetPropReturnAddr_;
|
||||
void *baselineSetPropReturnAddr_;
|
||||
|
||||
// Allocated space for optimized baseline stubs.
|
||||
OptimizedICStubSpace optimizedStubSpace_;
|
||||
@ -269,6 +271,22 @@ class IonCompartment
|
||||
JS_ASSERT(baselineCallReturnAddr_ != NULL);
|
||||
return baselineCallReturnAddr_;
|
||||
}
|
||||
void initBaselineGetPropReturnAddr(void *addr) {
|
||||
JS_ASSERT(baselineGetPropReturnAddr_ == NULL);
|
||||
baselineGetPropReturnAddr_ = addr;
|
||||
}
|
||||
void *baselineGetPropReturnAddr() {
|
||||
JS_ASSERT(baselineGetPropReturnAddr_ != NULL);
|
||||
return baselineGetPropReturnAddr_;
|
||||
}
|
||||
void initBaselineSetPropReturnAddr(void *addr) {
|
||||
JS_ASSERT(baselineSetPropReturnAddr_ == NULL);
|
||||
baselineSetPropReturnAddr_ = addr;
|
||||
}
|
||||
void *baselineSetPropReturnAddr() {
|
||||
JS_ASSERT(baselineSetPropReturnAddr_ != NULL);
|
||||
return baselineSetPropReturnAddr_;
|
||||
}
|
||||
|
||||
void toggleBaselineStubBarriers(bool enabled);
|
||||
|
||||
|
@ -1321,6 +1321,10 @@ InlineFrameIteratorMaybeGC<allowGC>::findNextFrame()
|
||||
if (JSOp(*pc_) == JSOP_FUNCALL) {
|
||||
JS_ASSERT(GET_ARGC(pc_) > 0);
|
||||
numActualArgs_ = GET_ARGC(pc_) - 1;
|
||||
} else if (IsGetterPC(pc_)) {
|
||||
numActualArgs_ = 0;
|
||||
} else if (IsSetterPC(pc_)) {
|
||||
numActualArgs_ = 1;
|
||||
}
|
||||
|
||||
JS_ASSERT(numActualArgs_ != 0xbadbad);
|
||||
|
@ -273,11 +273,16 @@ CodeGeneratorShared::encode(LSnapshot *snapshot)
|
||||
// include the this. When inlining that is not included.
|
||||
// So the exprStackSlots will be one less.
|
||||
JS_ASSERT(stackDepth - exprStack <= 1);
|
||||
} else if (JSOp(*bailPC) != JSOP_FUNAPPLY) {
|
||||
} else if (JSOp(*bailPC) != JSOP_FUNAPPLY && !IsGetterPC(bailPC) && !IsSetterPC(bailPC)) {
|
||||
// For fun.apply({}, arguments) the reconstructStackDepth will
|
||||
// have stackdepth 4, but it could be that we inlined the
|
||||
// funapply. In that case exprStackSlots, will have the real
|
||||
// arguments in the slots and not be 4.
|
||||
|
||||
// With accessors, we have different stack depths depending on whether or not we
|
||||
// inlined the accessor, as the inlined stack contains a callee function that should
|
||||
// never have been there and we might just be capturing an uneventful property site,
|
||||
// in which case there won't have been any violence.
|
||||
JS_ASSERT(exprStack == stackDepth);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user