bug 453492 - hiding JSCodeSpec.(nuses|ndefs) behind inlines to properly deal with variable stack bytecodes. r=brendan

This commit is contained in:
Igor Bukanov
2009-03-30 16:19:50 +02:00
parent 60aa8bb223
commit 7f43d1e11b
3 changed files with 78 additions and 49 deletions

View File

@@ -202,7 +202,7 @@ js_GetVariableBytecodeLength(jsbytecode *pc)
}
uintN
js_GetVariableStackUseLength(JSOp op, jsbytecode *pc)
js_GetVariableStackUses(JSOp op, jsbytecode *pc)
{
JS_ASSERT(*pc == op || *pc == JSOP_TRAP);
JS_ASSERT(js_CodeSpec[op].nuses == -1);
@@ -224,6 +224,16 @@ js_GetVariableStackUseLength(JSOp op, jsbytecode *pc)
}
}
uintN
js_GetEnterBlockStackDefs(JSContext *cx, JSScript *script, jsbytecode *pc)
{
JSObject *obj;
JS_ASSERT(*pc == JSOP_ENTERBLOCK || *pc == JSOP_TRAP);
GET_OBJECT_FROM_BYTECODE(script, pc, 0, obj);
return OBJ_BLOCK_COUNT(cx, obj);
}
#ifdef DEBUG
JS_FRIEND_API(JSBool)
@@ -1744,6 +1754,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
const JSCodeSpec *cs;
jssrcnote *sn, *sn2;
const char *lval, *rval, *xval, *fmt, *token;
uintN nuses;
jsint i, argc;
char **argv;
JSAtom *atom;
@@ -1911,9 +1922,19 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
}
saveop = op;
len = oplen = cs->length;
nuses = js_GetStackUses(cs, op, pc);
if (nb < 0 && -(nb + 1) == (intN)ss->top - cs->nuses + cs->ndefs)
return pc;
/*
* Here it is possible that nuses > ss->top when the op has a hidden
* source note. But when nb < 0 we assume that the caller knows that
* Decompile would never meet such opcodes.
*/
if (nb < 0) {
LOCAL_ASSERT(ss->top >= nuses);
uintN ndefs = js_GetStackDefs(cx, cs, op, jp->script, pc);
if ((uintN) -(nb + 1) == ss->top - nuses + ndefs)
return pc;
}
/*
* Save source literal associated with JS now before the following
@@ -1933,7 +1954,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
fp = js_GetScriptedCaller(cx, NULL);
format = cs->format;
if (((fp && fp->regs && pc == fp->regs->pc) ||
(pc == startpc && cs->nuses != 0)) &&
(pc == startpc && nuses != 0)) &&
format & (JOF_SET|JOF_DEL|JOF_INCDEC|JOF_FOR|JOF_VARPROP)) {
mode = JOF_MODE(format);
if (mode == JOF_NAME) {
@@ -1950,7 +1971,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
? JSOP_GETLOCAL
: JSOP_NAME;
i = cs->nuses - js_CodeSpec[op].nuses;
JS_ASSERT(js_CodeSpec[op].nuses >= 0);
i = nuses - js_CodeSpec[op].nuses;
while (--i >= 0)
PopOff(ss, JSOP_NOP);
} else {
@@ -2034,7 +2056,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
}
if (token) {
switch (cs->nuses) {
switch (nuses) {
case 2:
sn = js_GetSrcNote(jp->script, pc);
if (sn && SN_TYPE(sn) == SRC_ASSIGNOP) {
@@ -3070,7 +3092,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
lval, rval) < 0) {
return NULL;
}
/*
* Do not AddParentSlop here, as we will push the
* top-most offset again, which will add paren slop
@@ -3501,7 +3523,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
op = (JSOp) ss->opcodes[ss->top - 1];
lval = PopStr(ss,
(saveop == JSOP_NEW &&
(op == JSOP_CALL ||
(op == JSOP_CALL ||
op == JSOP_EVAL ||
op == JSOP_APPLY ||
(js_CodeSpec[op].format & JOF_CALLOP)))
@@ -5193,14 +5215,6 @@ static intN
ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
jsbytecode **pcstack)
{
intN pcdepth, nuses, ndefs;
jsbytecode *pc;
JSOp op;
const JSCodeSpec *cs;
ptrdiff_t oplen;
jssrcnote *sn;
intN i;
#define LOCAL_ASSERT(expr) LOCAL_ASSERT_RV(expr, -1);
/*
@@ -5211,10 +5225,12 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
* FIXME: Optimize to use last empty-stack sequence point.
*/
LOCAL_ASSERT(script->main <= target && target < script->code + script->length);
pcdepth = 0;
for (pc = script->main; pc < target; pc += oplen) {
op = js_GetOpcode(cx, script, pc);
cs = &js_CodeSpec[op];
uintN pcdepth = 0;
jsbytecode *pc = script->main;
ptrdiff_t oplen;
for (; pc < target; pc += oplen) {
JSOp op = js_GetOpcode(cx, script, pc);
const JSCodeSpec *cs = &js_CodeSpec[op];
oplen = cs->length;
if (oplen < 0)
oplen = js_GetVariableBytecodeLength(pc);
@@ -5226,11 +5242,9 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
* tests condition C. We know that the stack depth can't change from
* what it was with C on top of stack.
*/
sn = js_GetSrcNote(script, pc);
jssrcnote *sn = js_GetSrcNote(script, pc);
if (sn && SN_TYPE(sn) == SRC_COND) {
ptrdiff_t jmpoff, jmplen;
jmpoff = js_GetSrcNoteOffset(sn, 0);
ptrdiff_t jmpoff = js_GetSrcNoteOffset(sn, 0);
if (pc + jmpoff < target) {
pc += jmpoff;
op = js_GetOpcode(cx, script, pc);
@@ -5238,7 +5252,7 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
cs = &js_CodeSpec[op];
oplen = cs->length;
JS_ASSERT(oplen > 0);
jmplen = GetJumpOffset(pc, pc);
ptrdiff_t jmplen = GetJumpOffset(pc, pc);
if (pc + jmplen < target) {
oplen = (uintN) jmplen;
continue;
@@ -5248,31 +5262,19 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
* Ok, target lies in E. Manually pop C off the model stack,
* since we have moved beyond the IFEQ now.
*/
LOCAL_ASSERT(pcdepth != 0);
--pcdepth;
LOCAL_ASSERT(pcdepth >= 0);
}
}
if (sn && SN_TYPE(sn) == SRC_HIDDEN)
continue;
nuses = cs->nuses;
if (nuses < 0)
nuses = js_GetVariableStackUseLength(op, pc);
ndefs = cs->ndefs;
if (ndefs < 0) {
JSObject *obj;
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);
}
uintN nuses = js_GetStackUses(cs, op, pc);
uintN ndefs = js_GetStackDefs(cx, cs, op, script, pc);
LOCAL_ASSERT(pcdepth >= nuses);
pcdepth -= nuses;
LOCAL_ASSERT(pcdepth >= 0);
LOCAL_ASSERT((uintN)(pcdepth + ndefs) <= StackDepth(script));
LOCAL_ASSERT(pcdepth + ndefs <= StackDepth(script));
/*
* Fill the slots that the opcode defines withs its pc unless it just
@@ -5282,7 +5284,7 @@ ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
switch (op) {
default:
if (pcstack) {
for (i = 0; i != ndefs; ++i)
for (uintN i = 0; i != ndefs; ++i)
pcstack[pcdepth + i] = pc;
}
break;