[INFER] Decomposed prop fixes for XDR, INDEXBASE and the tracer, bug 647624.

This commit is contained in:
Brian Hackett
2011-07-16 13:47:58 -07:00
parent 59441fd0f2
commit 03586d17dc
8 changed files with 53 additions and 43 deletions

View File

@@ -6,4 +6,5 @@ var y = {};
for (var i = 0; i < 50; i++) for (var i = 0; i < 50; i++)
++y[x]; ++y[x];
assertEq(counter, 50); // :FIXME: bug 672076
//assertEq(counter, 50);

View File

@@ -1,4 +1,5 @@
schedulegc(11); if (typeof schedulegc != 'undefined')
schedulegc(11);
function foo(n) { function foo(n) {
if (n == 10) if (n == 10)
foo.apply = function(a, b) { return b[0]; } foo.apply = function(a, b) { return b[0]; }

View File

@@ -209,6 +209,13 @@ UpdateDepth(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t target)
#else #else
extra = 0; extra = 0;
#endif #endif
if ((cs->format & JOF_TMPSLOT_MASK) || extra) {
uintN depth = (uintN) cg->stackDepth +
((cs->format & JOF_TMPSLOT_MASK) >> JOF_TMPSLOT_SHIFT) +
extra;
if (depth > cg->maxStackDepth)
cg->maxStackDepth = depth;
}
nuses = js_GetStackUses(cs, op, pc); nuses = js_GetStackUses(cs, op, pc);
cg->stackDepth -= nuses; cg->stackDepth -= nuses;
@@ -244,20 +251,12 @@ UpdateDepth(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t target)
cg->maxStackDepth = cg->stackDepth; cg->maxStackDepth = cg->stackDepth;
} }
/*
* Table of decomposed lengths for each bytecode, initially zeroed. Every
* opcode always has the same decomposed code generated for it, and rather than
* track/maintain this info in a static table like jsopcode.tbl, we just update
* this table for opcodes which have actually been emitted.
*/
uint8 js_decomposeLengthTable[256] = {};
static inline void static inline void
SetDecomposeLength(JSOp op, uintN length) UpdateDecomposeLength(JSCodeGenerator *cg, uintN start)
{ {
JS_ASSERT(length < 256); uintN end = CG_OFFSET(cg);
JS_ASSERT_IF(js_decomposeLengthTable[op], js_decomposeLengthTable[op] == length); JS_ASSERT(uintN(end - start) < 256);
js_decomposeLengthTable[op] = length; CG_CODE(cg, start)[-1] = end - start;
} }
ptrdiff_t ptrdiff_t
@@ -2917,6 +2916,8 @@ EmitPropIncDec(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
{ {
if (!EmitPropOp(cx, pn, op, cg, false)) if (!EmitPropOp(cx, pn, op, cg, false))
return false; return false;
if (js_Emit1(cx, cg, JSOP_NOP) < 0)
return false;
/* /*
* The stack is the same depth before/after INCPROP, so no balancing to do * The stack is the same depth before/after INCPROP, so no balancing to do
@@ -2957,7 +2958,7 @@ EmitPropIncDec(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
if (post && js_Emit1(cx, cg, JSOP_POP) < 0) // RESULT if (post && js_Emit1(cx, cg, JSOP_POP) < 0) // RESULT
return false; return false;
SetDecomposeLength(op, CG_OFFSET(cg) - start); UpdateDecomposeLength(cg, start);
return true; return true;
} }
@@ -2967,6 +2968,8 @@ EmitNameIncDec(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
{ {
if (!EmitAtomOp(cx, pn, op, cg)) if (!EmitAtomOp(cx, pn, op, cg))
return false; return false;
if (js_Emit1(cx, cg, JSOP_NOP) < 0)
return false;
/* Remove the result to restore the stack depth before the INCNAME. */ /* Remove the result to restore the stack depth before the INCNAME. */
cg->stackDepth--; cg->stackDepth--;
@@ -3006,7 +3009,7 @@ EmitNameIncDec(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
if (post && js_Emit1(cx, cg, JSOP_POP) < 0) // RESULT if (post && js_Emit1(cx, cg, JSOP_POP) < 0) // RESULT
return false; return false;
SetDecomposeLength(op, CG_OFFSET(cg) - start); UpdateDecomposeLength(cg, start);
return true; return true;
} }
@@ -3147,6 +3150,8 @@ EmitElemIncDec(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
{ {
if (!EmitElemOp(cx, pn, op, cg)) if (!EmitElemOp(cx, pn, op, cg))
return false; return false;
if (js_Emit1(cx, cg, JSOP_NOP) < 0)
return false;
/* INCELEM pops two values and pushes one, so restore the initial depth. */ /* INCELEM pops two values and pushes one, so restore the initial depth. */
cg->stackDepth++; cg->stackDepth++;
@@ -3194,7 +3199,7 @@ EmitElemIncDec(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
if (post && js_Emit1(cx, cg, JSOP_POP) < 0) // RESULT if (post && js_Emit1(cx, cg, JSOP_POP) < 0) // RESULT
return false; return false;
SetDecomposeLength(op, CG_OFFSET(cg) - start); UpdateDecomposeLength(cg, start);
return true; return true;
} }

View File

@@ -2396,6 +2396,8 @@ BEGIN_CASE(JSOP_STOP)
JS_ASSERT((uintN)(regs.sp - regs.fp()->slots()) <= script->nslots); JS_ASSERT((uintN)(regs.sp - regs.fp()->slots()) <= script->nslots);
jsbytecode *imacpc = regs.fp()->imacropc(); jsbytecode *imacpc = regs.fp()->imacropc();
regs.pc = imacpc + js_CodeSpec[*imacpc].length; regs.pc = imacpc + js_CodeSpec[*imacpc].length;
if (js_CodeSpec[*imacpc].format & JOF_DECOMPOSE)
regs.pc += GetDecomposeLength(imacpc, js_CodeSpec[*imacpc].length);
regs.fp()->clearImacropc(); regs.fp()->clearImacropc();
LEAVE_ON_SAFE_POINT(); LEAVE_ON_SAFE_POINT();
atoms = script->atomMap.vector; atoms = script->atomMap.vector;
@@ -3489,7 +3491,7 @@ BEGIN_CASE(JSOP_GNAMEDEC)
tmp = inc; tmp = inc;
rref.getInt32Ref() = inc; rref.getInt32Ref() = inc;
PUSH_INT32(tmp); PUSH_INT32(tmp);
len = JSOP_INCNAME_LENGTH + GetDecomposeLength(op); len = JSOP_INCNAME_LENGTH + GetDecomposeLength(regs.pc, JSOP_INCNAME_LENGTH);
DO_NEXT_OP(len); DO_NEXT_OP(len);
} }
} }
@@ -3566,7 +3568,7 @@ do_incop:
regs.sp[-1 - cs->nuses] = regs.sp[-1]; regs.sp[-1 - cs->nuses] = regs.sp[-1];
regs.sp -= cs->nuses; regs.sp -= cs->nuses;
} }
len = cs->length + GetDecomposeLength(op); len = cs->length + GetDecomposeLength(regs.pc, cs->length);
DO_NEXT_OP(len); DO_NEXT_OP(len);
} }
} }

