зеркало из https://github.com/mozilla/pjs.git
Optimize x.p for arg/var/local x; fix decompiler bugs hiding nearby (363536, r=igor).
This commit is contained in:
Родитель
18c829229c
Коммит
0e994e3456
111
js/src/jsemit.c
111
js/src/jsemit.c
|
@ -1796,7 +1796,7 @@ EmitAtomIndexOp(JSContext *cx, JSOp op, jsatomid atomIndex, JSCodeGenerator *cg)
|
|||
case JSOP_BINDNAME: return JS_TRUE;
|
||||
case JSOP_SETNAME: op = JSOP_SETELEM; break;
|
||||
case JSOP_SETPROP: op = JSOP_SETELEM; break;
|
||||
default: JS_ASSERT(mode == 0); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return js_Emit1(cx, cg, op) >= 0;
|
||||
|
@ -1830,6 +1830,47 @@ EmitAtomOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
|
|||
return EmitAtomIndexOp(cx, op, ALE_INDEX(ale), cg);
|
||||
}
|
||||
|
||||
/*
|
||||
* What good are ARGNO_LEN and VARNO_LEN, you ask? The answer is that, apart
|
||||
* from EmitIndexConstOp, they abstract out the detail that both are 2, and in
|
||||
* other parts of the code there's no necessary relationship between the two.
|
||||
* The abstraction cracks here in order to share EmitIndexConstOp code among
|
||||
* the JSOP_DEFLOCALFUN and JSOP_GET{ARG,VAR,LOCAL}PROP cases.
|
||||
*/
|
||||
JS_STATIC_ASSERT(ARGNO_LEN == 2);
|
||||
JS_STATIC_ASSERT(VARNO_LEN == 2);
|
||||
|
||||
static JSBool
|
||||
EmitIndexConstOp(JSContext *cx, JSOp op, uintN slot, jsatomid atomIndex,
|
||||
JSCodeGenerator *cg)
|
||||
{
|
||||
ptrdiff_t off;
|
||||
jsbytecode *pc;
|
||||
|
||||
if (atomIndex >= JS_BIT(16)) {
|
||||
/*
|
||||
* Lots of literals in the outer function, so we have to emit
|
||||
* [JSOP_LITOPX, atomIndex, op, 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(op, slot);
|
||||
} else {
|
||||
/* Emit [op, slot, atomIndex]. */
|
||||
off = js_EmitN(cx, cg, op, 2 + ATOM_INDEX_LEN);
|
||||
if (off < 0)
|
||||
return JS_FALSE;
|
||||
pc = CG_CODE(cg, off);
|
||||
SET_UINT16(pc, slot);
|
||||
pc += 2;
|
||||
SET_ATOM_INDEX(pc, atomIndex);
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine tries to optimize name gets and sets to stack slot loads and
|
||||
* stores, given the variables object and scope chain in cx's top frame, the
|
||||
|
@ -2302,21 +2343,47 @@ EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
|
|||
|
||||
pn2 = pn->pn_expr;
|
||||
if (op == JSOP_GETPROP && pn->pn_type == TOK_DOT) {
|
||||
if (pn2->pn_op == JSOP_THIS && cg->atomList.count < JS_BIT(16)) {
|
||||
/*
|
||||
* Fast path for gets of |this.foo| where the immediate is
|
||||
* guaranteed to fit.
|
||||
*/
|
||||
if (pn2->pn_op == JSOP_THIS) {
|
||||
/* Fast path for gets of |this.foo|. */
|
||||
return EmitAtomOp(cx, pn, JSOP_GETTHISPROP, cg);
|
||||
}
|
||||
|
||||
if (pn2->pn_type == TOK_NAME) {
|
||||
/* Try to optimize arguments.length into JSOP_ARGCNT. */
|
||||
/*
|
||||
* Try to optimize:
|
||||
* - arguments.length into JSOP_ARGCNT
|
||||
* - argname.prop into JSOP_GETARGPROP
|
||||
* - varname.prop into JSOP_GETVARPROP
|
||||
* - localname.prop into JSOP_GETLOCALPROP
|
||||
*/
|
||||
if (!BindNameToSlot(cx, &cg->treeContext, pn2, JS_FALSE))
|
||||
return JS_FALSE;
|
||||
if (pn2->pn_op == JSOP_ARGUMENTS &&
|
||||
pn->pn_atom == cx->runtime->atomState.lengthAtom) {
|
||||
return js_Emit1(cx, cg, JSOP_ARGCNT) >= 0;
|
||||
switch (pn2->pn_op) {
|
||||
case JSOP_ARGUMENTS:
|
||||
if (pn->pn_atom == cx->runtime->atomState.lengthAtom)
|
||||
return js_Emit1(cx, cg, JSOP_ARGCNT) >= 0;
|
||||
break;
|
||||
|
||||
case JSOP_GETARG:
|
||||
op = JSOP_GETARGPROP;
|
||||
goto do_indexconst;
|
||||
case JSOP_GETVAR:
|
||||
op = JSOP_GETVARPROP;
|
||||
goto do_indexconst;
|
||||
case JSOP_GETLOCAL:
|
||||
op = JSOP_GETLOCALPROP;
|
||||
do_indexconst: {
|
||||
JSAtomListElement *ale;
|
||||
jsatomid atomIndex;
|
||||
|
||||
ale = js_IndexAtom(cx, pn->pn_atom, &cg->atomList);
|
||||
if (!ale)
|
||||
return JS_FALSE;
|
||||
atomIndex = ALE_INDEX(ale);
|
||||
return EmitIndexConstOp(cx, op, pn2->pn_slot, atomIndex, cg);
|
||||
}
|
||||
|
||||
default:;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3995,28 +4062,8 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||
cg->treeContext.flags |= TCF_HAS_BLOCKLOCALFUN;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
if (!EmitIndexConstOp(cx, JSOP_DEFLOCALFUN, slot, atomIndex, cg))
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
JS_ASSERT(!cg->treeContext.topStmt);
|
||||
EMIT_ATOM_INDEX_OP(JSOP_DEFFUN, atomIndex);
|
||||
|
|
|
@ -3821,8 +3821,7 @@ interrupt:
|
|||
DO_NEXT_OP(len);
|
||||
}
|
||||
|
||||
BEGIN_CASE(JSOP_GETTHISPROP)
|
||||
atom = GET_ATOM(cx, script, pc);
|
||||
BEGIN_LITOPX_CASE(JSOP_GETTHISPROP, 0)
|
||||
id = ATOM_TO_JSID(atom);
|
||||
obj = fp->thisp;
|
||||
SAVE_SP_AND_PC(fp);
|
||||
|
@ -3830,16 +3829,40 @@ interrupt:
|
|||
if (!ok)
|
||||
goto out;
|
||||
PUSH_OPND(rval);
|
||||
END_CASE(JSOP_GETTHISPROP)
|
||||
END_LITOPX_CASE(JSOP_GETTHISPROP)
|
||||
|
||||
BEGIN_LITOPX_CASE(JSOP_GETARGPROP, ARGNO_LEN)
|
||||
slot = GET_ARGNO(pc);
|
||||
JS_ASSERT(slot < fp->fun->nargs);
|
||||
PUSH_OPND(fp->argv[slot]);
|
||||
len = JSOP_GETARGPROP_LENGTH;
|
||||
goto do_getprop_body;
|
||||
|
||||
BEGIN_LITOPX_CASE(JSOP_GETVARPROP, VARNO_LEN)
|
||||
slot = GET_VARNO(pc);
|
||||
JS_ASSERT(slot < fp->fun->u.i.nvars);
|
||||
PUSH_OPND(fp->vars[slot]);
|
||||
len = JSOP_GETVARPROP_LENGTH;
|
||||
goto do_getprop_body;
|
||||
|
||||
BEGIN_LITOPX_CASE(JSOP_GETLOCALPROP, 2)
|
||||
slot = GET_UINT16(pc);
|
||||
JS_ASSERT(slot < (uintN)depth);
|
||||
PUSH_OPND(fp->spbase[slot]);
|
||||
len = JSOP_GETLOCALPROP_LENGTH;
|
||||
goto do_getprop_body;
|
||||
|
||||
BEGIN_CASE(JSOP_GETPROP)
|
||||
BEGIN_CASE(JSOP_GETXPROP)
|
||||
/* Get an immediate atom naming the property. */
|
||||
atom = GET_ATOM(cx, script, pc);
|
||||
len = JSOP_GETPROP_LENGTH;
|
||||
|
||||
do_getprop_body:
|
||||
lval = FETCH_OPND(-1);
|
||||
if (JSVAL_IS_STRING(lval) &&
|
||||
atom == cx->runtime->atomState.lengthAtom) {
|
||||
rval = INT_TO_JSVAL(JSSTRING_LENGTH(JSVAL_TO_STRING(lval)));
|
||||
if (JSVAL_IS_STRING(lval) && atom == rt->atomState.lengthAtom) {
|
||||
str = JSVAL_TO_STRING(lval);
|
||||
rval = INT_TO_JSVAL(JSSTRING_LENGTH(str));
|
||||
obj = NULL;
|
||||
} else {
|
||||
id = ATOM_TO_JSID(atom);
|
||||
|
@ -3851,7 +3874,7 @@ interrupt:
|
|||
goto out;
|
||||
}
|
||||
STORE_OPND(-1, rval);
|
||||
END_CASE(JSOP_GETPROP)
|
||||
END_VARLEN_CASE
|
||||
|
||||
BEGIN_CASE(JSOP_SETPROP)
|
||||
/* Pop the right-hand side into rval for OBJ_SET_PROPERTY. */
|
||||
|
@ -4301,6 +4324,10 @@ interrupt:
|
|||
case JSOP_XMLPI: goto do_JSOP_XMLPI;
|
||||
#endif
|
||||
case JSOP_ENTERBLOCK: goto do_JSOP_ENTERBLOCK;
|
||||
case JSOP_GETTHISPROP: goto do_JSOP_GETTHISPROP;
|
||||
case JSOP_GETARGPROP: goto do_JSOP_GETARGPROP;
|
||||
case JSOP_GETVARPROP: goto do_JSOP_GETVARPROP;
|
||||
case JSOP_GETLOCALPROP: goto do_JSOP_GETLOCALPROP;
|
||||
default: JS_ASSERT(0);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
|
|
|
@ -1070,6 +1070,22 @@ GetSlotAtom(JSPrinter *jp, JSPropertyOp getter, uintN slot)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
PushSlotAtom(SprintStack *ss, JSPropertyOp getter, uintN slot, JSOp op)
|
||||
{
|
||||
JSAtom *atom;
|
||||
char *lval;
|
||||
|
||||
atom = GetSlotAtom(ss->printer, getter, slot);
|
||||
if (!atom)
|
||||
return JS_FALSE;
|
||||
JS_ASSERT(ATOM_IS_STRING(atom));
|
||||
lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
|
||||
if (!lval)
|
||||
return JS_FALSE;
|
||||
return PushOff(ss, STR2OFF(&ss->sprinter, lval), op);
|
||||
}
|
||||
|
||||
/*
|
||||
* NB: Indexed by SRC_DECL_* defines from jsemit.h.
|
||||
*/
|
||||
|
@ -1092,7 +1108,7 @@ VarPrefix(jssrcnote *sn)
|
|||
JS_END_MACRO
|
||||
|
||||
const char *
|
||||
GetLocal(SprintStack *ss, jsint i)
|
||||
GetLocal(SprintStack *ss, jsint i, JSBool retract)
|
||||
{
|
||||
ptrdiff_t off;
|
||||
JSContext *cx;
|
||||
|
@ -1142,7 +1158,8 @@ GetLocal(SprintStack *ss, jsint i)
|
|||
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
|
||||
if (!rval)
|
||||
return NULL;
|
||||
RETRACT(&ss->sprinter, rval);
|
||||
if (retract)
|
||||
RETRACT(&ss->sprinter, rval);
|
||||
return rval;
|
||||
|
||||
#undef LOCAL_ASSERT
|
||||
|
@ -1212,7 +1229,7 @@ DecompileDestructuringLHS(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc,
|
|||
else if (op == JSOP_SETGVAR)
|
||||
atom = GET_ATOM(cx, jp->script, pc);
|
||||
else
|
||||
lval = GetLocal(ss, i);
|
||||
lval = GetLocal(ss, i, JS_TRUE);
|
||||
if (atom)
|
||||
lval = js_AtomToPrintableString(cx, atom);
|
||||
LOCAL_ASSERT(lval);
|
||||
|
@ -1636,7 +1653,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
format = cs->format;
|
||||
if (((fp && pc == fp->pc) ||
|
||||
(pc == startpc && cs->nuses != 0)) &&
|
||||
format & (JOF_SET|JOF_DEL|JOF_INCDEC|JOF_IMPORT|JOF_FOR)) {
|
||||
format & (JOF_SET|JOF_DEL|JOF_INCDEC|JOF_IMPORT|JOF_FOR|
|
||||
JOF_VARPROP)) {
|
||||
mode = (format & JOF_MODEMASK);
|
||||
if (mode == JOF_NAME) {
|
||||
/*
|
||||
|
@ -1686,6 +1704,15 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
op = JSOP_CALL;
|
||||
break;
|
||||
#endif
|
||||
case JSOP_GETARGPROP:
|
||||
op = JSOP_GETARG;
|
||||
break;
|
||||
case JSOP_GETVARPROP:
|
||||
op = JSOP_GETVAR;
|
||||
break;
|
||||
case JSOP_GETLOCALPROP:
|
||||
op = JSOP_GETLOCAL;
|
||||
break;
|
||||
default:
|
||||
LOCAL_ASSERT(0);
|
||||
}
|
||||
|
@ -1705,7 +1732,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
default:;
|
||||
}
|
||||
}
|
||||
LOCAL_ASSERT(js_CodeSpec[saveop].length == oplen);
|
||||
LOCAL_ASSERT(js_CodeSpec[saveop].length == oplen ||
|
||||
(format & JOF_TYPEMASK) == JOF_INDEXCONST);
|
||||
|
||||
jp->dvgfence = NULL;
|
||||
}
|
||||
|
@ -1754,9 +1782,10 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
}
|
||||
} else {
|
||||
switch (op) {
|
||||
#define BEGIN_LITOPX_CASE(OP) \
|
||||
#define BEGIN_LITOPX_CASE(OP,PCOFF) \
|
||||
case OP: \
|
||||
atomIndex = GET_ATOM_INDEX(pc); \
|
||||
pc2 = pc; \
|
||||
atomIndex = GET_ATOM_INDEX(pc + PCOFF); \
|
||||
do_##OP: \
|
||||
atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex);
|
||||
|
||||
|
@ -2283,7 +2312,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
js_printf(jp, "\t}\n");
|
||||
break;
|
||||
|
||||
BEGIN_LITOPX_CASE(JSOP_ENTERBLOCK)
|
||||
BEGIN_LITOPX_CASE(JSOP_ENTERBLOCK, 0)
|
||||
{
|
||||
JSAtom **atomv, *smallv[5];
|
||||
JSScopeProperty *sprop;
|
||||
|
@ -2427,9 +2456,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
|
||||
case JSOP_GETLOCAL:
|
||||
i = GET_UINT16(pc);
|
||||
sn = js_GetSrcNote(jp->script, pc);
|
||||
LOCAL_ASSERT((uintN)i < ss->top);
|
||||
rval = GetLocal(ss, i);
|
||||
sn = js_GetSrcNote(jp->script, pc);
|
||||
|
||||
#if JS_HAS_DESTRUCTURING
|
||||
if (sn && SN_TYPE(sn) == SRC_GROUPASSIGN) {
|
||||
|
@ -2442,6 +2470,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
}
|
||||
#endif
|
||||
|
||||
rval = GetLocal(ss, i, JS_TRUE);
|
||||
todo = Sprint(&ss->sprinter, ss_format, VarPrefix(sn), rval);
|
||||
break;
|
||||
|
||||
|
@ -2455,13 +2484,13 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
case JSOP_INCLOCAL:
|
||||
case JSOP_DECLOCAL:
|
||||
i = GET_UINT16(pc);
|
||||
lval = GetLocal(ss, i);
|
||||
lval = GetLocal(ss, i, JS_TRUE);
|
||||
goto do_inclval;
|
||||
|
||||
case JSOP_LOCALINC:
|
||||
case JSOP_LOCALDEC:
|
||||
i = GET_UINT16(pc);
|
||||
lval = GetLocal(ss, i);
|
||||
lval = GetLocal(ss, i, JS_TRUE);
|
||||
goto do_lvalinc;
|
||||
|
||||
case JSOP_FORLOCAL:
|
||||
|
@ -3271,21 +3300,38 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
todo = Sprint(&ss->sprinter, fmt, lval, rval);
|
||||
break;
|
||||
|
||||
case JSOP_GETTHISPROP:
|
||||
atom = GET_ATOM(cx, jp->script, pc);
|
||||
BEGIN_LITOPX_CASE(JSOP_GETTHISPROP, 0)
|
||||
GET_QUOTE_AND_FMT(index_format, dot_format, rval);
|
||||
todo = Sprint(&ss->sprinter, fmt, js_this_str, rval);
|
||||
break;
|
||||
END_LITOPX_CASE
|
||||
|
||||
BEGIN_LITOPX_CASE(JSOP_GETARGPROP, ARGNO_LEN)
|
||||
if (!PushSlotAtom(ss, js_GetArgument, GET_ARGNO(pc), op))
|
||||
return NULL;
|
||||
goto do_getprop;
|
||||
|
||||
BEGIN_LITOPX_CASE(JSOP_GETVARPROP, VARNO_LEN)
|
||||
if (!PushSlotAtom(ss, js_GetLocalVariable, GET_VARNO(pc), op))
|
||||
return NULL;
|
||||
goto do_getprop;
|
||||
|
||||
BEGIN_LITOPX_CASE(JSOP_GETLOCALPROP, 2)
|
||||
i = GET_UINT16(pc);
|
||||
LOCAL_ASSERT((uintN)i < ss->top);
|
||||
lval = GetLocal(ss, i, JS_FALSE);
|
||||
if (!lval || !PushOff(ss, STR2OFF(&ss->sprinter, lval), op))
|
||||
return NULL;
|
||||
goto do_getprop;
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
BEGIN_LITOPX_CASE(JSOP_GETMETHOD)
|
||||
BEGIN_LITOPX_CASE(JSOP_GETMETHOD, 0)
|
||||
sn = js_GetSrcNote(jp->script, pc);
|
||||
if (sn && SN_TYPE(sn) == SRC_PCBASE)
|
||||
goto do_getprop;
|
||||
GET_QUOTE_AND_FMT("%s.function::[%s]", "%s.function::%s", rval);
|
||||
goto do_getprop_lval;
|
||||
|
||||
BEGIN_LITOPX_CASE(JSOP_SETMETHOD)
|
||||
BEGIN_LITOPX_CASE(JSOP_SETMETHOD, 0)
|
||||
sn = js_GetSrcNote(jp->script, pc);
|
||||
if (sn && SN_TYPE(sn) == SRC_PCBASE)
|
||||
goto do_setprop;
|
||||
|
@ -3472,12 +3518,16 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
case JSOP_XMLPI: goto do_JSOP_XMLPI;
|
||||
#endif
|
||||
case JSOP_ENTERBLOCK: goto do_JSOP_ENTERBLOCK;
|
||||
case JSOP_GETTHISPROP: goto do_JSOP_GETTHISPROP;
|
||||
case JSOP_GETARGPROP: goto do_JSOP_GETARGPROP;
|
||||
case JSOP_GETVARPROP: goto do_JSOP_GETVARPROP;
|
||||
case JSOP_GETLOCALPROP: goto do_JSOP_GETLOCALPROP;
|
||||
default: LOCAL_ASSERT(0);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
break;
|
||||
|
||||
BEGIN_LITOPX_CASE(JSOP_NUMBER)
|
||||
BEGIN_LITOPX_CASE(JSOP_NUMBER, 0)
|
||||
val = ATOM_KEY(atom);
|
||||
if (JSVAL_IS_INT(val)) {
|
||||
long ival = (long)JSVAL_TO_INT(val);
|
||||
|
@ -3494,7 +3544,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
}
|
||||
END_LITOPX_CASE
|
||||
|
||||
BEGIN_LITOPX_CASE(JSOP_STRING)
|
||||
BEGIN_LITOPX_CASE(JSOP_STRING, 0)
|
||||
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
|
||||
inXML ? DONT_ESCAPE : '"');
|
||||
if (!rval)
|
||||
|
@ -3744,7 +3794,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
lval, (op == JSOP_STRICTEQ) ? '=' : '!', rval);
|
||||
break;
|
||||
|
||||
BEGIN_LITOPX_CASE(JSOP_CLOSURE)
|
||||
BEGIN_LITOPX_CASE(JSOP_CLOSURE, 0)
|
||||
LOCAL_ASSERT(ATOM_IS_OBJECT(atom));
|
||||
todo = -2;
|
||||
goto do_function;
|
||||
|
@ -3756,7 +3806,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
todo = -2;
|
||||
break;
|
||||
|
||||
BEGIN_LITOPX_CASE(JSOP_EXPORTNAME)
|
||||
BEGIN_LITOPX_CASE(JSOP_EXPORTNAME, 0)
|
||||
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
|
||||
if (!rval)
|
||||
return NULL;
|
||||
|
@ -3953,7 +4003,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
}
|
||||
break;
|
||||
|
||||
BEGIN_LITOPX_CASE(JSOP_QNAMEPART)
|
||||
BEGIN_LITOPX_CASE(JSOP_QNAMEPART, 0)
|
||||
if (pc[JSOP_QNAMEPART_LENGTH] == JSOP_TOATTRNAME) {
|
||||
saveop = JSOP_TOATTRNAME;
|
||||
len += JSOP_TOATTRNAME_LENGTH;
|
||||
|
@ -3963,7 +4013,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
goto do_name;
|
||||
END_LITOPX_CASE
|
||||
|
||||
BEGIN_LITOPX_CASE(JSOP_QNAMECONST)
|
||||
BEGIN_LITOPX_CASE(JSOP_QNAMECONST, 0)
|
||||
rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
|
||||
if (!rval)
|
||||
return NULL;
|
||||
|
@ -4058,26 +4108,26 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
|
|||
todo = Sprint(&ss->sprinter, "%s..%s", lval, rval);
|
||||
break;
|
||||
|
||||
BEGIN_LITOPX_CASE(JSOP_XMLOBJECT)
|
||||
BEGIN_LITOPX_CASE(JSOP_XMLOBJECT, 0)
|
||||
todo = Sprint(&ss->sprinter, "<xml address='%p'>",
|
||||
ATOM_TO_OBJECT(atom));
|
||||
END_LITOPX_CASE
|
||||
|
||||
BEGIN_LITOPX_CASE(JSOP_XMLCDATA)
|
||||
BEGIN_LITOPX_CASE(JSOP_XMLCDATA, 0)
|
||||
todo = SprintPut(&ss->sprinter, "<![CDATA[", 9);
|
||||
if (!QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0))
|
||||
return NULL;
|
||||
SprintPut(&ss->sprinter, "]]>", 3);
|
||||
END_LITOPX_CASE
|
||||
|
||||
BEGIN_LITOPX_CASE(JSOP_XMLCOMMENT)
|
||||
BEGIN_LITOPX_CASE(JSOP_XMLCOMMENT, 0)
|
||||
todo = SprintPut(&ss->sprinter, "<!--", 4);
|
||||
if (!QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0))
|
||||
return NULL;
|
||||
SprintPut(&ss->sprinter, "-->", 3);
|
||||
END_LITOPX_CASE
|
||||
|
||||
BEGIN_LITOPX_CASE(JSOP_XMLPI)
|
||||
BEGIN_LITOPX_CASE(JSOP_XMLPI, 0)
|
||||
rval = JS_strdup(cx, POP_STR());
|
||||
if (!rval)
|
||||
return NULL;
|
||||
|
@ -4596,21 +4646,25 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
|
|||
cs = &js_CodeSpec[op];
|
||||
begin = pc;
|
||||
end = pc + cs->length;
|
||||
if ((cs->format & JOF_MODEMASK) != JOF_NAME) {
|
||||
JSSrcNoteType noteType;
|
||||
|
||||
switch (cs->format & JOF_MODEMASK) {
|
||||
case JOF_PROP:
|
||||
case JOF_ELEM:
|
||||
sn = js_GetSrcNote(script, pc);
|
||||
if (!sn)
|
||||
goto do_fallback;
|
||||
noteType = SN_TYPE(sn);
|
||||
if (noteType == SRC_PCBASE) {
|
||||
switch (SN_TYPE(sn)) {
|
||||
case SRC_PCBASE:
|
||||
begin -= js_GetSrcNoteOffset(sn, 0);
|
||||
} else if (noteType == SRC_PCDELTA) {
|
||||
break;
|
||||
case SRC_PCDELTA:
|
||||
end = begin + js_GetSrcNoteOffset(sn, 0);
|
||||
begin += cs->length;
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
goto do_fallback;
|
||||
}
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
len = PTRDIFF(end, begin, jsbytecode);
|
||||
if (len <= 0)
|
||||
|
|
|
@ -92,22 +92,23 @@ typedef enum JSOpLength {
|
|||
#define JOF_NAME 0x0010 /* name operation */
|
||||
#define JOF_PROP 0x0020 /* obj.prop operation */
|
||||
#define JOF_ELEM 0x0030 /* obj[index] operation */
|
||||
#define JOF_MODEMASK 0x0030 /* mask for above addressing modes */
|
||||
#define JOF_SET 0x0040 /* set (i.e., assignment) operation */
|
||||
#define JOF_DEL 0x0080 /* delete operation */
|
||||
#define JOF_DEC 0x0100 /* decrement (--, not ++) opcode */
|
||||
#define JOF_INC 0x0200 /* increment (++, not --) opcode */
|
||||
#define JOF_INCDEC 0x0300 /* increment or decrement opcode */
|
||||
#define JOF_POST 0x0400 /* postorder increment or decrement */
|
||||
#define JOF_IMPORT 0x0800 /* import property op */
|
||||
#define JOF_FOR 0x1000 /* for-in property op */
|
||||
#define JOF_XMLNAME 0x0040 /* XML name: *, a::b, @a, @a::b, etc. */
|
||||
#define JOF_VARPROP 0x0050 /* x.prop for arg, var, or local x */
|
||||
#define JOF_MODEMASK 0x0070 /* mask for above addressing modes */
|
||||
#define JOF_SET 0x0080 /* set (i.e., assignment) operation */
|
||||
#define JOF_DEL 0x0100 /* delete operation */
|
||||
#define JOF_DEC 0x0200 /* decrement (--, not ++) opcode */
|
||||
#define JOF_INC 0x0400 /* increment (++, not --) opcode */
|
||||
#define JOF_INCDEC 0x0600 /* increment or decrement opcode */
|
||||
#define JOF_POST 0x0800 /* postorder increment or decrement */
|
||||
#define JOF_IMPORT 0x1000 /* import property op */
|
||||
#define JOF_FOR 0x2000 /* for-in property op */
|
||||
#define JOF_ASSIGNING JOF_SET /* hint for JSClass.resolve, used for ops
|
||||
that do simplex assignment */
|
||||
#define JOF_DETECTING 0x2000 /* object detection flag for JSNewResolveOp */
|
||||
#define JOF_BACKPATCH 0x4000 /* backpatch placeholder during codegen */
|
||||
#define JOF_LEFTASSOC 0x8000 /* left-associative operator */
|
||||
#define JOF_DECLARING 0x10000 /* var, const, or function declaration op */
|
||||
#define JOF_XMLNAME 0x20000 /* XML name: *, a::b, @a, @a::b, etc. */
|
||||
#define JOF_DETECTING 0x4000 /* object detection flag for JSNewResolveOp */
|
||||
#define JOF_BACKPATCH 0x8000 /* backpatch placeholder during codegen */
|
||||
#define JOF_LEFTASSOC 0x10000 /* left-associative operator */
|
||||
#define JOF_DECLARING 0x20000 /* var, const, or function declaration op */
|
||||
|
||||
#define JOF_TYPE_IS_EXTENDED_JUMP(t) \
|
||||
((unsigned)((t) - JOF_JUMPX) <= (unsigned)(JOF_LOOKUPSWITCHX - JOF_JUMPX))
|
||||
|
|
|
@ -478,6 +478,9 @@ OPDEF(JSOP_ENUMCONSTELEM, 214,"enumconstelem",NULL, 1, 3, 0, 3, JOF_BYTE|J
|
|||
OPDEF(JSOP_LEAVEBLOCKEXPR,215,"leaveblockexpr",NULL, 3, 0, 0, 1, JOF_UINT16)
|
||||
|
||||
/*
|
||||
* Optimization equivalent to the very common JSOP_THIS -> JSOP_GETPROP cliche.
|
||||
* Optimize common JSOP_{THIS,GET{ARG,VAR,LOCAL}} -> JSOP_GETPROP cliches.
|
||||
*/
|
||||
OPDEF(JSOP_GETTHISPROP, 216,"getthisprop", NULL, 3, 0, 1, 18, JOF_CONST|JOF_NAME)
|
||||
OPDEF(JSOP_GETTHISPROP, 216,"getthisprop", NULL, 3, 0, 1, 18, JOF_CONST)
|
||||
OPDEF(JSOP_GETARGPROP, 217,"getargprop", NULL, 5, 0, 1, 18, JOF_INDEXCONST|JOF_VARPROP)
|
||||
OPDEF(JSOP_GETVARPROP, 218,"getvarprop", NULL, 5, 0, 1, 18, JOF_INDEXCONST|JOF_VARPROP)
|
||||
OPDEF(JSOP_GETLOCALPROP, 219,"getlocalprop", NULL, 5, 0, 1, 18, JOF_INDEXCONST|JOF_VARPROP)
|
||||
|
|
Загрузка…
Ссылка в новой задаче