Allow up to 2^23 literals in a script (155081, r=shaver, a=me).

This commit is contained in:
brendan%mozilla.org 2005-04-23 02:14:20 +00:00
Родитель 94e828fc62
Коммит ca6ebfbcf0
5 изменённых файлов: 486 добавлений и 228 удалений

Просмотреть файл

@ -1230,15 +1230,17 @@ js_PushStatement(JSTreeContext *tc, JSStmtInfo *stmt, JSStmtType type,
* Emit a backpatch op with offset pointing to the previous jump of this type,
* so that we can walk back up the chain fixing up the op and jump offset.
*/
#define EMIT_BACKPATCH_OP(cx, cg, last, op, jmp) \
JS_BEGIN_MACRO \
ptrdiff_t offset, delta; \
offset = CG_OFFSET(cg); \
delta = offset - (last); \
last = offset; \
JS_ASSERT(delta > 0); \
jmp = EmitJump((cx), (cg), (op), (delta)); \
JS_END_MACRO
static ptrdiff_t
EmitBackPatchOp(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t *lastp)
{
ptrdiff_t offset, delta;
offset = CG_OFFSET(cg);
delta = offset - *lastp;
*lastp = offset;
JS_ASSERT(delta > 0);
return EmitJump(cx, cg, op, delta);
}
/* Emit additional bytecode(s) for non-local jumps. */
static JSBool
@ -1297,7 +1299,7 @@ EmitNonLocalJumpFixup(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt,
case STMT_FINALLY:
if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
return JS_FALSE;
EMIT_BACKPATCH_OP(cx, cg, stmt->gosub, JSOP_BACKPATCH_PUSH, jmp);
jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH_PUSH, &stmt->gosub);
if (jmp < 0)
return JS_FALSE;
break;
@ -1338,10 +1340,9 @@ EmitNonLocalJumpFixup(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt,
static ptrdiff_t
EmitGoto(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt,
ptrdiff_t *last, JSAtomListElement *label, JSSrcNoteType noteType)
ptrdiff_t *lastp, JSAtomListElement *label, JSSrcNoteType noteType)
{
intN index;
ptrdiff_t jmp;
if (!EmitNonLocalJumpFixup(cx, cg, toStmt, NULL))
return -1;
@ -1359,8 +1360,7 @@ EmitGoto(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt,
return -1;
}
EMIT_BACKPATCH_OP(cx, cg, *last, JSOP_BACKPATCH, jmp);
return jmp;
return EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, lastp);
}
static JSBool
@ -1590,16 +1590,94 @@ IndexRegExpClone(JSContext *cx, JSParseNode *pn, JSAtomListElement *ale,
}
/*
* Emit a bytecode and its 2-byte constant (atom) index immediate operand.
* Macro to emit a bytecode followed by a uint16 immediate operand stored in
* big-endian order, used for arg and var numbers as well as for atomIndexes.
* NB: We use cx and cg from our caller's lexical environment, and return
* false on error.
*/
#define EMIT_UINT16_IMM_OP(op, i) \
JS_BEGIN_MACRO \
if (js_Emit3(cx, cg, op, ATOM_INDEX_HI(i), ATOM_INDEX_LO(i)) < 0) \
return JS_FALSE; \
JS_END_MACRO
/*
* Emit a bytecode and its 2-byte constant (atom) index immediate operand.
* If the atomIndex requires more than 2 bytes, emit a prefix op whose 24-bit
* immediate operand indexes the atom in script->atomMap.
*
* If op has JOF_NAME mode, emit JSOP_FINDNAME to find and push the object in
* the scope chain in which the literal name was found, followed by the name
* as a string. This enables us to use the JOF_ELEM counterpart to op.
*
* Otherwise, if op has JOF_PROP mode, emit JSOP_LITERAL before op, to push
* the atom's value key. For JOF_PROP ops, the object being operated on has
* already been pushed, and JSOP_LITERAL will push the id, leaving the stack
* in the proper state for a JOF_ELEM counterpart.
*
* Otherwise, emit JSOP_LITOPX to push the atom index, then perform a special
* dispatch on op, but getting op's atom index from the stack instead of from
* an unsigned 16-bit immediate operand.
*/
static JSBool
EmitAtomIndexOp(JSContext *cx, JSOp op, jsatomid atomIndex, JSCodeGenerator *cg)
{
uint32 mode;
JSOp prefixOp;
ptrdiff_t off;
jsbytecode *pc;
if (atomIndex >= JS_BIT(16)) {
mode = (js_CodeSpec[op].format & JOF_MODEMASK);
prefixOp = (mode == JOF_NAME)
? JSOP_FINDNAME
: (mode == JOF_PROP)
? JSOP_LITERAL
: JSOP_LITOPX;
off = js_EmitN(cx, cg, prefixOp, 3);
if (off < 0)
return JS_FALSE;
pc = CG_CODE(cg, off);
SET_LITERAL_INDEX(pc, atomIndex);
switch (op) {
case JSOP_DECNAME: op = JSOP_DECELEM; break;
case JSOP_DECPROP: op = JSOP_DECELEM; break;
case JSOP_DELNAME: op = JSOP_DELELEM; break;
case JSOP_DELPROP: op = JSOP_DELELEM; break;
case JSOP_FORNAME: op = JSOP_FORELEM; break;
case JSOP_FORPROP: op = JSOP_FORELEM; break;
case JSOP_GETPROP: op = JSOP_GETELEM; break;
case JSOP_IMPORTPROP: op = JSOP_IMPORTELEM; break;
case JSOP_INCNAME: op = JSOP_INCELEM; break;
case JSOP_INCPROP: op = JSOP_INCELEM; break;
case JSOP_INITPROP: op = JSOP_INITELEM; break;
case JSOP_NAME: op = JSOP_GETELEM; break;
case JSOP_NAMEDEC: op = JSOP_ELEMDEC; break;
case JSOP_NAMEINC: op = JSOP_ELEMINC; break;
case JSOP_PROPDEC: op = JSOP_ELEMDEC; break;
case JSOP_PROPINC: op = JSOP_ELEMINC; break;
case JSOP_SETNAME: op = JSOP_SETELEM; break;
case JSOP_SETPROP: op = JSOP_SETELEM; break;
default: JS_ASSERT(mode == 0); break;
}
return js_Emit1(cx, cg, op) >= 0;
}
EMIT_UINT16_IMM_OP(op, atomIndex);
return JS_TRUE;
}
/*
* Slight sugar for EmitAtomIndexOp, again accessing cx and cg from the macro
* caller's lexical environment, and embedding a false return on error.
* XXXbe hey, who checks for fun->nvars and fun->nargs overflow?!
*/
#define EMIT_ATOM_INDEX_OP(op, atomIndex) \
JS_BEGIN_MACRO \
if (js_Emit3(cx, cg, op, ATOM_INDEX_HI(atomIndex), \
ATOM_INDEX_LO(atomIndex)) < 0) { \
if (!EmitAtomIndexOp(cx, op, atomIndex, cg) < 0) \
return JS_FALSE; \
} \
JS_END_MACRO
static JSBool
@ -1612,8 +1690,7 @@ EmitAtomOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
return JS_FALSE;
if (op == JSOP_REGEXP && !IndexRegExpClone(cx, pn, ale, cg))
return JS_FALSE;
EMIT_ATOM_INDEX_OP(op, ALE_INDEX(ale));
return JS_TRUE;
return EmitAtomIndexOp(cx, op, ALE_INDEX(ale), cg);
}
/*
@ -2059,9 +2136,9 @@ EmitElemOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
return JS_FALSE;
if (left->pn_op == JSOP_ARGUMENTS &&
JSDOUBLE_IS_INT(next->pn_dval, slot) &&
(jsuint)slot < ATOM_INDEX_LIMIT) {
(jsuint)slot < JS_BIT(16)) {
left->pn_offset = next->pn_offset = top;
EMIT_ATOM_INDEX_OP(JSOP_ARGSUB, (jsatomid)slot);
EMIT_UINT16_IMM_OP(JSOP_ARGSUB, (jsatomid)slot);
left = next;
next = left->pn_next;
}
@ -2101,9 +2178,9 @@ EmitElemOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
return JS_FALSE;
if (left->pn_op == JSOP_ARGUMENTS &&
JSDOUBLE_IS_INT(right->pn_dval, slot) &&
(jsuint)slot < ATOM_INDEX_LIMIT) {
(jsuint)slot < JS_BIT(16)) {
left->pn_offset = right->pn_offset = top;
EMIT_ATOM_INDEX_OP(JSOP_ARGSUB, (jsatomid)slot);
EMIT_UINT16_IMM_OP(JSOP_ARGSUB, (jsatomid)slot);
return JS_TRUE;
}
}
@ -2123,6 +2200,8 @@ EmitNumberOp(JSContext *cx, jsdouble dval, JSCodeGenerator *cg)
{
jsint ival;
jsatomid atomIndex;
ptrdiff_t off;
jsbytecode *pc;
JSAtom *atom;
JSAtomListElement *ale;
@ -2131,22 +2210,33 @@ EmitNumberOp(JSContext *cx, jsdouble dval, JSCodeGenerator *cg)
return js_Emit1(cx, cg, JSOP_ZERO) >= 0;
if (ival == 1)
return js_Emit1(cx, cg, JSOP_ONE) >= 0;
if ((jsuint)ival < (jsuint)ATOM_INDEX_LIMIT) {
atomIndex = (jsatomid)ival;
EMIT_ATOM_INDEX_OP(JSOP_UINT16, atomIndex);
atomIndex = (jsatomid)ival;
if (atomIndex < JS_BIT(16)) {
EMIT_UINT16_IMM_OP(JSOP_UINT16, atomIndex);
return JS_TRUE;
}
if (atomIndex < JS_BIT(24)) {
off = js_EmitN(cx, cg, JSOP_UINT24, 3);
if (off < 0)
return JS_FALSE;
pc = CG_CODE(cg, off);
SET_LITERAL_INDEX(pc, atomIndex);
return JS_TRUE;
}
atom = js_AtomizeInt(cx, ival, 0);
} else {
atom = js_AtomizeDouble(cx, dval, 0);
}
if (!atom)
return JS_FALSE;
ale = js_IndexAtom(cx, atom, &cg->atomList);
if (!ale)
return JS_FALSE;
EMIT_ATOM_INDEX_OP(JSOP_NUMBER, ALE_INDEX(ale));
return JS_TRUE;
return EmitAtomIndexOp(cx, JSOP_NUMBER, ALE_INDEX(ale), cg);
}
#if JS_HAS_SWITCH_STATEMENT
@ -2787,14 +2877,28 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
slot = ((JSScopeProperty *) prop)->shortid;
OBJ_DROP_PROPERTY(cx, pobj, prop);
/* Emit [JSOP_DEFLOCALFUN, local variable slot, atomIndex]. */
off = js_EmitN(cx, cg, JSOP_DEFLOCALFUN, VARNO_LEN+ATOM_INDEX_LEN);
if (off < 0)
return JS_FALSE;
pc = CG_CODE(cg, off);
SET_VARNO(pc, slot);
pc += VARNO_LEN;
SET_ATOM_INDEX(pc, atomIndex);
if (atomIndex >= JS_BIT(16)) {
/*
* Lots of literals in the outer function, so we have to emit
* [JSOP_LITOPX, atomIndex, JSOP_DEFLOCALFUN, var slot].
*/
off = js_EmitN(cx, cg, JSOP_LITOPX, 3);
if (off < 0)
return JS_FALSE;
pc = CG_CODE(cg, off);
SET_LITERAL_INDEX(pc, atomIndex);
EMIT_UINT16_IMM_OP(JSOP_DEFLOCALFUN, slot);
} else {
/* Emit [JSOP_DEFLOCALFUN, var slot, atomIndex]. */
off = js_EmitN(cx, cg, JSOP_DEFLOCALFUN,
VARNO_LEN + ATOM_INDEX_LEN);
if (off < 0)
return JS_FALSE;
pc = CG_CODE(cg, off);
SET_VARNO(pc, slot);
pc += VARNO_LEN;
SET_ATOM_INDEX(pc, atomIndex);
}
} else
#endif
EMIT_ATOM_INDEX_OP(JSOP_DEFFUN, atomIndex);
@ -3030,7 +3134,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
SET_STATEMENT_TOP(&stmtInfo, top);
#if JS_HAS_XML_SUPPORT
/* Emit a for each prefix. */
/* Emit a prefix opcode if 'for each (... in ...)' was used. */
if (pn->pn_op != JSOP_NOP && js_Emit1(cx, cg, pn->pn_op) < 0)
return JS_FALSE;
#endif
@ -3065,7 +3169,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
if (pn3->pn_attrs & JSPROP_READONLY)
op = JSOP_GETVAR;
atomIndex = (jsatomid) pn3->pn_slot;
EMIT_ATOM_INDEX_OP(op, atomIndex);
EMIT_UINT16_IMM_OP(op, atomIndex);
} else {
if (!EmitAtomOp(cx, pn3, op, cg))
return JS_FALSE;
@ -3294,14 +3398,6 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
/* Quell GCC overwarnings. */
end = catchStart = finallyCatch = catchJump = -1;
/* Emit JSOP_GOTO that points to the first op after the catch/finally blocks */
#define EMIT_CATCH_GOTO(cx, cg, jmp) \
EMIT_BACKPATCH_OP(cx, cg, stmtInfo.catchJump, JSOP_BACKPATCH, jmp)
/* Emit JSOP_GOSUB that points to the finally block. */
#define EMIT_FINALLY_GOSUB(cx, cg, jmp) \
EMIT_BACKPATCH_OP(cx, cg, stmtInfo.gosub, JSOP_BACKPATCH_PUSH, jmp)
/*
* Push stmtInfo to track jumps-over-catches and gosubs-to-finally
* for later fixup.
@ -3309,7 +3405,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
* When a finally block is `active' (STMT_FINALLY on the treeContext),
* non-local jumps (including jumps-over-catches) result in a GOSUB
* being written into the bytecode stream and fixed-up later (c.f.
* EMIT_BACKPATCH_OP and BackPatch).
* EmitBackPatchOp and BackPatch).
*/
js_PushStatement(&cg->treeContext, &stmtInfo,
pn->pn_kid3 ? STMT_FINALLY : STMT_BLOCK,
@ -3339,7 +3435,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
if (pn->pn_kid3) {
if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
return JS_FALSE;
EMIT_FINALLY_GOSUB(cx, cg, jmp);
jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH_PUSH, &stmtInfo.gosub);
if (jmp < 0)
return JS_FALSE;
}
@ -3347,7 +3443,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
/* Emit (hidden) jump over catch and/or finally. */
if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
return JS_FALSE;
EMIT_CATCH_GOTO(cx, cg, jmp);
jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, &stmtInfo.catchJump);
if (jmp < 0)
return JS_FALSE;
@ -3402,7 +3498,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
}
} else {
/* Set stack to original depth (see SETSP comment above). */
EMIT_ATOM_INDEX_OP(JSOP_SETSP, (jsatomid)depth);
EMIT_UINT16_IMM_OP(JSOP_SETSP, (jsatomid)depth);
cg->stackDepth = depth;
}
@ -3475,7 +3571,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
/* gosub <finally>, if required */
if (pn->pn_kid3) {
EMIT_FINALLY_GOSUB(cx, cg, jmp);
jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH_PUSH,
&stmtInfo.gosub);
if (jmp < 0)
return JS_FALSE;
}
@ -3483,7 +3580,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
/* This will get fixed up to jump to after catch/finally. */
if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
return JS_FALSE;
EMIT_CATCH_GOTO(cx, cg, jmp);
jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH,
&stmtInfo.catchJump);
if (jmp < 0)
return JS_FALSE;
if (!iter->pn_kid2) /* leave iter at last catch */
@ -3507,7 +3605,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
* stack fixup.
*/
finallyCatch = CG_OFFSET(cg);
EMIT_ATOM_INDEX_OP(JSOP_SETSP, (jsatomid)depth);
EMIT_UINT16_IMM_OP(JSOP_SETSP, (jsatomid)depth);
cg->stackDepth = depth;
/* Last discriminant jumps to rethrow if none match. */
@ -3515,7 +3613,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, catchJump);
if (pn->pn_kid3) {
EMIT_FINALLY_GOSUB(cx, cg, jmp);
jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH_PUSH,
&stmtInfo.gosub);
if (jmp < 0)
return JS_FALSE;
cg->stackDepth = depth;
@ -3666,6 +3765,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
if (op == JSOP_ARGUMENTS) {
if (js_Emit1(cx, cg, op) < 0)
return JS_FALSE;
} else if (pn2->pn_slot >= 0) {
EMIT_UINT16_IMM_OP(op, atomIndex);
} else {
EMIT_ATOM_INDEX_OP(op, atomIndex);
}
@ -3898,7 +3999,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
switch (pn2->pn_type) {
case TOK_NAME:
if (pn2->pn_op != JSOP_SETNAME) {
EMIT_ATOM_INDEX_OP((pn2->pn_op == JSOP_SETGVAR)
EMIT_UINT16_IMM_OP((pn2->pn_op == JSOP_SETGVAR)
? JSOP_GETGVAR
: (pn2->pn_op == JSOP_SETARG)
? JSOP_GETARG
@ -3951,7 +4052,11 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
case TOK_NAME:
if (pn2->pn_slot < 0 || !(pn2->pn_attrs & JSPROP_READONLY)) {
case TOK_DOT:
EMIT_ATOM_INDEX_OP(pn2->pn_op, atomIndex);
if (pn2->pn_slot >= 0) {
EMIT_UINT16_IMM_OP(pn2->pn_op, atomIndex);
} else {
EMIT_ATOM_INDEX_OP(pn2->pn_op, atomIndex);
}
}
break;
case TOK_LB:
@ -4149,7 +4254,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
: JSOP_GETVAR;
}
atomIndex = (jsatomid) pn2->pn_slot;
EMIT_ATOM_INDEX_OP(op, atomIndex);
EMIT_UINT16_IMM_OP(op, atomIndex);
} else {
if (!EmitAtomOp(cx, pn2, op, cg))
return JS_FALSE;
@ -4351,25 +4456,16 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
pn2 = pn->pn_head;
#if JS_HAS_SHARP_VARS
if (pn2 && pn2->pn_type == TOK_DEFSHARP) {
EMIT_ATOM_INDEX_OP(JSOP_DEFSHARP, (jsatomid)pn2->pn_num);
EMIT_UINT16_IMM_OP(JSOP_DEFSHARP, (jsatomid)pn2->pn_num);
pn2 = pn2->pn_next;
}
#endif
for (atomIndex = 0; pn2; pn2 = pn2->pn_next) {
/* PrimaryExpr enforced ATOM_INDEX_LIMIT, so in-line optimize. */
JS_ASSERT(atomIndex < ATOM_INDEX_LIMIT);
if (atomIndex == 0) {
if (js_Emit1(cx, cg, JSOP_ZERO) < 0)
return JS_FALSE;
} else if (atomIndex == 1) {
if (js_Emit1(cx, cg, JSOP_ONE) < 0)
return JS_FALSE;
} else {
EMIT_ATOM_INDEX_OP(JSOP_UINT16, (jsatomid)atomIndex);
}
for (atomIndex = 0; pn2; atomIndex++, pn2 = pn2->pn_next) {
if (!EmitNumberOp(cx, atomIndex, cg))
return JS_FALSE;
/* Sub-optimal: holes in a sparse initializer are void-filled. */
/* FIXME 260106: holes in a sparse initializer are void-filled. */
if (pn2->pn_type == TOK_COMMA) {
if (js_Emit1(cx, cg, JSOP_PUSH) < 0)
return JS_FALSE;
@ -4377,10 +4473,9 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
if (!js_EmitTree(cx, cg, pn2))
return JS_FALSE;
}
if (js_Emit1(cx, cg, JSOP_INITELEM) < 0)
return JS_FALSE;
atomIndex++;
}
if (pn->pn_extra & PNX_ENDCOMMA) {
@ -4415,7 +4510,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
pn2 = pn->pn_head;
#if JS_HAS_SHARP_VARS
if (pn2 && pn2->pn_type == TOK_DEFSHARP) {
EMIT_ATOM_INDEX_OP(JSOP_DEFSHARP, (jsatomid)pn2->pn_num);
EMIT_UINT16_IMM_OP(JSOP_DEFSHARP, (jsatomid)pn2->pn_num);
pn2 = pn2->pn_next;
}
#endif
@ -4469,11 +4564,11 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
case TOK_DEFSHARP:
if (!js_EmitTree(cx, cg, pn->pn_kid))
return JS_FALSE;
EMIT_ATOM_INDEX_OP(JSOP_DEFSHARP, (jsatomid) pn->pn_num);
EMIT_UINT16_IMM_OP(JSOP_DEFSHARP, (jsatomid) pn->pn_num);
break;
case TOK_USESHARP:
EMIT_ATOM_INDEX_OP(JSOP_USESHARP, (jsatomid) pn->pn_num);
EMIT_UINT16_IMM_OP(JSOP_USESHARP, (jsatomid) pn->pn_num);
break;
#endif /* JS_HAS_SHARP_VARS */
#endif /* JS_HAS_INITIALIZERS */
@ -4501,7 +4596,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
}
if (pn->pn_slot >= 0) {
atomIndex = (jsatomid) pn->pn_slot;
EMIT_ATOM_INDEX_OP(op, atomIndex);
EMIT_UINT16_IMM_OP(op, atomIndex);
break;
}
/* FALL THROUGH */
@ -4654,21 +4749,13 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
break;
case TOK_XMLPI:
off = js_EmitN(cx, cg, JSOP_XMLPI, 2 * ATOM_INDEX_LEN);
if (off < 0)
return JS_FALSE;
pc = CG_CODE(cg, off);
ale = js_IndexAtom(cx, pn->pn_atom, &cg->atomList);
if (!ale)
return JS_FALSE;
atomIndex = ALE_INDEX(ale);
SET_ATOM_INDEX(pc, atomIndex);
pc += ATOM_INDEX_LEN;
ale = js_IndexAtom(cx, pn->pn_atom2, &cg->atomList);
if (!ale)
return JS_FALSE;
atomIndex = ALE_INDEX(ale);
SET_ATOM_INDEX(pc, atomIndex);
if (!EmitAtomIndexOp(cx, JSOP_STRING, ALE_INDEX(ale), cg))
return JS_FALSE;
if (!EmitAtomOp(cx, pn, JSOP_XMLPI, cg))
return JS_FALSE;
break;
#endif /* JS_HAS_XML_SUPPORT */

Просмотреть файл

@ -1857,6 +1857,7 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
jsbytecode *endpc, *pc2;
JSOp op, op2;
const JSCodeSpec *cs;
jsatomid atomIndex;
JSAtom *atom;
uintN argc, slot, attrs;
jsval *vp, lval, rval, ltmp, rtmp;
@ -2682,9 +2683,17 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
} \
JS_END_MACRO
case JSOP_SETCONST:
#define BEGIN_LITOPX_CASE(OP,PCOFF) \
case OP: \
atomIndex = GET_ATOM_INDEX(pc + PCOFF); \
do_##OP: \
atom = js_GetAtom(cx, &script->atomMap, atomIndex);
#define END_LITOPX_CASE \
break; \
BEGIN_LITOPX_CASE(JSOP_SETCONST, 0)
obj = fp->varobj;
atom = GET_ATOM(cx, script, pc);
rval = FETCH_OPND(-1);
SAVE_SP(fp);
ok = OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval,
@ -2695,10 +2704,9 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
if (!ok)
goto out;
STORE_OPND(-1, rval);
break;
END_LITOPX_CASE
case JSOP_BINDNAME:
atom = GET_ATOM(cx, script, pc);
BEGIN_LITOPX_CASE(JSOP_BINDNAME, 0)
SAVE_SP(fp);
obj = js_FindIdentifierBase(cx, ATOM_TO_JSID(atom));
if (!obj) {
@ -2706,7 +2714,7 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
goto out;
}
PUSH_OPND(OBJECT_TO_JSVAL(obj));
break;
END_LITOPX_CASE
case JSOP_SETNAME:
atom = GET_ATOM(cx, script, pc);
@ -3708,16 +3716,78 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
PUSH_OPND(rval);
obj = NULL;
break;
case JSOP_UINT24:
i = (jsint) GET_LITERAL_INDEX(pc);
rval = INT_TO_JSVAL(i);
PUSH_OPND(rval);
break;
case JSOP_NUMBER:
case JSOP_STRING:
case JSOP_OBJECT:
atom = GET_ATOM(cx, script, pc);
case JSOP_LITERAL:
atomIndex = GET_LITERAL_INDEX(pc);
atom = js_GetAtom(cx, &script->atomMap, atomIndex);
PUSH_OPND(ATOM_KEY(atom));
obj = NULL;
break;
case JSOP_REGEXP:
case JSOP_FINDNAME:
atomIndex = GET_LITERAL_INDEX(pc);
atom = js_GetAtom(cx, &script->atomMap, atomIndex);
SAVE_SP(fp);
obj = js_FindIdentifierBase(cx, ATOM_TO_JSID(atom));
if (!obj) {
ok = JS_FALSE;
goto out;
}
PUSH_OPND(OBJECT_TO_JSVAL(obj));
PUSH_OPND(ATOM_KEY(atom));
break;
case JSOP_LITOPX:
atomIndex = GET_LITERAL_INDEX(pc);
op = pc[1 + LITERAL_INDEX_LEN];
switch (op) {
case JSOP_ANONFUNOBJ: goto do_JSOP_ANONFUNOBJ;
case JSOP_BINDNAME: goto do_JSOP_BINDNAME;
case JSOP_CLOSURE: goto do_JSOP_CLOSURE;
case JSOP_DEFCONST: goto do_JSOP_DEFCONST;
case JSOP_DEFFUN: goto do_JSOP_DEFFUN;
case JSOP_DEFLOCALFUN: goto do_JSOP_DEFLOCALFUN;
case JSOP_DEFVAR: goto do_JSOP_DEFVAR;
case JSOP_EXPORTNAME: goto do_JSOP_EXPORTNAME;
case JSOP_GETMETHOD: goto do_JSOP_GETMETHOD;
case JSOP_INITCATCHVAR: goto do_JSOP_INITCATCHVAR;
case JSOP_NAMEDFUNOBJ: goto do_JSOP_NAMEDFUNOBJ;
case JSOP_NUMBER: goto do_JSOP_NUMBER;
case JSOP_OBJECT: goto do_JSOP_OBJECT;
case JSOP_QNAMECONST: goto do_JSOP_QNAMECONST;
case JSOP_QNAMEPART: goto do_JSOP_QNAMEPART;
case JSOP_REGEXP: goto do_JSOP_REGEXP;
case JSOP_SETCONST: goto do_JSOP_SETCONST;
case JSOP_STRING: goto do_JSOP_STRING;
case JSOP_XMLCDATA: goto do_JSOP_XMLCDATA;
case JSOP_XMLCOMMENT: goto do_JSOP_XMLCOMMENT;
case JSOP_XMLOBJECT: goto do_JSOP_XMLOBJECT;
case JSOP_XMLPI: goto do_JSOP_XMLPI;
default: JS_ASSERT(0);
}
/* NOTREACHED */
break;
case JSOP_NUMBER:
case JSOP_STRING:
case JSOP_OBJECT:
atomIndex = GET_ATOM_INDEX(pc);
do_JSOP_NUMBER:
do_JSOP_STRING:
do_JSOP_OBJECT:
atom = js_GetAtom(cx, &script->atomMap, atomIndex);
PUSH_OPND(ATOM_KEY(atom));
obj = NULL;
break;
BEGIN_LITOPX_CASE(JSOP_REGEXP, 0)
{
JSRegExp *re;
JSObject *funobj;
@ -3746,7 +3816,6 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
* need a similar op for other kinds of object literals, we should
* push cloning down under JSObjectOps and reuse code here.
*/
atom = GET_ATOM(cx, script, pc);
JS_ASSERT(ATOM_IS_OBJECT(atom));
obj = ATOM_TO_OBJECT(atom);
JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_RegExpClass);
@ -3829,8 +3898,8 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
PUSH_OPND(rval);
obj = NULL;
break;
}
END_LITOPX_CASE
case JSOP_ZERO:
PUSH_OPND(JSVAL_ZERO);
@ -4062,8 +4131,7 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
}
break;
case JSOP_EXPORTNAME:
atom = GET_ATOM(cx, script, pc);
BEGIN_LITOPX_CASE(JSOP_EXPORTNAME, 0)
id = ATOM_TO_JSID(atom);
obj = fp->varobj;
SAVE_SP(fp);
@ -4083,7 +4151,7 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
}
if (!ok)
goto out;
break;
END_LITOPX_CASE
case JSOP_IMPORTALL:
id = (jsid) JSVAL_VOID;
@ -4244,10 +4312,10 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
case JSOP_DEFCONST:
case JSOP_DEFVAR:
{
jsatomid atomIndex;
atomIndex = GET_ATOM_INDEX(pc);
do_JSOP_DEFCONST:
do_JSOP_DEFVAR:
atom = js_GetAtom(cx, &script->atomMap, atomIndex);
obj = fp->varobj;
attrs = JSPROP_ENUMERATE;
@ -4298,11 +4366,9 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
OBJ_DROP_PROPERTY(cx, obj2, prop);
break;
}
case JSOP_DEFFUN:
BEGIN_LITOPX_CASE(JSOP_DEFFUN, 0)
{
jsatomid atomIndex;
uintN flags;
atomIndex = GET_ATOM_INDEX(pc);
@ -4416,11 +4482,11 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
}
#endif
OBJ_DROP_PROPERTY(cx, parent, prop);
break;
}
END_LITOPX_CASE
#if JS_HAS_LEXICAL_CLOSURE
case JSOP_DEFLOCALFUN:
BEGIN_LITOPX_CASE(JSOP_DEFLOCALFUN, VARNO_LEN)
/*
* Define a local function (i.e., one nested at the top level of
* another function), parented by the current scope chain, and
@ -4428,15 +4494,14 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
* This is an optimization over JSOP_DEFFUN that avoids requiring
* a call object for the outer function's activation.
*/
pc2 = pc;
slot = GET_VARNO(pc2);
pc2 += VARNO_LEN;
atom = GET_ATOM(cx, script, pc2);
slot = GET_VARNO(pc);
atom = js_GetAtom(cx, &script->atomMap, atomIndex);
obj = ATOM_TO_OBJECT(atom);
fun = (JSFunction *) JS_GetPrivate(cx, obj);
parent = fp->scopeChain;
if (OBJ_GET_PARENT(cx, obj) != parent) {
SAVE_SP(fp);
obj = js_CloneFunctionObject(cx, obj, parent);
if (!obj) {
ok = JS_FALSE;
@ -4444,16 +4509,16 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
}
}
fp->vars[slot] = OBJECT_TO_JSVAL(obj);
break;
END_LITOPX_CASE
case JSOP_ANONFUNOBJ:
BEGIN_LITOPX_CASE(JSOP_ANONFUNOBJ, 0)
/* Push the specified function object literal. */
atom = GET_ATOM(cx, script, pc);
obj = ATOM_TO_OBJECT(atom);
/* If re-parenting, push a clone of the function object. */
parent = fp->scopeChain;
if (OBJ_GET_PARENT(cx, obj) != parent) {
SAVE_SP(fp);
obj = js_CloneFunctionObject(cx, obj, parent);
if (!obj) {
ok = JS_FALSE;
@ -4462,11 +4527,10 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
}
PUSH_OPND(OBJECT_TO_JSVAL(obj));
obj = NULL;
break;
END_LITOPX_CASE
case JSOP_NAMEDFUNOBJ:
BEGIN_LITOPX_CASE(JSOP_NAMEDFUNOBJ, 0)
/* ECMA ed. 3 FunctionExpression: function Identifier [etc.]. */
atom = GET_ATOM(cx, script, pc);
rval = ATOM_KEY(atom);
JS_ASSERT(JSVAL_IS_FUNCTION(cx, rval));
@ -4552,12 +4616,9 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
*/
PUSH_OPND(OBJECT_TO_JSVAL(obj));
obj = NULL;
break;
case JSOP_CLOSURE:
{
jsatomid atomIndex;
END_LITOPX_CASE
BEGIN_LITOPX_CASE(JSOP_CLOSURE, 0)
/*
* ECMA ed. 3 extension: a named function expression in a compound
* statement (not at the top statement level of global code, or at
@ -4566,8 +4627,6 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
* Get immediate operand atom, which is a function object literal.
* From it, get the function to close.
*/
atomIndex = GET_ATOM_INDEX(pc);
atom = js_GetAtom(cx, &script->atomMap, atomIndex);
JS_ASSERT(JSVAL_IS_FUNCTION(cx, ATOM_KEY(atom)));
obj = ATOM_TO_OBJECT(atom);
@ -4638,8 +4697,7 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
}
#endif
OBJ_DROP_PROPERTY(cx, parent, prop);
break;
}
END_LITOPX_CASE
#endif /* JS_HAS_LEXICAL_CLOSURE */
#if JS_HAS_GETTER_SETTER
@ -4898,13 +4956,12 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
/* let the code at out try to catch the exception. */
goto out;
case JSOP_INITCATCHVAR:
BEGIN_LITOPX_CASE(JSOP_INITCATCHVAR, 0)
/* Load the value into rval, while keeping it live on stack. */
JS_ASSERT(sp - fp->spbase >= 2);
rval = FETCH_OPND(-1);
/* Get the immediate catch variable name into id. */
atom = GET_ATOM(cx, script, pc);
id = ATOM_TO_JSID(atom);
/* Find the object being initialized at top of stack. */
@ -4921,7 +4978,7 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
/* Now that we're done with rval, pop it. */
sp--;
break;
END_LITOPX_CASE
#endif /* JS_HAS_EXCEPTIONS */
#if JS_HAS_INSTANCEOF
@ -4998,13 +5055,11 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
PUSH_OPND(rval);
break;
case JSOP_QNAMEPART:
atom = GET_ATOM(cx, script, pc);
BEGIN_LITOPX_CASE(JSOP_QNAMEPART, 0)
PUSH_OPND(ATOM_KEY(atom));
break;
END_LITOPX_CASE
case JSOP_QNAMECONST:
atom = GET_ATOM(cx, script, pc);
BEGIN_LITOPX_CASE(JSOP_QNAMECONST, 0)
rval = ATOM_KEY(atom);
lval = FETCH_OPND(-1);
SAVE_SP(fp);
@ -5014,7 +5069,7 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
goto out;
}
STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
break;
END_LITOPX_CASE
case JSOP_QNAME:
rval = FETCH_OPND(-1);
@ -5194,8 +5249,7 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
STORE_OPND(-1, STRING_TO_JSVAL(str));
break;
case JSOP_XMLOBJECT:
atom = GET_ATOM(cx, script, pc);
BEGIN_LITOPX_CASE(JSOP_XMLOBJECT, 0)
SAVE_SP(fp);
obj = js_CloneXMLObject(cx, ATOM_TO_OBJECT(atom));
if (!obj) {
@ -5204,10 +5258,9 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
}
PUSH_OPND(OBJECT_TO_JSVAL(obj));
obj = NULL;
break;
END_LITOPX_CASE
case JSOP_XMLCDATA:
atom = GET_ATOM(cx, script, pc);
BEGIN_LITOPX_CASE(JSOP_XMLCDATA, 0)
str = ATOM_TO_STRING(atom);
obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_TEXT, NULL, str);
if (!obj) {
@ -5215,10 +5268,9 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
goto out;
}
PUSH_OPND(OBJECT_TO_JSVAL(obj));
break;
END_LITOPX_CASE
case JSOP_XMLCOMMENT:
atom = GET_ATOM(cx, script, pc);
BEGIN_LITOPX_CASE(JSOP_XMLCOMMENT, 0)
str = ATOM_TO_STRING(atom);
obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_COMMENT, NULL, str);
if (!obj) {
@ -5226,13 +5278,13 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
goto out;
}
PUSH_OPND(OBJECT_TO_JSVAL(obj));
break;
END_LITOPX_CASE
case JSOP_XMLPI:
atom = GET_ATOM(cx, script, pc);
BEGIN_LITOPX_CASE(JSOP_XMLPI, 0)
str = ATOM_TO_STRING(atom);
atom = GET_ATOM(cx, script, pc + ATOM_INDEX_LEN);
str2 = ATOM_TO_STRING(atom);
rval = FETCH_OPND(-1);
str2 = JSVAL_TO_STRING(rval);
SAVE_SP(fp);
obj = js_NewXMLSpecialObject(cx,
JSXML_CLASS_PROCESSING_INSTRUCTION,
str, str2);
@ -5240,12 +5292,11 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
ok = JS_FALSE;
goto out;
}
PUSH_OPND(OBJECT_TO_JSVAL(obj));
break;
STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
END_LITOPX_CASE
case JSOP_GETMETHOD:
BEGIN_LITOPX_CASE(JSOP_GETMETHOD, 0)
/* Get an immediate atom naming the property. */
atom = GET_ATOM(cx, script, pc);
id = ATOM_TO_JSID(atom);
FETCH_OBJECT(cx, -1, lval, obj);
SAVE_SP(fp);
@ -5264,7 +5315,7 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
if (!ok)
goto out;
STORE_OPND(-1, rval);
break;
END_LITOPX_CASE
case JSOP_GETFUNNS:
ok = js_GetFunctionNamespace(cx, &rval);

