зеркало из https://github.com/mozilla/pjs.git
Allow up to 2^23 literals in a script (155081, r=shaver, a=me).
This commit is contained in:
Родитель
94e828fc62
Коммит
ca6ebfbcf0
249
js/src/jsemit.c
249
js/src/jsemit.c
|
@ -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);
|
||||
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 (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,8 +4052,12 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||
case TOK_NAME:
|
||||
if (pn2->pn_slot < 0 || !(pn2->pn_attrs & JSPROP_READONLY)) {
|
||||
case TOK_DOT:
|
||||
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:
|
||||
#if JS_HAS_LVALUE_RETURN
|
||||
|
@ -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)
|
||||
for (atomIndex = 0; pn2; atomIndex++, pn2 = pn2->pn_next) {
|
||||
if (!EmitNumberOp(cx, atomIndex, cg))
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
@ -3709,15 +3717,77 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
|
|||
obj = NULL;
|
||||
break;
|
||||
|
||||
case JSOP_NUMBER:
|
||||
case JSOP_STRING:
|
||||
case JSOP_OBJECT:
|
||||
atom = GET_ATOM(cx, script, pc);
|
||||
case JSOP_UINT24:
|
||||
i = (jsint) GET_LITERAL_INDEX(pc);
|
||||
rval = INT_TO_JSVAL(i);
|
||||
PUSH_OPND(rval);
|
||||
break;
|
||||
|
||||
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);
|
||||
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;
|
||||
if (*pc == JSOP_LITOPX) {
|
||||
atomIndex = GET_LITERAL_INDEX(pc);
|
||||
pc += 1 + LITERAL_INDEX_LEN;
|
||||
LOCAL_ASSERT(*pc == JSOP_INITCATCHVAR);
|
||||
atom = GET_ATOM(cx, jp->script, pc);
|
||||
++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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче