bug 449494 - uniform handling of bytecodes with variable stack uses. r=mrbkap,brendan

This commit is contained in:
Igor Bukanov
2008-09-02 08:25:15 +02:00
parent 5899982681
commit 4be80b5c95
5 changed files with 86 additions and 151 deletions

View File

@@ -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;
}