Просмотреть файл

@ -149,7 +149,6 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
const JSCodeSpec *cs;
ptrdiff_t len, off, jmplen;
uint32 type;
jsbytecode *stop;
JSAtom *atom;
JSString *str;
@ -185,16 +184,12 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
fprintf(fp, " %u (%d)", loc + off, off);
break;
case JOF_CONST2:
case JOF_CONST:
stop = pc + len - 1;
do {
atom = GET_ATOM(cx, script, pc);
str = js_ValueToSource(cx, ATOM_KEY(atom));
if (!str)
return 0;
fprintf(fp, " %s", JS_GetStringBytes(str));
} while ((pc += ATOM_INDEX_LEN) < stop);
atom = GET_ATOM(cx, script, pc);
str = js_ValueToSource(cx, ATOM_KEY(atom));
if (!str)
return 0;
fprintf(fp, " %s", JS_GetStringBytes(str));
break;
case JOF_UINT16:
@ -839,6 +834,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
const char *lval, *rval, *xval, *fmt;
jsint i, argc;
char **argv;
jsatomid atomIndex;
JSAtom *atom;
JSObject *obj;
JSFunction *fun;
@ -863,13 +859,13 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
(!ATOM_KEYWORD(atom) && js_IsIdentifier(ATOM_TO_STRING(atom)))
/*
* Get atom from script's atom map, quote/escape its string appropriately into
* rval, and select fmt from the quoted and unquoted alternatives.
* Given an atom already fetched from jp->script's atom map, quote/escape its
* string appropriately into rval, and select fmt from the quoted and unquoted
* alternatives.
*/
#define GET_ATOM_QUOTE_AND_FMT(qfmt, ufmt, rval) \
#define GET_QUOTE_AND_FMT(qfmt, ufmt, rval) \
JS_BEGIN_MACRO \
jschar quote_; \
atom = GET_ATOM(cx, jp->script, pc); \
if (!ATOM_IS_IDENTIFIER(atom)) { \
quote_ = '\''; \
fmt = qfmt; \
@ -882,6 +878,16 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
return JS_FALSE; \
JS_END_MACRO
/*
* Get atom from jp->script's atom map, quote/escape its string appropriately
* into rval, and select fmt from the quoted and unquoted alternatives.
*/
#define GET_ATOM_QUOTE_AND_FMT(qfmt, ufmt, rval) \
JS_BEGIN_MACRO \
atom = GET_ATOM(cx, jp->script, pc); \
GET_QUOTE_AND_FMT(qfmt, ufmt, rval); \
JS_END_MACRO
cx = ss->sprinter.context;
jp = ss->printer;
endpc = pc + nb;
@ -939,6 +945,15 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
}
} else {
switch (op) {
#define BEGIN_LITOPX_CASE(OP) \
case OP: \
atomIndex = GET_ATOM_INDEX(pc); \
do_##OP: \
atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex);
#define END_LITOPX_CASE \
break;
case JSOP_NOP:
/*
* Check for a do-while loop, a for-loop with an empty
@ -1040,14 +1055,22 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
pc += js_CodeSpec[JSOP_NEWINIT].length;
LOCAL_ASSERT(*pc == JSOP_EXCEPTION);
pc += js_CodeSpec[JSOP_EXCEPTION].length;
LOCAL_ASSERT(*pc == JSOP_INITCATCHVAR);
atom = GET_ATOM(cx, jp->script, pc);
if (*pc == JSOP_LITOPX) {
atomIndex = GET_LITERAL_INDEX(pc);
pc += 1 + LITERAL_INDEX_LEN;
LOCAL_ASSERT(*pc == JSOP_INITCATCHVAR);
++pc;
} else {
LOCAL_ASSERT(*pc == JSOP_INITCATCHVAR);
atomIndex = GET_ATOM_INDEX(pc);
pc += js_CodeSpec[JSOP_INITCATCHVAR].length;
}
atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex);
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
if (!rval)
return JS_FALSE;
RETRACT(&ss->sprinter, rval);
js_printf(jp, "%s", rval);
pc += js_CodeSpec[JSOP_INITCATCHVAR].length;
LOCAL_ASSERT(*pc == JSOP_ENTERWITH);
pc += js_CodeSpec[JSOP_ENTERWITH].length;
@ -1108,6 +1131,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_PUSH:
case JSOP_PUSHOBJ:
case JSOP_BINDNAME:
do_JSOP_BINDNAME:
todo = Sprint(&ss->sprinter, "");
break;
@ -1588,7 +1612,11 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_SETCONST:
case JSOP_SETNAME:
case JSOP_SETGVAR:
atom = GET_ATOM(cx, jp->script, pc);
atomIndex = GET_ATOM_INDEX(pc);
do_JSOP_SETCONST:
atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex);
do_setname:
lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
if (!lval)
@ -1596,6 +1624,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
rval = POP_STR();
if (op == JSOP_SETNAME)
(void) PopOff(ss, op);
do_setlval:
sn = js_GetSrcNote(jp->script, pc - 1);
if (sn && SN_TYPE(sn) == SRC_ASSIGNOP) {
@ -1829,14 +1858,20 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
/* FALL THROUGH */
case JSOP_GETPROP:
#if JS_HAS_XML_SUPPORT
case JSOP_GETMETHOD:
#endif
GET_ATOM_QUOTE_AND_FMT("%s[%s]", "%s.%s", rval);
atom = GET_ATOM(cx, jp->script, pc);
do_getprop:
GET_QUOTE_AND_FMT("%s[%s]", "%s.%s", rval);
lval = POP_STR();
todo = Sprint(&ss->sprinter, fmt, lval, rval);
break;
#if JS_HAS_XML_SUPPORT
BEGIN_LITOPX_CASE(JSOP_GETMETHOD)
goto do_getprop;
END_LITOPX_CASE
#endif
case JSOP_SETPROP:
GET_ATOM_QUOTE_AND_FMT("%s[%s] %s= %s", "%s.%s %s= %s", xval);
rval = POP_STR();
@ -1925,11 +1960,53 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_UINT16:
i = (jsint) GET_ATOM_INDEX(pc);
goto do_sprint_int;
case JSOP_UINT24:
i = (jsint) GET_LITERAL_INDEX(pc);
do_sprint_int:
todo = Sprint(&ss->sprinter, "%u", (unsigned) i);
break;
case JSOP_NUMBER:
atom = GET_ATOM(cx, jp->script, pc);
case JSOP_LITERAL:
atomIndex = GET_LITERAL_INDEX(pc);
goto do_JSOP_STRING;
case JSOP_FINDNAME:
atomIndex = GET_LITERAL_INDEX(pc);
todo = Sprint(&ss->sprinter, "");
if (todo < 0 || !PushOff(ss, todo, op))
return JS_FALSE;
atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex);
goto do_name;
case JSOP_LITOPX:
atomIndex = GET_LITERAL_INDEX(pc);
op = pc[1 + LITERAL_INDEX_LEN];
switch (op) {
case JSOP_ANONFUNOBJ: goto do_JSOP_ANONFUNOBJ;
case JSOP_BINDNAME: goto do_JSOP_BINDNAME;
case JSOP_CLOSURE: goto do_JSOP_CLOSURE;
case JSOP_EXPORTNAME: goto do_JSOP_EXPORTNAME;
case JSOP_GETMETHOD: goto do_JSOP_GETMETHOD;
case JSOP_NAMEDFUNOBJ: goto do_JSOP_NAMEDFUNOBJ;
case JSOP_NUMBER: goto do_JSOP_NUMBER;
case JSOP_OBJECT: goto do_JSOP_OBJECT;
case JSOP_QNAMECONST: goto do_JSOP_QNAMECONST;
case JSOP_QNAMEPART: goto do_JSOP_QNAMEPART;
case JSOP_REGEXP: goto do_JSOP_REGEXP;
case JSOP_SETCONST: goto do_JSOP_SETCONST;
case JSOP_STRING: goto do_JSOP_STRING;
case JSOP_XMLCDATA: goto do_JSOP_XMLCDATA;
case JSOP_XMLCOMMENT: goto do_JSOP_XMLCOMMENT;
case JSOP_XMLOBJECT: goto do_JSOP_XMLOBJECT;
case JSOP_XMLPI: goto do_JSOP_XMLPI;
default: JS_ASSERT(0);
}
/* NOTREACHED */
break;
BEGIN_LITOPX_CASE(JSOP_NUMBER)
val = ATOM_KEY(atom);
if (JSVAL_IS_INT(val)) {
long ival = (long)JSVAL_TO_INT(val);
@ -1944,22 +2021,27 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
}
todo = Sprint(&ss->sprinter, numStr);
}
break;
END_LITOPX_CASE
case JSOP_STRING:
atom = GET_ATOM(cx, jp->script, pc);
BEGIN_LITOPX_CASE(JSOP_STRING)
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
(jschar)'"');
if (!rval)
return JS_FALSE;
todo = STR2OFF(&ss->sprinter, rval);
break;
END_LITOPX_CASE
case JSOP_OBJECT:
case JSOP_REGEXP:
case JSOP_ANONFUNOBJ:
case JSOP_NAMEDFUNOBJ:
atom = GET_ATOM(cx, jp->script, pc);
atomIndex = GET_ATOM_INDEX(pc);
do_JSOP_OBJECT:
do_JSOP_REGEXP:
do_JSOP_ANONFUNOBJ:
do_JSOP_NAMEDFUNOBJ:
atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex);
if (op == JSOP_OBJECT || op == JSOP_REGEXP) {
if (!js_regexp_toString(cx, ATOM_TO_OBJECT(atom), 0, NULL,
&val)) {
@ -2196,14 +2278,14 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
"=",
rval);
break;
#endif /* !JS_BUG_FALLIBLE_EQOPS */
#endif
#if JS_HAS_LEXICAL_CLOSURE
case JSOP_CLOSURE:
atom = GET_ATOM(cx, jp->script, pc);
BEGIN_LITOPX_CASE(JSOP_CLOSURE)
JS_ASSERT(ATOM_IS_OBJECT(atom));
goto do_function;
#endif /* JS_HAS_LEXICAL_CLOSURE */
END_LITOPX_CASE
#endif
#if JS_HAS_EXPORT_IMPORT
case JSOP_EXPORTALL:
@ -2211,15 +2293,14 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
todo = -2;
break;
case JSOP_EXPORTNAME:
atom = GET_ATOM(cx, jp->script, pc);
BEGIN_LITOPX_CASE(JSOP_EXPORTNAME)
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
if (!rval)
return JS_FALSE;
RETRACT(&ss->sprinter, rval);
js_printf(jp, "\texport %s\n", rval);
todo = -2;
break;
END_LITOPX_CASE
case JSOP_IMPORTALL:
lval = POP_STR();
@ -2291,7 +2372,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
break;
case JSOP_INITPROP:
case JSOP_INITCATCHVAR:
atom = GET_ATOM(cx, jp->script, pc);
xval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
(jschar)
@ -2377,19 +2457,18 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
todo = SprintPut(&ss->sprinter, "*", 1);
break;
case JSOP_QNAMEPART:
atom = GET_ATOM(cx, jp->script, pc);
BEGIN_LITOPX_CASE(JSOP_QNAMEPART)
goto do_name;
END_LITOPX_CASE
case JSOP_QNAMECONST:
atom = GET_ATOM(cx, jp->script, pc);
BEGIN_LITOPX_CASE(JSOP_QNAMECONST)
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
if (!rval)
return JS_FALSE;
RETRACT(&ss->sprinter, rval);
lval = POP_STR();
todo = Sprint(&ss->sprinter, "%s::%s", lval, rval);
break;
END_LITOPX_CASE
case JSOP_QNAME:
op = JSOP_NOP; /* turn off parens */
@ -2453,39 +2532,39 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
todo = Sprint(&ss->sprinter, "%s..%s", lval, rval);
break;
case JSOP_XMLOBJECT:
BEGIN_LITOPX_CASE(JSOP_XMLOBJECT)
atom = GET_ATOM(cx, jp->script, pc);
todo = Sprint(&ss->sprinter, "<xml address='%p'>",
ATOM_TO_OBJECT(atom));
break;
END_LITOPX_CASE
case JSOP_XMLCDATA:
BEGIN_LITOPX_CASE(JSOP_XMLCDATA)
todo = SprintPut(&ss->sprinter, "<![CDATA[", 9);
atom = GET_ATOM(cx, jp->script, pc);
if (!QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0))
return JS_FALSE;
SprintPut(&ss->sprinter, "]]>", 3);
break;
END_LITOPX_CASE
case JSOP_XMLCOMMENT:
BEGIN_LITOPX_CASE(JSOP_XMLCOMMENT)
todo = SprintPut(&ss->sprinter, "<!--", 4);
atom = GET_ATOM(cx, jp->script, pc);
if (!QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0))
return JS_FALSE;
SprintPut(&ss->sprinter, "-->", 3);
break;
END_LITOPX_CASE
case JSOP_XMLPI:
todo = SprintPut(&ss->sprinter, "<?", 2);
atom = GET_ATOM(cx, jp->script, pc);
if (!QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0))
BEGIN_LITOPX_CASE(JSOP_XMLPI)
rval = JS_strdup(cx, POP_STR());
if (!rval)
return JS_FALSE;
SprintPut(&ss->sprinter, " ", 1);
atom = GET_ATOM(cx, jp->script, pc + ATOM_INDEX_LEN);
if (!QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0))
todo = SprintPut(&ss->sprinter, "<?", 2);
ok = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0) &&
SprintPut(&ss->sprinter, " ", 1) >= 0 &&
SprintPut(&ss->sprinter, rval, strlen(rval));
JS_free(cx, (char *)rval);
if (!ok)
return JS_FALSE;
SprintPut(&ss->sprinter, "?>", 2);
break;
END_LITOPX_CASE
case JSOP_GETFUNNS:
todo = SprintPut(&ss->sprinter, js_function_str, 8);
@ -2495,6 +2574,9 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
default:
todo = -2;
break;
#undef BEGIN_LITOPX_CASE
#undef END_LITOPX_CASE
}
}
@ -2516,6 +2598,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
#undef POP_STR
#undef LOCAL_ASSERT
#undef ATOM_IS_IDENTIFIER
#undef GET_QUOTE_AND_FMT
#undef GET_ATOM_QUOTE_AND_FMT
return JS_TRUE;

