Fix imacro vs. script code disassembly/decompilation confusion (510644, r=jorendorff).

This commit is contained in:
Brendan Eich 2009-09-04 16:27:17 -07:00
parent cf62469ed2
commit fd61e1b61a
7 changed files with 60 additions and 16 deletions

View File

@ -341,6 +341,14 @@ function assemble(filename) {
if (!imacro)
throw new Error("opcode " + opname + " outside of .imacro");
// Blacklist ops that may or must use an atomized double immediate.
switch (info.opname) {
case "double":
case "lookupswitch":
case "lookupswitchx":
throw new Error(op.opname + " opcode not yet supported");
}
if (label) {
imacro.labeldefs[label] = imacro.offset;
imacro.labeldef_indexes[label] = imacro.code.length;

View File

@ -365,7 +365,7 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc,
case JOF_REGEXP:
index = js_GetIndexFromBytecode(cx, script, pc, 0);
if (type == JOF_ATOM) {
JS_GET_SCRIPT_ATOM(script, index, atom);
JS_GET_SCRIPT_ATOM(script, pc, index, atom);
v = ATOM_KEY(atom);
} else {
if (type == JOF_OBJECT)
@ -424,7 +424,7 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc,
pc2 += UINT16_LEN;
fprintf(fp, " offset %d npairs %u", (intN) off, (uintN) npairs);
while (npairs) {
JS_GET_SCRIPT_ATOM(script, GET_INDEX(pc2), atom);
JS_GET_SCRIPT_ATOM(script, pc, GET_INDEX(pc2), atom);
pc2 += INDEX_LEN;
off = GetJumpOffset(pc, pc2);
pc2 += jmplen;
@ -452,7 +452,7 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc,
fprintf(fp, " %u", GET_SLOTNO(pc));
index = js_GetIndexFromBytecode(cx, script, pc, SLOTNO_LEN);
if (type == JOF_SLOTATOM) {
JS_GET_SCRIPT_ATOM(script, index, atom);
JS_GET_SCRIPT_ATOM(script, pc, index, atom);
v = ATOM_KEY(atom);
} else {
JS_GET_SCRIPT_OBJECT(script, index, obj);
@ -1345,6 +1345,9 @@ IsVarSlot(JSPrinter *jp, jsbytecode *pc, jsint *indexp)
return JS_FALSE;
}
#define LOAD_ATOM(PCOFF) \
GET_ATOM_FROM_BYTECODE(jp->script, pc, PCOFF, atom)
#if JS_HAS_DESTRUCTURING
#define LOCAL_ASSERT(expr) LOCAL_ASSERT_RV(expr, NULL)
@ -1405,7 +1408,7 @@ DecompileDestructuringLHS(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc,
atom = GetArgOrVarAtom(jp, GET_SLOTNO(pc));
LOCAL_ASSERT(atom);
} else if (op == JSOP_SETGVAR) {
GET_ATOM_FROM_BYTECODE(jp->script, pc, 0, atom);
LOAD_ATOM(0);
} else if (IsVarSlot(jp, pc, &i)) {
atom = GetArgOrVarAtom(jp, i);
LOCAL_ASSERT(atom);
@ -1539,7 +1542,7 @@ DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc)
case JSOP_INT32: d = i = GET_INT32(pc); goto do_getelem;
case JSOP_DOUBLE:
GET_ATOM_FROM_BYTECODE(jp->script, pc, 0, atom);
GET_DOUBLE_FROM_BYTECODE(jp->script, pc, 0, atom);
d = *ATOM_TO_DOUBLE(atom);
LOCAL_ASSERT(JSDOUBLE_IS_FINITE(d) && !JSDOUBLE_IS_NEGZERO(d));
i = (jsint)d;
@ -1575,7 +1578,7 @@ DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc)
case JSOP_CALLPROP:
case JSOP_GETPROP:
GET_ATOM_FROM_BYTECODE(jp->script, pc, 0, atom);
LOAD_ATOM(0);
do_destructure_atom:
*OFF2STR(&ss->sprinter, head) = '{';
str = ATOM_TO_STRING(atom);
@ -1858,9 +1861,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
return NULL; \
JS_END_MACRO
#define LOAD_ATOM(PCOFF) \
GET_ATOM_FROM_BYTECODE(jp->script, pc, PCOFF, atom)
#define LOAD_OBJECT(PCOFF) \
GET_OBJECT_FROM_BYTECODE(jp->script, pc, PCOFF, obj)
@ -3993,7 +3993,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
break;
case JSOP_DOUBLE:
LOAD_ATOM(0);
GET_DOUBLE_FROM_BYTECODE(jp->script, pc, 0, atom);
val = ATOM_KEY(atom);
LOCAL_ASSERT(JSVAL_IS_DOUBLE(val));
todo = SprintDoubleValue(&ss->sprinter, val, &saveop);
@ -4272,7 +4272,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
} else {
table[k].label = NULL;
}
JS_GET_SCRIPT_ATOM(jp->script, GET_INDEX(pc2), atom);
JS_GET_SCRIPT_ATOM(jp->script, pc, GET_INDEX(pc2), atom);
pc2 += INDEX_LEN;
off2 = GetJumpOffset(pc, pc2);
pc2 += jmplen;

View File

@ -311,8 +311,27 @@ js_GetIndexFromBytecode(JSContext *cx, JSScript *script, jsbytecode *pc,
*/
#define GET_ATOM_FROM_BYTECODE(script, pc, pcoff, atom) \
JS_BEGIN_MACRO \
JS_ASSERT(*(pc) != JSOP_DOUBLE); \
uintN index_ = js_GetIndexFromBytecode(cx, (script), (pc), (pcoff)); \
JS_GET_SCRIPT_ATOM((script), index_, atom); \
JS_GET_SCRIPT_ATOM(script, pc, index_, atom); \
JS_END_MACRO
/*
* Variant for getting a double atom when we might be in an imacro. Bytecodes
* with literals that are only ever doubles must use this macro, and never use
* GET_ATOM_FROM_BYTECODE or JS_GET_SCRIPT_ATOM.
*
* Unfortunately some bytecodes such as JSOP_LOOKUPSWITCH have immediates that
* might be string or double atoms. Those opcodes cannot be used from imacros.
* See the assertions in the JSOP_DOUBLE and JSOP_LOOKUPSWTICH* opcode cases in
* jsops.cpp.
*/
#define GET_DOUBLE_FROM_BYTECODE(script, pc, pcoff, atom) \
JS_BEGIN_MACRO \
uintN index_ = js_GetIndexFromBytecode(cx, (script), (pc), (pcoff)); \
JS_ASSERT(index_ < (script)->atomMap.length); \
(atom) = (script)->atomMap.vector[index_]; \
JS_ASSERT(ATOM_IS_DOUBLE(atom)); \
JS_END_MACRO
#define GET_OBJECT_FROM_BYTECODE(script, pc, pcoff, obj) \

View File

@ -2395,6 +2395,10 @@
END_CASE(JSOP_RESETBASE)
BEGIN_CASE(JSOP_DOUBLE)
JS_ASSERT(!fp->imacpc);
JS_ASSERT(atoms == script->atomMap.vector);
/* FALL THROUGH */
BEGIN_CASE(JSOP_STRING)
LOAD_ATOM(0);
PUSH_OPND(ATOM_KEY(atom));
@ -2617,6 +2621,7 @@
* JSOP_LOOKUPSWITCH and JSOP_LOOKUPSWITCHX are never used if
* any atom index in it would exceed 64K limit.
*/
JS_ASSERT(!fp->imacpc);
JS_ASSERT(atoms == script->atomMap.vector);
pc2 = regs.pc;
lval = POP_OPND();

View File

@ -161,10 +161,15 @@ StackDepth(JSScript *script)
(JS_ASSERT((script)->trynotesOffset != 0), \
(JSTryNoteArray *)((uint8 *)(script) + (script)->trynotesOffset))
#define JS_GET_SCRIPT_ATOM(script_, index, atom) \
/*
* If pc_ does not point within script_'s bytecode, then it must point into an
* imacro body, so we use cx->runtime common atoms instead of script_'s atoms.
* This macro uses cx from its callers' environments in the pc-in-imacro case.
*/
#define JS_GET_SCRIPT_ATOM(script_, pc_, index, atom) \
JS_BEGIN_MACRO \
JSStackFrame *fp_ = js_GetTopStackFrame(cx); \
if (fp_ && fp_->imacpc && fp_->script == script_) { \
if ((pc_) < (script_)->code || \
(script_)->code + (script_)->length <= (pc_)) { \
JS_ASSERT((size_t)(index) < js_common_atom_count); \
(atom) = COMMON_ATOMS_START(&cx->runtime->atomState)[index]; \
} else { \

View File

@ -1619,7 +1619,7 @@ SrcNotes(JSContext *cx, JSScript *script)
case SRC_BREAK2LABEL:
case SRC_CONT2LABEL:
index = js_GetSrcNoteOffset(sn, 0);
JS_GET_SCRIPT_ATOM(script, index, atom);
JS_GET_SCRIPT_ATOM(script, NULL, index, atom);
JS_ASSERT(ATOM_IS_STRING(atom));
str = ATOM_TO_STRING(atom);
fprintf(gOutFile, " atom %u (", index);

View File

@ -0,0 +1,7 @@
function f() {
for (var i=0; i<9; i++)
assertEq("" + f, expected);
}
var expected = "" + f;
f();