Bug 913978 - Fix over-tight assertions after enabling Baseline getter/setter calls for GETELEM/SETELEM ops. r=efaust

This commit is contained in:
Kannan Vijayan 2013-09-10 12:26:47 -04:00
parent 11c7d05ca8
commit 78fdcfa160
5 changed files with 34 additions and 17 deletions

View File

@ -379,9 +379,9 @@ IsInlinableFallback(ICFallbackStub *icEntry)
static inline void* static inline void*
GetStubReturnAddress(JSContext *cx, jsbytecode *pc) GetStubReturnAddress(JSContext *cx, jsbytecode *pc)
{ {
if (IsGetterPC(pc)) if (IsGetPropPC(pc))
return cx->compartment()->ionCompartment()->baselineGetPropReturnAddr(); return cx->compartment()->ionCompartment()->baselineGetPropReturnAddr();
if (IsSetterPC(pc)) if (IsSetPropPC(pc))
return cx->compartment()->ionCompartment()->baselineSetPropReturnAddr(); return cx->compartment()->ionCompartment()->baselineSetPropReturnAddr();
// This should be a call op of some kind, now. // This should be a call op of some kind, now.
JS_ASSERT(IsCallPC(pc)); JS_ASSERT(IsCallPC(pc));
@ -661,7 +661,7 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
// On the caller side this must represent like the function wasn't inlined. // On the caller side this must represent like the function wasn't inlined.
uint32_t pushedSlots = 0; uint32_t pushedSlots = 0;
AutoValueVector savedCallerArgs(cx); AutoValueVector savedCallerArgs(cx);
bool needToSaveArgs = op == JSOP_FUNAPPLY || IsGetterPC(pc) || IsSetterPC(pc); bool needToSaveArgs = op == JSOP_FUNAPPLY || IsGetPropPC(pc) || IsSetPropPC(pc);
if (iter.moreFrames() && (op == JSOP_FUNCALL || needToSaveArgs)) if (iter.moreFrames() && (op == JSOP_FUNCALL || needToSaveArgs))
{ {
uint32_t inlined_args = 0; uint32_t inlined_args = 0;
@ -670,7 +670,7 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
else if (op == JSOP_FUNAPPLY) else if (op == JSOP_FUNAPPLY)
inlined_args = 2 + blFrame->numActualArgs(); inlined_args = 2 + blFrame->numActualArgs();
else else
inlined_args = 2 + IsSetterPC(pc); inlined_args = 2 + IsSetPropPC(pc);
JS_ASSERT(exprStackSlots >= inlined_args); JS_ASSERT(exprStackSlots >= inlined_args);
pushedSlots = exprStackSlots - inlined_args; pushedSlots = exprStackSlots - inlined_args;
@ -725,7 +725,7 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
for (uint32_t i = 0; i < inlined_args; i++) for (uint32_t i = 0; i < inlined_args; i++)
savedCallerArgs[i] = iter.read(); savedCallerArgs[i] = iter.read();
if (IsSetterPC(pc)) { if (IsSetPropPC(pc)) {
// We would love to just save all the arguments and leave them // We would love to just save all the arguments and leave them
// in the stub frame pushed below, but we will lose the inital // in the stub frame pushed below, but we will lose the inital
// argument which the function was called with, which we must // argument which the function was called with, which we must
@ -793,7 +793,7 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
// include the this. When inlining that is not included. // include the this. When inlining that is not included.
// So the exprStackSlots will be one less. // So the exprStackSlots will be one less.
JS_ASSERT(expectedDepth - exprStackSlots <= 1); JS_ASSERT(expectedDepth - exprStackSlots <= 1);
} else if (iter.moreFrames() && (IsGetterPC(pc) || IsSetterPC(pc))) { } else if (iter.moreFrames() && (IsGetPropPC(pc) || IsSetPropPC(pc))) {
// Accessors coming out of ion are inlined via a complete // Accessors coming out of ion are inlined via a complete
// lie perpetrated by the compiler internally. Ion just rearranges // lie perpetrated by the compiler internally. Ion just rearranges
// the stack, and pretends that it looked like a call all along. // the stack, and pretends that it looked like a call all along.
@ -1028,7 +1028,7 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
if (op == JSOP_FUNAPPLY) if (op == JSOP_FUNAPPLY)
actualArgc = blFrame->numActualArgs(); actualArgc = blFrame->numActualArgs();
else else
actualArgc = IsSetterPC(pc); actualArgc = IsSetPropPC(pc);
JS_ASSERT(actualArgc + 2 <= exprStackSlots); JS_ASSERT(actualArgc + 2 <= exprStackSlots);
JS_ASSERT(savedCallerArgs.length() == actualArgc + 2); JS_ASSERT(savedCallerArgs.length() == actualArgc + 2);

View File

@ -374,7 +374,7 @@ IsIonInlinablePC(jsbytecode *pc) {
// CALL, FUNCALL, FUNAPPLY, EVAL, NEW (Normal Callsites) // CALL, FUNCALL, FUNAPPLY, EVAL, NEW (Normal Callsites)
// GETPROP, CALLPROP, and LENGTH. (Inlined Getters) // GETPROP, CALLPROP, and LENGTH. (Inlined Getters)
// SETPROP, SETNAME, SETGNAME (Inlined Setters) // SETPROP, SETNAME, SETGNAME (Inlined Setters)
return IsCallPC(pc) || IsGetterPC(pc) || IsSetterPC(pc); return IsCallPC(pc) || IsGetPropPC(pc) || IsSetPropPC(pc);
} }
void ForbidCompilation(JSContext *cx, JSScript *script); void ForbidCompilation(JSContext *cx, JSScript *script);

View File

@ -1374,9 +1374,9 @@ InlineFrameIteratorMaybeGC<allowGC>::findNextFrame()
if (JSOp(*pc_) == JSOP_FUNCALL) { if (JSOp(*pc_) == JSOP_FUNCALL) {
JS_ASSERT(GET_ARGC(pc_) > 0); JS_ASSERT(GET_ARGC(pc_) > 0);
numActualArgs_ = GET_ARGC(pc_) - 1; numActualArgs_ = GET_ARGC(pc_) - 1;
} else if (IsGetterPC(pc_)) { } else if (IsGetPropPC(pc_)) {
numActualArgs_ = 0; numActualArgs_ = 0;
} else if (IsSetterPC(pc_)) { } else if (IsSetPropPC(pc_)) {
numActualArgs_ = 1; numActualArgs_ = 1;
} }
@ -1443,7 +1443,7 @@ InlineFrameIteratorMaybeGC<allowGC>::isConstructing() const
++parent; ++parent;
// Inlined Getters and Setters are never constructing. // Inlined Getters and Setters are never constructing.
if (IsGetterPC(parent.pc()) || IsSetterPC(parent.pc())) if (IsGetPropPC(parent.pc()) || IsSetPropPC(parent.pc()))
return false; return false;
// In the case of a JS frame, look up the pc from the snapshot. // In the case of a JS frame, look up the pc from the snapshot.
@ -1472,7 +1472,7 @@ IonFrameIterator::isConstructing() const
InlineFrameIterator inlinedParent(GetIonContext()->cx, &parent); InlineFrameIterator inlinedParent(GetIonContext()->cx, &parent);
//Inlined Getters and Setters are never constructing. //Inlined Getters and Setters are never constructing.
if (IsGetterPC(inlinedParent.pc()) || IsSetterPC(inlinedParent.pc())) if (IsGetPropPC(inlinedParent.pc()) || IsSetPropPC(inlinedParent.pc()))
return false; return false;
JS_ASSERT(IsCallPC(inlinedParent.pc())); JS_ASSERT(IsCallPC(inlinedParent.pc()));
@ -1484,8 +1484,9 @@ IonFrameIterator::isConstructing() const
jsbytecode *pc; jsbytecode *pc;
parent.baselineScriptAndPc(NULL, &pc); parent.baselineScriptAndPc(NULL, &pc);
//Inlined Getters and Setters are never constructing. // Inlined Getters and Setters are never constructing.
if (IsGetterPC(pc) || IsSetterPC(pc)) // Baseline may call getters from [GET|SET]PROP or [GET|SET]ELEM ops.
if (IsGetPropPC(pc) || IsSetPropPC(pc) || IsGetElemPC(pc) || IsSetElemPC(pc))
return false; return false;
JS_ASSERT(IsCallPC(pc)); JS_ASSERT(IsCallPC(pc));

View File

@ -284,7 +284,9 @@ CodeGeneratorShared::encode(LSnapshot *snapshot)
// include the this. When inlining that is not included. // include the this. When inlining that is not included.
// So the exprStackSlots will be one less. // So the exprStackSlots will be one less.
JS_ASSERT(stackDepth - exprStack <= 1); JS_ASSERT(stackDepth - exprStack <= 1);
} else if (JSOp(*bailPC) != JSOP_FUNAPPLY && !IsGetterPC(bailPC) && !IsSetterPC(bailPC)) { } else if (JSOp(*bailPC) != JSOP_FUNAPPLY &&
!IsGetPropPC(bailPC) && !IsSetPropPC(bailPC))
{
// For fun.apply({}, arguments) the reconstructStackDepth will // For fun.apply({}, arguments) the reconstructStackDepth will
// have stackdepth 4, but it could be that we inlined the // have stackdepth 4, but it could be that we inlined the
// funapply. In that case exprStackSlots, will have the real // funapply. In that case exprStackSlots, will have the real

View File

@ -591,19 +591,33 @@ IsEqualityOp(JSOp op)
} }
inline bool inline bool
IsGetterPC(jsbytecode *pc) IsGetPropPC(jsbytecode *pc)
{ {
JSOp op = JSOp(*pc); JSOp op = JSOp(*pc);
return op == JSOP_LENGTH || op == JSOP_GETPROP || op == JSOP_CALLPROP; return op == JSOP_LENGTH || op == JSOP_GETPROP || op == JSOP_CALLPROP;
} }
inline bool inline bool
IsSetterPC(jsbytecode *pc) IsSetPropPC(jsbytecode *pc)
{ {
JSOp op = JSOp(*pc); JSOp op = JSOp(*pc);
return op == JSOP_SETPROP || op == JSOP_SETNAME || op == JSOP_SETGNAME; return op == JSOP_SETPROP || op == JSOP_SETNAME || op == JSOP_SETGNAME;
} }
inline bool
IsGetElemPC(jsbytecode *pc)
{
JSOp op = JSOp(*pc);
return op == JSOP_GETELEM || op == JSOP_CALLELEM;
}
inline bool
IsSetElemPC(jsbytecode *pc)
{
JSOp op = JSOp(*pc);
return op == JSOP_SETELEM;
}
inline bool inline bool
IsCallPC(jsbytecode *pc) IsCallPC(jsbytecode *pc)
{ {