Просмотреть файл

@ -74,7 +74,10 @@ typedef enum JSOp {
#define JOF_JUMPX 9 /* signed 32-bit jump offset immediate */
#define JOF_TABLESWITCHX 10 /* extended (32-bit offset) table switch */
#define JOF_LOOKUPSWITCHX 11 /* extended (32-bit offset) lookup switch */
#define JOF_CONST2 12 /* 2 unsigned 16-bit constant pool indexes */
#define JOF_UINT24 12 /* extended unsigned 24-bit literal (index) */
#define JOF_LITOPX 13 /* JOF_UINT24 followed by op being extended,
where op if JOF_CONST has no unsigned 16-
bit immediate operand */
#define JOF_TYPEMASK 0x000f /* mask for above immediate types */
#define JOF_NAME 0x0010 /* name operation */
#define JOF_PROP 0x0020 /* obj.prop operation */
@ -145,16 +148,36 @@ typedef enum JSOp {
#define JUMPX_OFFSET_MIN ((int32)0x80000000)
#define JUMPX_OFFSET_MAX ((int32)0x7fffffff)
/* A literal is indexed by a per-script atom map. */
/*
* A literal is indexed by a per-script atom map. Most scripts have relatively
* few literals, so the standard JOF_CONST format specifies a fixed 16 bits of
* immediate operand index. A script with more than 64K literals must push all
* high-indexed literals on the stack using JSOP_LITERAL, then use JOF_ELEM ops
* instead of JOF_PROP, etc.
*/
#define ATOM_INDEX_LEN 2
#define ATOM_INDEX_HI(index) ((jsbytecode)((index) >> 8))
#define ATOM_INDEX_LO(index) ((jsbytecode)(index))
#define ATOM_INDEX_HI(i) ((jsbytecode)((i) >> 8))
#define ATOM_INDEX_LO(i) ((jsbytecode)(i))
#define GET_ATOM_INDEX(pc) ((jsatomid)(((pc)[1] << 8) | (pc)[2]))
#define SET_ATOM_INDEX(pc,index)((pc)[1] = ATOM_INDEX_HI(index), \
(pc)[2] = ATOM_INDEX_LO(index))
#define SET_ATOM_INDEX(pc,i) ((pc)[1] = ATOM_INDEX_HI(i), \
(pc)[2] = ATOM_INDEX_LO(i))
#define GET_ATOM(cx,script,pc) js_GetAtom((cx), &(script)->atomMap, \
GET_ATOM_INDEX(pc))
#define ATOM_INDEX_LIMIT_LOG2 16
/* A full atom index for JSOP_LITERAL uses 24 bits of immediate operand. */
#define LITERAL_INDEX_LEN 3
#define LITERAL_INDEX_HI(i) ((jsbytecode)((i) >> 16))
#define LITERAL_INDEX_MID(i) ((jsbytecode)((i) >> 8))
#define LITERAL_INDEX_LO(i) ((jsbytecode)(i))
#define GET_LITERAL_INDEX(pc) ((jsatomid)(((pc)[1] << 16) | \
((pc)[2] << 8) | \
(pc)[3]))
#define SET_LITERAL_INDEX(pc,i) ((pc)[1] = LITERAL_INDEX_HI(i), \
(pc)[2] = LITERAL_INDEX_MID(i), \
(pc)[3] = LITERAL_INDEX_LO(i))
/* Atom index limit is determined by SN_3BYTE_OFFSET_FLAG, see jsemit.h. */
#define ATOM_INDEX_LIMIT_LOG2 23
#define ATOM_INDEX_LIMIT ((uint32)1 << ATOM_INDEX_LIMIT_LOG2)
/* Actual argument count operand format helpers. */

