Optimize x.p for arg/var/local x; fix decompiler bugs hiding nearby (363536, r=igor).

This commit is contained in:
brendan%mozilla.org 2006-12-27 23:47:13 +00:00
Родитель 18c829229c
Коммит 0e994e3456
5 изменённых файлов: 221 добавлений и 89 удалений

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

@ -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)