bug 449494 - uniform handling of bytecodes with variable stack uses. r=mrbkap,brendan
This commit is contained in:
@@ -197,6 +197,28 @@ js_GetVariableBytecodeLength(jsbytecode *pc)
|
||||
}
|
||||
}
|
||||
|
||||
uintN
|
||||
js_GetVariableStackUseLength(JSOp op, jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(*pc == op || *pc == JSOP_TRAP);
|
||||
JS_ASSERT(js_CodeSpec[op].nuses == -1);
|
||||
switch (op) {
|
||||
case JSOP_POPN:
|
||||
return GET_UINT16(pc);
|
||||
case JSOP_LEAVEBLOCK:
|
||||
return GET_UINT16(pc);
|
||||
case JSOP_LEAVEBLOCKEXPR:
|
||||
return GET_UINT16(pc) + 1;
|
||||
case JSOP_NEWARRAY:
|
||||
return GET_UINT24(pc);
|
||||
default:
|
||||
/* stack: fun, this, [argc arguments] */
|
||||
JS_ASSERT(op == JSOP_NEW || op == JSOP_CALL ||
|
||||
op == JSOP_EVAL || op == JSOP_SETCALL);
|
||||
return 2 + GET_ARGC(pc);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
JS_FRIEND_API(JSBool)
|
||||
@@ -5162,20 +5184,6 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
|
||||
if (oplen < 0)
|
||||
oplen = js_GetVariableBytecodeLength(pc);
|
||||
|
||||
if (op == JSOP_POPN) {
|
||||
pcdepth -= GET_UINT16(pc);
|
||||
LOCAL_ASSERT(pcdepth >= 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (op == JSOP_NEWARRAY) {
|
||||
pcdepth -= GET_UINT24(pc) - 1;
|
||||
LOCAL_ASSERT(pcdepth > 0);
|
||||
if (pcstack)
|
||||
pcstack[pcdepth - 1] = pc;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* A (C ? T : E) expression requires skipping either T (if target is in
|
||||
* E) or both T and E (if target is after the whole expression) before
|
||||
@@ -5214,34 +5222,21 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
|
||||
continue;
|
||||
|
||||
nuses = cs->nuses;
|
||||
if (nuses < 0) {
|
||||
/* Call opcode pushes [callee, this, argv...]. */
|
||||
nuses = 2 + GET_ARGC(pc);
|
||||
} else if (op == JSOP_RETSUB) {
|
||||
/* Pop [exception or hole, retsub pc-index]. */
|
||||
JS_ASSERT(nuses == 0);
|
||||
nuses = 2;
|
||||
} else if (op == JSOP_LEAVEBLOCK || op == JSOP_LEAVEBLOCKEXPR) {
|
||||
JS_ASSERT(nuses == 0);
|
||||
nuses = GET_UINT16(pc);
|
||||
}
|
||||
pcdepth -= nuses;
|
||||
LOCAL_ASSERT(pcdepth >= 0);
|
||||
if (nuses < 0)
|
||||
nuses = js_GetVariableStackUseLength(op, pc);
|
||||
|
||||
ndefs = cs->ndefs;
|
||||
if (op == JSOP_FINALLY) {
|
||||
/* Push [exception or hole, retsub pc-index]. */
|
||||
JS_ASSERT(ndefs == 0);
|
||||
ndefs = 2;
|
||||
} else if (op == JSOP_ENTERBLOCK) {
|
||||
if (ndefs < 0) {
|
||||
JSObject *obj;
|
||||
|
||||
JS_ASSERT(ndefs == 0);
|
||||
JS_ASSERT(op == JSOP_ENTERBLOCK);
|
||||
GET_OBJECT_FROM_BYTECODE(script, pc, 0, obj);
|
||||
JS_ASSERT(OBJ_BLOCK_DEPTH(cx, obj) == pcdepth);
|
||||
ndefs = OBJ_BLOCK_COUNT(cx, obj);
|
||||
}
|
||||
|
||||
pcdepth -= nuses;
|
||||
LOCAL_ASSERT(pcdepth >= 0);
|
||||
LOCAL_ASSERT((uintN)(pcdepth + ndefs) <= StackDepth(script));
|
||||
|
||||
/*
|
||||
@@ -5276,25 +5271,6 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
|
||||
pcstack[pcdepth + 3] = pcstack[pcdepth + 1];
|
||||
}
|
||||
break;
|
||||
|
||||
case JSOP_LEAVEBLOCKEXPR:
|
||||
/*
|
||||
* The decompiler wants to see [leaveblockexpr] on pcstack, not
|
||||
* [enterblock] or the pc that ended a simulated let expression
|
||||
* when [enterblock] defines zero locals as in:
|
||||
*
|
||||
* let ([] = []) expr
|
||||
*/
|
||||
JS_ASSERT(ndefs == 0);
|
||||
LOCAL_ASSERT(pcdepth >= 1);
|
||||
LOCAL_ASSERT(nuses == 0 || !pcstack ||
|
||||
*pcstack[pcdepth - 1] == JSOP_ENTERBLOCK ||
|
||||
(*pcstack[pcdepth - 1] == JSOP_TRAP &&
|
||||
JS_GetTrapOpcode(cx, script, pcstack[pcdepth - 1])
|
||||
== JSOP_ENTERBLOCK));
|
||||
if (pcstack)
|
||||
pcstack[pcdepth - 1] = pc;
|
||||
break;
|
||||
}
|
||||
pcdepth += ndefs;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user