Просмотреть файл

@ -272,8 +272,11 @@ OPDEF(JSOP_ANONFUNOBJ, 128, "anonfunobj", NULL, 3, 0, 1, 12, JOF_CONST)
/* ECMA ed. 3 named function expression. */
OPDEF(JSOP_NAMEDFUNOBJ, 129, "namedfunobj", NULL, 3, 0, 1, 12, JOF_CONST)
/* Like JSOP_INITPROP, but specialized to make a DontDelete property for ECMA ed. 3 catch variables. */
OPDEF(JSOP_INITCATCHVAR,130, "initcatchvar",NULL, 3, 1, 0, 0, JOF_CONST|JOF_PROP)
/*
* Like JSOP_INITPROP, but specialized to make a DontDelete property for ECMA
* Edition 3 catch variables.
*/
OPDEF(JSOP_INITCATCHVAR,130, "initcatchvar",NULL, 3, 1, 0, 0, JOF_CONST)
/* ECMA-mandated parenthesization opcode, which nulls the reference base register, obj; see jsinterp.c. */
OPDEF(JSOP_GROUP, 131, "group", NULL, 1, 0, 0, 0, JOF_BYTE)
@ -366,8 +369,19 @@ OPDEF(JSOP_XMLELTEXPR, 179,"xmleltexpr", NULL, 1, 1, 1, 12, JOF_BYTE)
OPDEF(JSOP_XMLOBJECT, 180,"xmlobject", NULL, 3, 0, 1, 12, JOF_CONST)
OPDEF(JSOP_XMLCDATA, 181,"xmlcdata", NULL, 3, 0, 1, 12, JOF_CONST)
OPDEF(JSOP_XMLCOMMENT, 182,"xmlcomment", NULL, 3, 0, 1, 12, JOF_CONST)
OPDEF(JSOP_XMLPI, 183,"xmlpi", NULL, 5, 0, 1, 12, JOF_CONST2)
OPDEF(JSOP_XMLPI, 183,"xmlpi", NULL, 3, 1, 1, 12, JOF_CONST)
OPDEF(JSOP_GETMETHOD, 184,"getmethod", NULL, 3, 1, 1, 11, JOF_CONST|JOF_PROP)
OPDEF(JSOP_GETFUNNS, 185,"getfunns", NULL, 1, 0, 1, 12, JOF_BYTE)
OPDEF(JSOP_FOREACH, 186,"foreach", NULL, 1, 0, 0, 0, JOF_BYTE)
OPDEF(JSOP_DELDESC, 187,"deldesc", NULL, 1, 2, 1, 10, JOF_BYTE |JOF_ELEM|JOF_DEL)
/*
* Opcodes for extended literal addressing, using unsigned 24-bit immediate
* operands to hold integer operands (JSOP_UINT24), extended atom indexes in
* script->atomMap (JSOP_LITERAL, JSOP_FINDNAME), and ops prefixed by such
* atom index immediates (JSOP_LITOPX). See jsemit.c, EmitAtomIndexOp.
*/
OPDEF(JSOP_UINT24, 188,"uint24", NULL, 4, 0, 1, 12, JOF_UINT24)
OPDEF(JSOP_LITERAL, 189,"literal", NULL, 4, 0, 1, 12, JOF_UINT24)
OPDEF(JSOP_FINDNAME, 190,"findname", NULL, 4, 0, 2, 0, JOF_UINT24)
OPDEF(JSOP_LITOPX, 191,"litopx", NULL, 5, 0, 0, 12, JOF_LITOPX)