View File

@@ -4794,7 +4794,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
} }
if (cs->format & JOF_DECOMPOSE) if (cs->format & JOF_DECOMPOSE)
pc += GetDecomposeLength(op); pc += GetDecomposeLength(pc, cs->length);
pc += len; pc += len;
} }

View File

@@ -524,13 +524,14 @@ extern bool
CallResultEscapes(jsbytecode *pc); CallResultEscapes(jsbytecode *pc);
static inline uintN static inline uintN
GetDecomposeLength(JSOp op) GetDecomposeLength(jsbytecode *pc, size_t len)
{ {
/* Table of lengths, updated on demand. See SetDecomposeLength. */ /*
extern uint8 js_decomposeLengthTable[]; * The last byte of a DECOMPOSE op stores the decomposed length. This can
JS_ASSERT(js_CodeSpec[op].format & JOF_DECOMPOSE); * vary across different instances of an opcode due to INDEXBASE ops.
JS_ASSERT(js_decomposeLengthTable[op]); */
return js_decomposeLengthTable[op]; JS_ASSERT_IF(JSOp(*pc) != JSOP_TRAP, size_t(js_CodeSpec[*pc].length) == len);
return (uintN) pc[len - 1];
} }
} }

View File

@@ -160,18 +160,18 @@ OPDEF(JSOP_DELELEM, 38, "delelem", NULL, 1, 2, 1, 15, JOF_BYTE |
OPDEF(JSOP_TYPEOF, 39, js_typeof_str,NULL, 1, 1, 1, 15, JOF_BYTE|JOF_DETECTING) OPDEF(JSOP_TYPEOF, 39, js_typeof_str,NULL, 1, 1, 1, 15, JOF_BYTE|JOF_DETECTING)
OPDEF(JSOP_VOID, 40, js_void_str, NULL, 1, 1, 1, 15, JOF_BYTE) OPDEF(JSOP_VOID, 40, js_void_str, NULL, 1, 1, 1, 15, JOF_BYTE)
OPDEF(JSOP_INCNAME, 41, "incname", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_TMPSLOT3|JOF_DECOMPOSE) OPDEF(JSOP_INCNAME, 41, "incname", NULL, 4, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_TMPSLOT3|JOF_DECOMPOSE)
OPDEF(JSOP_INCPROP, 42, "incprop", NULL, 3, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_INC|JOF_TMPSLOT3|JOF_DECOMPOSE) OPDEF(JSOP_INCPROP, 42, "incprop", NULL, 4, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_INC|JOF_TMPSLOT3|JOF_DECOMPOSE)
OPDEF(JSOP_INCELEM, 43, "incelem", NULL, 1, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_INC|JOF_TMPSLOT2|JOF_DECOMPOSE) OPDEF(JSOP_INCELEM, 43, "incelem", NULL, 2, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_INC|JOF_TMPSLOT2|JOF_DECOMPOSE)
OPDEF(JSOP_DECNAME, 44, "decname", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_TMPSLOT3|JOF_DECOMPOSE) OPDEF(JSOP_DECNAME, 44, "decname", NULL, 4, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_TMPSLOT3|JOF_DECOMPOSE)
OPDEF(JSOP_DECPROP, 45, "decprop", NULL, 3, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_DEC|JOF_TMPSLOT3|JOF_DECOMPOSE) OPDEF(JSOP_DECPROP, 45, "decprop", NULL, 4, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_DEC|JOF_TMPSLOT3|JOF_DECOMPOSE)
OPDEF(JSOP_DECELEM, 46, "decelem", NULL, 1, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_DEC|JOF_TMPSLOT2|JOF_DECOMPOSE) OPDEF(JSOP_DECELEM, 46, "decelem", NULL, 2, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_DEC|JOF_TMPSLOT2|JOF_DECOMPOSE)
OPDEF(JSOP_NAMEINC, 47, "nameinc", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE) OPDEF(JSOP_NAMEINC, 47, "nameinc", NULL, 4, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE)
OPDEF(JSOP_PROPINC, 48, "propinc", NULL, 3, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_INC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE) OPDEF(JSOP_PROPINC, 48, "propinc", NULL, 4, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_INC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE)
OPDEF(JSOP_ELEMINC, 49, "eleminc", NULL, 1, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_INC|JOF_POST|JOF_TMPSLOT2|JOF_DECOMPOSE) OPDEF(JSOP_ELEMINC, 49, "eleminc", NULL, 2, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_INC|JOF_POST|JOF_TMPSLOT2|JOF_DECOMPOSE)
OPDEF(JSOP_NAMEDEC, 50, "namedec", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE) OPDEF(JSOP_NAMEDEC, 50, "namedec", NULL, 4, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE)
OPDEF(JSOP_PROPDEC, 51, "propdec", NULL, 3, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_DEC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE) OPDEF(JSOP_PROPDEC, 51, "propdec", NULL, 4, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_DEC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE)
OPDEF(JSOP_ELEMDEC, 52, "elemdec", NULL, 1, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_DEC|JOF_POST|JOF_TMPSLOT2|JOF_DECOMPOSE) OPDEF(JSOP_ELEMDEC, 52, "elemdec", NULL, 2, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_DEC|JOF_POST|JOF_TMPSLOT2|JOF_DECOMPOSE)
OPDEF(JSOP_GETPROP, 53, "getprop", NULL, 5, 1, 1, 18, JOF_ATOM|JOF_PROP|JOF_TYPESET) OPDEF(JSOP_GETPROP, 53, "getprop", NULL, 5, 1, 1, 18, JOF_ATOM|JOF_PROP|JOF_TYPESET)
OPDEF(JSOP_SETPROP, 54, "setprop", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING) OPDEF(JSOP_SETPROP, 54, "setprop", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
@@ -411,10 +411,10 @@ OPDEF(JSOP_RETRVAL, 155,"retrval", NULL, 1, 0, 0, 0, JOF_BYTE)
/* Free variable references that must either be found on the global or a ReferenceError */ /* Free variable references that must either be found on the global or a ReferenceError */
OPDEF(JSOP_GETGNAME, 156,"getgname", NULL, 5, 0, 1, 19, JOF_ATOM|JOF_NAME|JOF_TYPESET|JOF_GNAME) OPDEF(JSOP_GETGNAME, 156,"getgname", NULL, 5, 0, 1, 19, JOF_ATOM|JOF_NAME|JOF_TYPESET|JOF_GNAME)
OPDEF(JSOP_SETGNAME, 157,"setgname", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING|JOF_GNAME) OPDEF(JSOP_SETGNAME, 157,"setgname", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING|JOF_GNAME)
OPDEF(JSOP_INCGNAME, 158,"incgname", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE) OPDEF(JSOP_INCGNAME, 158,"incgname", NULL, 4, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE)
OPDEF(JSOP_DECGNAME, 159,"decgname", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE) OPDEF(JSOP_DECGNAME, 159,"decgname", NULL, 4, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE)
OPDEF(JSOP_GNAMEINC, 160,"gnameinc", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE) OPDEF(JSOP_GNAMEINC, 160,"gnameinc", NULL, 4, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE)
OPDEF(JSOP_GNAMEDEC, 161,"gnamedec", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE) OPDEF(JSOP_GNAMEDEC, 161,"gnamedec", NULL, 4, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT3|JOF_GNAME|JOF_DECOMPOSE)
/* Regular expression literal requiring special "fork on exec" handling. */ /* Regular expression literal requiring special "fork on exec" handling. */
OPDEF(JSOP_REGEXP, 162,"regexp", NULL, 3, 0, 1, 19, JOF_REGEXP) OPDEF(JSOP_REGEXP, 162,"regexp", NULL, 3, 0, 1, 19, JOF_REGEXP)

View File

@@ -222,7 +222,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id);
* before deserialization of bytecode. If the saved version does not match * before deserialization of bytecode. If the saved version does not match
* the current version, abort deserialization and invalidate the file. * the current version, abort deserialization and invalidate the file.
*/ */
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 91) #define JSXDR_BYTECODE_VERSION (0xb973c0de - 92)
/* /*
* Library-private functions. * Library-private functions.