Igor's patch for simpler extended atom indexing (365608, tweaks and r=me).

This commit is contained in:
brendan%mozilla.org 2007-01-06 23:25:00 +00:00
parent 2296397878
commit 5535f707ed
8 changed files with 355 additions and 499 deletions

View File

@ -928,7 +928,7 @@ GetSwitchTableBounds(JSScript *script, uintN offset,
pc += jmplen;
n = GET_ATOM_INDEX(pc);
pc += ATOM_INDEX_LEN;
jmplen += ATOM_INDEX_LEN;
jmplen += JUMP_OFFSET_LEN;
break;
}

View File

@ -595,8 +595,8 @@ BuildSpanDepTable(JSContext *cx, JSCodeGenerator *cg)
if (!AddSpanDep(cx, cg, pc, pc2, off))
return JS_FALSE;
pc2 += JUMP_OFFSET_LEN;
npairs = (jsint) GET_ATOM_INDEX(pc2);
pc2 += ATOM_INDEX_LEN;
npairs = (jsint) GET_UINT16(pc2);
pc2 += UINT16_LEN;
while (npairs) {
pc2 += ATOM_INDEX_LEN;
off = GET_JUMP_OFFSET(pc2);
@ -1734,76 +1734,42 @@ IndexRegExpClone(JSContext *cx, JSParseNode *pn, JSAtomListElement *ale,
return JS_TRUE;
}
static int
EmitBigIndexPrefix(JSContext *cx, JSCodeGenerator *cg, jsatomid atomIndex)
{
if (atomIndex < JS_BIT(16))
return JSOP_NOP;
atomIndex >>= 16;
if (atomIndex <= JSOP_ATOMBASE3 - JSOP_ATOMBASE1 + 1) {
if (js_Emit1(cx, cg, JSOP_ATOMBASE1 + atomIndex - 1) < 0)
return -1;
return JSOP_RESETBASE0;
}
if (js_Emit2(cx, cg, JSOP_ATOMBASE, atomIndex) < 0)
return -1;
return JSOP_RESETBASE;
}
/*
* 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 the atomIndex requires more than 2 bytes, emit a prefix op whose 8-bit
* immediate operand effectively extends the 16-bit immediate of the prefixed
* opcode, by changing atom "segment" within script->atomMap (see jsinterp.c).
* We optimize segments 1-3 with single-byte JSOP_ATOMBASE[123] codes.
*
* 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.
* Such prefixing currently requires a suffix to restore the "zero segment"
* register setting, but this could be optimized further.
*/
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);
if (op != JSOP_SETNAME) {
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_GETXPROP: op = JSOP_GETXELEM; 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_BINDNAME: return JS_TRUE;
case JSOP_SETNAME: op = JSOP_SETELEM; break;
case JSOP_SETPROP: op = JSOP_SETELEM; break;
default: break;
}
return js_Emit1(cx, cg, op) >= 0;
}
int bigSuffix;
bigSuffix = EmitBigIndexPrefix(cx, cg, atomIndex);
if (bigSuffix < 0)
return JS_FALSE;
EMIT_UINT16_IMM_OP(op, atomIndex);
return JS_TRUE;
return bigSuffix == JSOP_NOP || js_Emit1(cx, cg, bigSuffix) >= 0;
}
/*
@ -1844,31 +1810,23 @@ static JSBool
EmitIndexConstOp(JSContext *cx, JSOp op, uintN slot, jsatomid atomIndex,
JSCodeGenerator *cg)
{
int bigSuffix;
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;
bigSuffix = EmitBigIndexPrefix(cx, cg, atomIndex);
if (bigSuffix < 0)
return JS_FALSE;
/* 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 bigSuffix == 0 || js_Emit1(cx, cg, bigSuffix) >= 0;
}
/*
@ -2590,7 +2548,7 @@ EmitNumberOp(JSContext *cx, jsdouble dval, JSCodeGenerator *cg)
if (off < 0)
return JS_FALSE;
pc = CG_CODE(cg, off);
SET_LITERAL_INDEX(pc, atomIndex);
SET_UINT24(pc, atomIndex);
return JS_TRUE;
}

View File

@ -632,7 +632,6 @@ NoSuchMethod(JSContext *cx, JSStackFrame *fp, jsval *vp, uint32 flags,
JSObject *thisp, *argsobj;
jsid id;
jsbytecode *pc;
jsatomid atomIndex;
JSAtom *atom;
uintN argc;
JSArena *a;
@ -691,8 +690,7 @@ NoSuchMethod(JSContext *cx, JSStackFrame *fp, jsval *vp, uint32 flags,
#if JS_HAS_XML_SUPPORT
case JSOP_GETMETHOD:
#endif
atomIndex = GET_ATOM_INDEX(pc);
atom = js_GetAtom(cx, &fp->script->atomMap, atomIndex);
atom = js_GetAtomFromBytecode(cx, fp->script, pc, 0);
argc = *argcp;
argsobj = js_NewArrayObject(cx, argc, vp + 2);
if (!argsobj)
@ -760,7 +758,7 @@ typedef struct CallKey {
/* Compensate for typeof null == "object" brain damage. */
#define JSTYPE_NULL JSTYPE_LIMIT
#define TYPEOF(cx,v) (JSVAL_IS_NULL(v) ? JSTYPE_NULL : JS_TypeOfValue(cx,v))
#define TYPENAME(t) (((t) == JSTYPE_NULL) ? js_null_str : js_type_str[t])
#define TYPENAME(t) (((t) == JSTYPE_NULL) ? js_null_str : js_type_strs[t])
#define NTYPEHIST (JSTYPE_LIMIT + 1)
typedef struct CallValue {
@ -907,7 +905,8 @@ CallTableDumper(JSHashEntry *he, intN k, void *arg)
argval = avc->value;
fprintf(fp, " %9u: %8lu %.*s (%#lx)\n",
n, (unsigned long) avc->count,
sizeof avc->strbuf, avc->strbuf, argval);
(int) sizeof avc->strbuf, avc->strbuf,
argval);
++n;
}
}
@ -1032,13 +1031,13 @@ LogCall(JSContext *cx, jsval callee, uintN argc, jsval *argv)
cstr = "";
switch (TYPEOF(cx, argval)) {
case JSTYPE_VOID:
cstr = js_type_str[JSTYPE_VOID];
cstr = js_type_strs[JSTYPE_VOID];
break;
case JSTYPE_NULL:
cstr = js_null_str;
break;
case JSTYPE_BOOLEAN:
cstr = js_boolean_str[JSVAL_TO_BOOLEAN(argval)];
cstr = js_boolean_strs[JSVAL_TO_BOOLEAN(argval)];
break;
case JSTYPE_NUMBER:
if (JSVAL_IS_INT(argval)) {
@ -2196,6 +2195,7 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
JSStackFrame *fp;
JSScript *script;
uintN inlineCallCount;
JSAtom **atoms;
JSObject *obj, *obj2, *parent;
JSVersion currentVersion, originalVersion;
JSBranchCallback onbranch;
@ -2289,6 +2289,11 @@ js_Interpret(JSContext *cx, jsbytecode *pc, jsval *result)
/* Count of JS function calls that nest in this C js_Interpret frame. */
inlineCallCount = 0;
/* Load the atom base register used by LOAD_ATOM and inline equivalents. */
atoms = script->atomMap.vector;
#define LOAD_ATOM(PCOFF) (atom = GET_ATOM(cx, atoms, pc + PCOFF))
/*
* Optimized Get and SetVersion for proper script language versioning.
*
@ -2629,6 +2634,7 @@ interrupt:
/* Restore the calling script's interpreter registers. */
script = fp->script;
depth = (jsint) script->depth;
atoms = script->atomMap.vector;
pc = fp->pc;
#ifndef JS_THREADED_INTERP
endpc = script->code + script->length;
@ -2813,14 +2819,14 @@ interrupt:
* Handle JSOP_FORPROP first, so the cost of the goto do_forinloop
* is not paid for the more common cases.
*/
lval = FETCH_OPND(-1);
atom = GET_ATOM(cx, script, pc);
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
lval = FETCH_OPND(-1);
i = -2;
goto do_forinloop;
BEGIN_CASE(JSOP_FORNAME)
atom = GET_ATOM(cx, script, pc);
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
/*
@ -3050,17 +3056,9 @@ interrupt:
} \
JS_END_MACRO
#define BEGIN_LITOPX_CASE(OP,PCOFF) \
BEGIN_CASE(OP) \
pc2 = pc; \
atomIndex = GET_ATOM_INDEX(pc + PCOFF); \
do_##OP: \
atom = js_GetAtom(cx, &script->atomMap, atomIndex);
#define END_LITOPX_CASE(OP) \
END_CASE(OP)
BEGIN_LITOPX_CASE(JSOP_SETCONST, 0)
BEGIN_CASE(JSOP_SETCONST)
LOAD_ATOM(0);
obj = fp->varobj;
rval = FETCH_OPND(-1);
SAVE_SP_AND_PC(fp);
@ -3072,7 +3070,7 @@ interrupt:
if (!ok)
goto out;
STORE_OPND(-1, rval);
END_LITOPX_CASE(JSOP_SETCONST)
END_CASE(JSOP_SETCONST)
#if JS_HAS_DESTRUCTURING
BEGIN_CASE(JSOP_ENUMCONSTELEM)
@ -3091,18 +3089,20 @@ interrupt:
END_CASE(JSOP_ENUMCONSTELEM)
#endif
BEGIN_LITOPX_CASE(JSOP_BINDNAME, 0)
BEGIN_CASE(JSOP_BINDNAME)
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
SAVE_SP_AND_PC(fp);
obj = js_FindIdentifierBase(cx, ATOM_TO_JSID(atom));
obj = js_FindIdentifierBase(cx, id);
if (!obj) {
ok = JS_FALSE;
goto out;
}
PUSH_OPND(OBJECT_TO_JSVAL(obj));
END_LITOPX_CASE(JSOP_BINDNAME)
END_CASE(JSOP_BINDNAME)
BEGIN_CASE(JSOP_SETNAME)
atom = GET_ATOM(cx, script, pc);
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
rval = FETCH_OPND(-1);
lval = FETCH_OPND(-2);
@ -3558,7 +3558,7 @@ interrupt:
DO_NEXT_OP(len);
BEGIN_CASE(JSOP_DELNAME)
atom = GET_ATOM(cx, script, pc);
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
SAVE_SP_AND_PC(fp);
@ -3578,7 +3578,7 @@ interrupt:
END_CASE(JSOP_DELNAME)
BEGIN_CASE(JSOP_DELPROP)
atom = GET_ATOM(cx, script, pc);
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
PROPERTY_OP(-1, ok = OBJ_DELETE_PROPERTY(cx, obj, id, &rval));
STORE_OPND(-1, rval);
@ -3608,7 +3608,7 @@ interrupt:
BEGIN_CASE(JSOP_DECNAME)
BEGIN_CASE(JSOP_NAMEINC)
BEGIN_CASE(JSOP_NAMEDEC)
atom = GET_ATOM(cx, script, pc);
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
SAVE_SP_AND_PC(fp);
@ -3627,7 +3627,7 @@ interrupt:
BEGIN_CASE(JSOP_DECPROP)
BEGIN_CASE(JSOP_PROPINC)
BEGIN_CASE(JSOP_PROPDEC)
atom = GET_ATOM(cx, script, pc);
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
lval = FETCH_OPND(-1);
i = -1;
@ -3830,7 +3830,8 @@ interrupt:
DO_NEXT_OP(len);
}
BEGIN_LITOPX_CASE(JSOP_GETTHISPROP, 0)
BEGIN_CASE(JSOP_GETTHISPROP)
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
obj = fp->thisp;
SAVE_SP_AND_PC(fp);
@ -3838,23 +3839,26 @@ interrupt:
if (!ok)
goto out;
PUSH_OPND(rval);
END_LITOPX_CASE(JSOP_GETTHISPROP)
END_CASE(JSOP_GETTHISPROP)
BEGIN_LITOPX_CASE(JSOP_GETARGPROP, ARGNO_LEN)
BEGIN_CASE(JSOP_GETARGPROP)
LOAD_ATOM(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)
BEGIN_CASE(JSOP_GETVARPROP)
LOAD_ATOM(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)
BEGIN_CASE(JSOP_GETLOCALPROP)
LOAD_ATOM(2);
slot = GET_UINT16(pc);
JS_ASSERT(slot < (uintN)depth);
PUSH_OPND(fp->spbase[slot]);
@ -3864,7 +3868,7 @@ interrupt:
BEGIN_CASE(JSOP_GETPROP)
BEGIN_CASE(JSOP_GETXPROP)
/* Get an immediate atom naming the property. */
atom = GET_ATOM(cx, script, pc);
LOAD_ATOM(0);
len = JSOP_GETPROP_LENGTH;
do_getprop_body:
@ -3886,12 +3890,12 @@ interrupt:
END_VARLEN_CASE
BEGIN_CASE(JSOP_SETPROP)
/* Get an immediate atom naming the property. */
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
/* Pop the right-hand side into rval for OBJ_SET_PROPERTY. */
rval = FETCH_OPND(-1);
/* Get an immediate atom naming the property. */
atom = GET_ATOM(cx, script, pc);
id = ATOM_TO_JSID(atom);
PROPERTY_OP(-2, CACHED_SET(OBJ_SET_PROPERTY(cx, obj, id, &rval)));
sp--;
STORE_OPND(-1, rval);
@ -3988,6 +3992,7 @@ interrupt:
nvars = fun->u.i.nvars;
script = fun->u.i.script;
depth = (jsint) script->depth;
atoms = script->atomMap.vector;
nslots = nframeslots + nvars + 2 * depth;
/* Allocate missing expected args adjacent to actual args. */
@ -4136,6 +4141,7 @@ interrupt:
bad_inline_call:
script = fp->script;
depth = (jsint) script->depth;
atoms = script->atomMap.vector;
ok = JS_FALSE;
goto out;
}
@ -4197,7 +4203,7 @@ interrupt:
#endif
BEGIN_CASE(JSOP_NAME)
atom = GET_ATOM(cx, script, pc);
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
SAVE_SP_AND_PC(fp);
@ -4235,112 +4241,42 @@ interrupt:
END_CASE(JSOP_NAME)
BEGIN_CASE(JSOP_UINT16)
i = (jsint) GET_ATOM_INDEX(pc);
i = (jsint) GET_UINT16(pc);
rval = INT_TO_JSVAL(i);
PUSH_OPND(rval);
obj = NULL;
END_CASE(JSOP_UINT16)
BEGIN_CASE(JSOP_UINT24)
i = (jsint) GET_LITERAL_INDEX(pc);
i = (jsint) GET_UINT24(pc);
rval = INT_TO_JSVAL(i);
PUSH_OPND(rval);
END_CASE(JSOP_UINT24)
BEGIN_CASE(JSOP_LITERAL)
atomIndex = GET_LITERAL_INDEX(pc);
atom = js_GetAtom(cx, &script->atomMap, atomIndex);
PUSH_OPND(ATOM_KEY(atom));
obj = NULL;
END_CASE(JSOP_LITERAL)
BEGIN_CASE(JSOP_ATOMBASE)
atoms += GET_ATOMBASE(pc);
END_CASE(JSOP_ATOMBASE)
BEGIN_CASE(JSOP_FINDNAME)
atomIndex = GET_LITERAL_INDEX(pc);
atom = js_GetAtom(cx, &script->atomMap, atomIndex);
SAVE_SP_AND_PC(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));
END_CASE(JSOP_FINDNAME)
BEGIN_CASE(JSOP_ATOMBASE1)
BEGIN_CASE(JSOP_ATOMBASE2)
BEGIN_CASE(JSOP_ATOMBASE3)
atoms += (op - JSOP_ATOMBASE1 + 1) << 16;
END_CASE(JSOP_ATOMBASE3)
BEGIN_CASE(JSOP_LITOPX)
/*
* Load atomIndex, which is used by code at each do_JSOP_* label.
*
* Also set pc2 to point at the bytecode extended by this prefix
* to have a leading 24 bit atomIndex, instead of the unextended
* 16-bit atomIndex that normally comes after op. This enables
* JOF_INDEXCONST format ops (which have multiple immediates) to
* collect their other immediate via GET_VARNO(pc2) or similar.
*
* Finally, load op and, if threading, adjust pc so that it will
* be advanced properly at the end of op's case by DO_NEXT_OP.
*/
atomIndex = GET_LITERAL_INDEX(pc);
pc2 = pc + 1 + LITERAL_INDEX_LEN;
op = *pc2;
pc += JSOP_LITOPX_LENGTH - (1 + ATOM_INDEX_LEN);
#ifndef JS_THREADED_INTERP
len = js_CodeSpec[op].length;
#endif
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;
#if JS_HAS_EXPORT_IMPORT
case JSOP_EXPORTNAME: goto do_JSOP_EXPORTNAME;
#endif
#if JS_HAS_XML_SUPPORT
case JSOP_GETMETHOD: goto do_JSOP_GETMETHOD;
case JSOP_SETMETHOD: goto do_JSOP_SETMETHOD;
#endif
case JSOP_NAMEDFUNOBJ: goto do_JSOP_NAMEDFUNOBJ;
case JSOP_NUMBER: goto do_JSOP_NUMBER;
case JSOP_OBJECT: goto do_JSOP_OBJECT;
#if JS_HAS_XML_SUPPORT
case JSOP_QNAMECONST: goto do_JSOP_QNAMECONST;
case JSOP_QNAMEPART: goto do_JSOP_QNAMEPART;
#endif
case JSOP_REGEXP: goto do_JSOP_REGEXP;
case JSOP_SETCONST: goto do_JSOP_SETCONST;
case JSOP_STRING: goto do_JSOP_STRING;
#if JS_HAS_XML_SUPPORT
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;
#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 */
BEGIN_CASE(JSOP_RESETBASE0)
BEGIN_CASE(JSOP_RESETBASE)
atoms = script->atomMap.vector;
END_CASE(JSOP_RESETBASE)
BEGIN_CASE(JSOP_NUMBER)
BEGIN_CASE(JSOP_STRING)
BEGIN_CASE(JSOP_OBJECT)
atomIndex = GET_ATOM_INDEX(pc);
do_JSOP_NUMBER:
do_JSOP_STRING:
do_JSOP_OBJECT:
atom = js_GetAtom(cx, &script->atomMap, atomIndex);
LOAD_ATOM(0);
PUSH_OPND(ATOM_KEY(atom));
obj = NULL;
END_CASE(JSOP_NUMBER)
BEGIN_LITOPX_CASE(JSOP_REGEXP, 0)
BEGIN_CASE(JSOP_REGEXP)
{
JSRegExp *re;
JSObject *funobj;
@ -4369,6 +4305,7 @@ interrupt:
* need a similar op for other kinds of object literals, we should
* push cloning down under JSObjectOps and reuse code here.
*/
LOAD_ATOM(0);
JS_ASSERT(ATOM_IS_OBJECT(atom));
obj = ATOM_TO_OBJECT(atom);
JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_RegExpClass);
@ -4461,7 +4398,7 @@ interrupt:
PUSH_OPND(rval);
obj = NULL;
}
END_LITOPX_CASE(JSOP_REGEXP)
END_CASE(JSOP_REGEXP)
BEGIN_CASE(JSOP_ZERO)
PUSH_OPND(JSVAL_ZERO);
@ -4548,12 +4485,12 @@ interrupt:
}
pc2 += JUMP_OFFSET_LEN;
npairs = (jsint) GET_ATOM_INDEX(pc2);
pc2 += ATOM_INDEX_LEN;
npairs = (jsint) GET_UINT16(pc2);
pc2 += UINT16_LEN;
#define SEARCH_PAIRS(MATCH_CODE) \
while (npairs) { \
atom = GET_ATOM(cx, script, pc2); \
atom = GET_ATOM(cx, atoms, pc2); \
rval = ATOM_KEY(atom); \
MATCH_CODE \
if (match) { \
@ -4625,12 +4562,12 @@ interrupt:
}
pc2 += JUMPX_OFFSET_LEN;
npairs = (jsint) GET_ATOM_INDEX(pc2);
pc2 += ATOM_INDEX_LEN;
npairs = (jsint) GET_UINT16(pc2);
pc2 += UINT16_LEN;
#define SEARCH_EXTENDED_PAIRS(MATCH_CODE) \
while (npairs) { \
atom = GET_ATOM(cx, script, pc2); \
atom = GET_ATOM(cx, atoms, pc2); \
rval = ATOM_KEY(atom); \
MATCH_CODE \
if (match) { \
@ -4692,7 +4629,8 @@ interrupt:
}
END_CASE(JSOP_EXPORTALL)
BEGIN_LITOPX_CASE(JSOP_EXPORTNAME, 0)
BEGIN_CASE(JSOP_EXPORTNAME)
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
obj = fp->varobj;
SAVE_SP_AND_PC(fp);
@ -4712,7 +4650,7 @@ interrupt:
}
if (!ok)
goto out;
END_LITOPX_CASE(JSOP_EXPORTNAME)
END_CASE(JSOP_EXPORTNAME)
BEGIN_CASE(JSOP_IMPORTALL)
id = (jsid) JSVAL_VOID;
@ -4722,7 +4660,7 @@ interrupt:
BEGIN_CASE(JSOP_IMPORTPROP)
/* Get an immediate atom naming the property. */
atom = GET_ATOM(cx, script, pc);
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
PROPERTY_OP(-1, ok = ImportProperty(cx, obj, id));
sp--;
@ -4863,7 +4801,7 @@ interrupt:
* JSOP_SETGVAR has arity 1: [rval], not arity 2: [obj, rval]
* as JSOP_SETNAME does, where [obj] is due to JSOP_BINDNAME.
*/
atom = GET_ATOM(cx, script, pc);
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
SAVE_SP_AND_PC(fp);
CACHED_SET(OBJ_SET_PROPERTY(cx, obj, id, &rval));
@ -4881,10 +4819,7 @@ interrupt:
BEGIN_CASE(JSOP_DEFCONST)
BEGIN_CASE(JSOP_DEFVAR)
atomIndex = GET_ATOM_INDEX(pc);
do_JSOP_DEFCONST:
do_JSOP_DEFVAR:
atom = js_GetAtom(cx, &script->atomMap, atomIndex);
atom = atoms[atomIndex];
obj = fp->varobj;
attrs = JSPROP_ENUMERATE;
if (!(fp->flags & JSFRAME_EVAL))
@ -4936,7 +4871,9 @@ interrupt:
OBJ_DROP_PROPERTY(cx, obj2, prop);
END_CASE(JSOP_DEFVAR)
BEGIN_LITOPX_CASE(JSOP_DEFFUN, 0)
BEGIN_CASE(JSOP_DEFFUN)
atomIndex = GET_ATOM_INDEX(pc);
atom = atoms[atomIndex];
obj = ATOM_TO_OBJECT(atom);
fun = (JSFunction *) JS_GetPrivate(cx, obj);
id = ATOM_TO_JSID(fun->atom);
@ -5048,9 +4985,10 @@ interrupt:
}
#endif
OBJ_DROP_PROPERTY(cx, parent, prop);
END_LITOPX_CASE(JSOP_DEFFUN)
END_CASE(JSOP_DEFFUN)
BEGIN_LITOPX_CASE(JSOP_DEFLOCALFUN, VARNO_LEN)
BEGIN_CASE(JSOP_DEFLOCALFUN)
LOAD_ATOM(VARNO_LEN);
/*
* Define a local function (i.e., one nested at the top level of
* another function), parented by the current scope chain, and
@ -5058,7 +4996,7 @@ interrupt:
* This is an optimization over JSOP_DEFFUN that avoids requiring
* a call object for the outer function's activation.
*/
slot = GET_VARNO(pc2);
slot = GET_VARNO(pc);
obj = ATOM_TO_OBJECT(atom);
/*
@ -5097,10 +5035,11 @@ interrupt:
if (!ok)
goto out;
fp->vars[slot] = OBJECT_TO_JSVAL(obj);
END_LITOPX_CASE(JSOP_DEFLOCALFUN)
END_CASE(JSOP_DEFLOCALFUN)
BEGIN_LITOPX_CASE(JSOP_ANONFUNOBJ, 0)
BEGIN_CASE(JSOP_ANONFUNOBJ)
/* Push the specified function object literal. */
LOAD_ATOM(0);
obj = ATOM_TO_OBJECT(atom);
/* If re-parenting, push a clone of the function object. */
@ -5119,10 +5058,11 @@ interrupt:
}
PUSH_OPND(OBJECT_TO_JSVAL(obj));
obj = NULL;
END_LITOPX_CASE(JSOP_ANONFUNOBJ)
END_CASE(JSOP_ANONFUNOBJ)
BEGIN_LITOPX_CASE(JSOP_NAMEDFUNOBJ, 0)
BEGIN_CASE(JSOP_NAMEDFUNOBJ)
/* ECMA ed. 3 FunctionExpression: function Identifier [etc.]. */
LOAD_ATOM(0);
rval = ATOM_KEY(atom);
JS_ASSERT(VALUE_IS_FUNCTION(cx, rval));
@ -5211,9 +5151,12 @@ interrupt:
*/
PUSH_OPND(OBJECT_TO_JSVAL(obj));
obj = NULL;
END_LITOPX_CASE(JSOP_NAMEDFUNOBJ)
END_CASE(JSOP_NAMEDFUNOBJ)
BEGIN_CASE(JSOP_CLOSURE)
atomIndex = GET_ATOM_INDEX(pc);
atom = atoms[atomIndex];
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
@ -5296,16 +5239,27 @@ interrupt:
}
#endif
OBJ_DROP_PROPERTY(cx, parent, prop);
END_LITOPX_CASE(JSOP_CLOSURE)
END_CASE(JSOP_CLOSURE)
#if JS_HAS_GETTER_SETTER
BEGIN_CASE(JSOP_GETTER)
BEGIN_CASE(JSOP_SETTER)
do_getter_setter:
op2 = (JSOp) *++pc;
switch (op2) {
case JSOP_ATOMBASE:
atoms += GET_ATOMBASE(pc);
pc += JSOP_ATOMBASE_LENGTH - 1;
goto do_getter_setter;
case JSOP_ATOMBASE1:
case JSOP_ATOMBASE2:
case JSOP_ATOMBASE3:
atoms += (op2 - JSOP_ATOMBASE1 + 1) << 16;
goto do_getter_setter;
case JSOP_SETNAME:
case JSOP_SETPROP:
atom = GET_ATOM(cx, script, pc);
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
rval = FETCH_OPND(-1);
i = -1;
@ -5323,7 +5277,7 @@ interrupt:
JS_ASSERT(sp - fp->spbase >= 2);
rval = FETCH_OPND(-1);
i = -1;
atom = GET_ATOM(cx, script, pc);
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
goto gs_get_lval;
@ -5410,13 +5364,13 @@ interrupt:
END_CASE(JSOP_ENDINIT)
BEGIN_CASE(JSOP_INITPROP)
/* Get the immediate property name into id. */
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
/* Pop the property's value into rval. */
JS_ASSERT(sp - fp->spbase >= 2);
rval = FETCH_OPND(-1);
/* Get the immediate property name into id. */
atom = GET_ATOM(cx, script, pc);
id = ATOM_TO_JSID(atom);
i = -1;
goto do_init;
@ -5459,7 +5413,7 @@ interrupt:
}
fp->sharpArray = obj;
}
i = (jsint) GET_ATOM_INDEX(pc);
i = (jsint) GET_UINT16(pc);
id = INT_TO_JSID(i);
rval = FETCH_OPND(-1);
if (JSVAL_IS_PRIMITIVE(rval)) {
@ -5476,7 +5430,7 @@ interrupt:
END_CASE(JSOP_DEFSHARP)
BEGIN_CASE(JSOP_USESHARP)
i = (jsint) GET_ATOM_INDEX(pc);
i = (jsint) GET_UINT16(pc);
id = INT_TO_JSID(i);
obj = fp->sharpArray;
if (!obj) {
@ -5505,8 +5459,7 @@ interrupt:
/* Reset the stack to the given depth. */
BEGIN_CASE(JSOP_SETSP)
i = (jsint) GET_ATOM_INDEX(pc);
JS_ASSERT(i >= 0);
i = (jsint) GET_UINT16(pc);
for (obj = fp->blockChain; obj; obj = OBJ_GET_PARENT(cx, obj)) {
JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_BlockClass);
@ -5682,11 +5635,13 @@ interrupt:
PUSH_OPND(rval);
END_CASE(JSOP_ANYNAME)
BEGIN_LITOPX_CASE(JSOP_QNAMEPART, 0)
BEGIN_CASE(JSOP_QNAMEPART)
LOAD_ATOM(0);
PUSH_OPND(ATOM_KEY(atom));
END_LITOPX_CASE(JSOP_QNAMEPART)
END_CASE(JSOP_QNAMEPART)
BEGIN_LITOPX_CASE(JSOP_QNAMECONST, 0)
BEGIN_CASE(JSOP_QNAMECONST)
LOAD_ATOM(0);
rval = ATOM_KEY(atom);
lval = FETCH_OPND(-1);
SAVE_SP_AND_PC(fp);
@ -5696,7 +5651,7 @@ interrupt:
goto out;
}
STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
END_LITOPX_CASE(JSOP_QNAMECONST)
END_CASE(JSOP_QNAMECONST)
BEGIN_CASE(JSOP_QNAME)
rval = FETCH_OPND(-1);
@ -5872,7 +5827,8 @@ interrupt:
STORE_OPND(-1, STRING_TO_JSVAL(str));
END_CASE(JSOP_XMLELTEXPR)
BEGIN_LITOPX_CASE(JSOP_XMLOBJECT, 0)
BEGIN_CASE(JSOP_XMLOBJECT)
LOAD_ATOM(0);
SAVE_SP_AND_PC(fp);
obj = js_CloneXMLObject(cx, ATOM_TO_OBJECT(atom));
if (!obj) {
@ -5881,9 +5837,10 @@ interrupt:
}
PUSH_OPND(OBJECT_TO_JSVAL(obj));
obj = NULL;
END_LITOPX_CASE(JSOP_XMLOBJECT)
END_CASE(JSOP_XMLOBJECT)
BEGIN_LITOPX_CASE(JSOP_XMLCDATA, 0)
BEGIN_CASE(JSOP_XMLCDATA)
LOAD_ATOM(0);
str = ATOM_TO_STRING(atom);
obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_TEXT, NULL, str);
if (!obj) {
@ -5891,9 +5848,10 @@ interrupt:
goto out;
}
PUSH_OPND(OBJECT_TO_JSVAL(obj));
END_LITOPX_CASE(JSOP_XMLCDATA)
END_CASE(JSOP_XMLCDATA)
BEGIN_LITOPX_CASE(JSOP_XMLCOMMENT, 0)
BEGIN_CASE(JSOP_XMLCOMMENT)
LOAD_ATOM(0);
str = ATOM_TO_STRING(atom);
obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_COMMENT, NULL, str);
if (!obj) {
@ -5901,9 +5859,10 @@ interrupt:
goto out;
}
PUSH_OPND(OBJECT_TO_JSVAL(obj));
END_LITOPX_CASE(JSOP_XMLCOMMENT)
END_CASE(JSOP_XMLCOMMENT)
BEGIN_LITOPX_CASE(JSOP_XMLPI, 0)
BEGIN_CASE(JSOP_XMLPI)
LOAD_ATOM(0);
str = ATOM_TO_STRING(atom);
rval = FETCH_OPND(-1);
str2 = JSVAL_TO_STRING(rval);
@ -5916,10 +5875,11 @@ interrupt:
goto out;
}
STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
END_LITOPX_CASE(JSOP_XMLPI)
END_CASE(JSOP_XMLPI)
BEGIN_LITOPX_CASE(JSOP_GETMETHOD, 0)
BEGIN_CASE(JSOP_GETMETHOD)
/* Get an immediate atom naming the property. */
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
lval = FETCH_OPND(-1);
SAVE_SP_AND_PC(fp);
@ -5968,10 +5928,11 @@ interrupt:
if (!ok)
goto out;
STORE_OPND(-1, rval);
END_LITOPX_CASE(JSOP_GETMETHOD)
END_CASE(JSOP_GETMETHOD)
BEGIN_LITOPX_CASE(JSOP_SETMETHOD, 0)
BEGIN_CASE(JSOP_SETMETHOD)
/* Get an immediate atom naming the property. */
LOAD_ATOM(0);
id = ATOM_TO_JSID(atom);
rval = FETCH_OPND(-1);
FETCH_OBJECT(cx, -2, lval, obj);
@ -5991,7 +5952,7 @@ interrupt:
--sp;
STORE_OPND(-1, rval);
obj = NULL;
END_LITOPX_CASE(JSOP_SETMETHOD)
END_CASE(JSOP_SETMETHOD)
BEGIN_CASE(JSOP_GETFUNNS)
ok = js_GetFunctionNamespace(cx, &rval);
@ -6001,7 +5962,8 @@ interrupt:
END_CASE(JSOP_GETFUNNS)
#endif /* JS_HAS_XML_SUPPORT */
BEGIN_LITOPX_CASE(JSOP_ENTERBLOCK, 0)
BEGIN_CASE(JSOP_ENTERBLOCK)
LOAD_ATOM(0);
obj = ATOM_TO_OBJECT(atom);
JS_ASSERT(fp->spbase + OBJ_BLOCK_DEPTH(cx, obj) == sp);
vp = sp + OBJ_BLOCK_COUNT(cx, obj);
@ -6033,7 +5995,7 @@ interrupt:
OBJ_GET_PARENT(cx, obj) == fp->blockChain);
fp->blockChain = obj;
}
END_LITOPX_CASE(JSOP_ENTERBLOCK)
END_CASE(JSOP_ENTERBLOCK)
BEGIN_CASE(JSOP_LEAVEBLOCKEXPR)
BEGIN_CASE(JSOP_LEAVEBLOCK)

View File

@ -63,11 +63,11 @@
#include "jslock.h"
#include "jsnum.h"
#include "jsobj.h"
#include "jsopcode.h"
#include "jsscan.h"
#include "jsscope.h"
#include "jsscript.h"
#include "jsstr.h"
#include "jsopcode.h"
#include "jsdbgapi.h" /* whether or not JS_HAS_OBJ_WATCHPOINT */
@ -787,7 +787,9 @@ js_obj_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
size_t classnchars = strlen(classname);
static const char classpropid[] = "C";
const char *cp;
#ifdef DEBUG
size_t onchars = nchars;
#endif
/* 2 for ': ', 2 quotes around classname, 2 for ', ' after. */
classnchars += sizeof classpropid - 1 + 2 + 2;
@ -3100,41 +3102,51 @@ Detecting(JSContext *cx, jsbytecode *pc)
if (!cx->fp)
return JS_FALSE;
script = cx->fp->script;
for (endpc = script->code + script->length; pc < endpc; pc++) {
for (endpc = script->code + script->length;
pc < endpc;
pc += js_CodeSpec[op].length) {
/* General case: a branch or equality op follows the access. */
op = (JSOp) *pc;
if (js_CodeSpec[op].format & JOF_DETECTING)
return JS_TRUE;
/*
* Special case #1: handle (document.all == null). Don't sweat about
* JS1.2's revision of the equality operators here.
*/
if (op == JSOP_NULL) {
switch (op) {
case JSOP_NULL:
/*
* Special case #1: handle (document.all == null). Don't sweat
* about JS1.2's revision of the equality operators here.
*/
if (++pc < endpc)
return *pc == JSOP_EQ || *pc == JSOP_NE;
break;
}
return JS_FALSE;
/*
* Special case #2: handle (document.all == undefined). Don't worry
* about someone redefining undefined, which was added by Edition 3,
* so is read/write for backward compatibility.
*/
if (op == JSOP_NAME) {
atom = GET_ATOM(cx, script, pc);
case JSOP_NAME:
/*
* Special case #2: handle (document.all == undefined). Don't
* worry about someone redefining undefined, which was added by
* Edition 3, so is read/write for backward compatibility.
*/
atom = js_GetAtomFromBytecode(cx, script, pc, 0);
if (atom == cx->runtime->atomState.typeAtoms[JSTYPE_VOID] &&
(pc += js_CodeSpec[op].length) < endpc) {
op = (JSOp) *pc;
return op == JSOP_EQ || op == JSOP_NE ||
op == JSOP_STRICTEQ || op == JSOP_STRICTNE;
}
return JS_FALSE;
case JSOP_GROUP:
break;
default:
/*
* At this point, anything but grouping means we're not detecting
* unless we see an extended atom index prefix.
*/
if (js_CodeSpec[op].format & JOF_ATOMBASE)
return JS_FALSE;
break;
}
/* At this point, anything but grouping means we're not detecting. */
if (op != JSOP_GROUP)
break;
}
return JS_FALSE;
}

View File

@ -110,6 +110,33 @@ GetJumpOffset(jsbytecode *pc, jsbytecode *pc2)
return GET_JUMP_OFFSET(pc2);
}
JSAtom *
js_GetAtomFromBytecode(JSContext *cx, JSScript *script, jsbytecode *pc,
ptrdiff_t pcoff)
{
JSOp op;
uintN span, atomBase;
op = (JSOp)*pc;
JS_ASSERT(js_CodeSpec[op].length >= 1 + pcoff + ATOM_INDEX_LEN);
/*
* We need to detect atom base prefix. It presents when resetbase
* follows the bytecode.
*/
span = js_CodeSpec[op].length;
atomBase = 0;
if (pc - script->code + span < script->length) {
if (pc[span] == JSOP_RESETBASE) {
atomBase = GET_ATOMBASE(pc - JSOP_ATOMBASE_LENGTH);
} else if (pc[span] == JSOP_RESETBASE0) {
JS_ASSERT(JSOP_ATOMBASE1 <= pc[-1] || pc[-1] <= JSOP_ATOMBASE3);
atomBase = (pc[-1] - JSOP_ATOMBASE1 + 1) << 16;
}
}
return GET_ATOM(cx, script->atomMap.vector + atomBase, pc + pcoff);
}
#ifdef DEBUG
JS_FRIEND_API(JSBool)
@ -169,8 +196,8 @@ ToDisassemblySource(JSContext *cx, jsval v)
}
JS_FRIEND_API(uintN)
js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
JSBool lines, FILE *fp)
js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc,
uintN loc, JSBool lines, FILE *fp)
{
JSOp op;
const JSCodeSpec *cs;
@ -212,7 +239,7 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
break;
case JOF_CONST:
atom = GET_ATOM(cx, script, pc);
atom = js_GetAtomFromBytecode(cx, script, pc, 0);
bytes = ToDisassemblySource(cx, ATOM_KEY(atom));
if (!bytes)
return 0;
@ -224,6 +251,10 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
fprintf(fp, " %u", GET_UINT16(pc));
break;
case JOF_2BYTE:
fprintf(fp, " %u", (uintN)pc[1]);
break;
case JOF_TABLESWITCH:
case JOF_TABLESWITCHX:
{
@ -260,11 +291,11 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
pc2 = pc;
off = GetJumpOffset(pc, pc2);
pc2 += jmplen;
npairs = GET_ATOM_INDEX(pc2);
pc2 += ATOM_INDEX_LEN;
npairs = GET_UINT16(pc2);
pc2 += UINT16_LEN;
fprintf(fp, " offset %d npairs %u", off, (uintN) npairs);
while (npairs) {
atom = GET_ATOM(cx, script, pc2);
atom = GET_ATOM(cx, script->atomMap.vector, pc2);
pc2 += ATOM_INDEX_LEN;
off = GetJumpOffset(pc, pc2);
pc2 += jmplen;
@ -289,8 +320,7 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
case JOF_INDEXCONST:
fprintf(fp, " %u", GET_VARNO(pc));
pc += VARNO_LEN;
atom = GET_ATOM(cx, script, pc);
atom = js_GetAtomFromBytecode(cx, script, pc, VARNO_LEN);
bytes = ToDisassemblySource(cx, ATOM_KEY(atom));
if (!bytes)
return 0;
@ -298,45 +328,10 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
break;
case JOF_UINT24:
if (op == JSOP_FINDNAME) {
/* Special case to avoid a JOF_FINDNAME just for this op. */
atom = js_GetAtom(cx, &script->atomMap, GET_UINT24(pc));
bytes = ToDisassemblySource(cx, ATOM_KEY(atom));
if (!bytes)
return 0;
fprintf(fp, " %s", bytes);
break;
}
JS_ASSERT(op == JSOP_UINT24 || op == JSOP_LITERAL);
JS_ASSERT(op == JSOP_UINT24);
fprintf(fp, " %u", GET_UINT24(pc));
break;
case JOF_LITOPX:
atom = js_GetAtom(cx, &script->atomMap, GET_LITERAL_INDEX(pc));
bytes = ToDisassemblySource(cx, ATOM_KEY(atom));
if (!bytes)
return 0;
/*
* Bytecode: JSOP_LITOPX <uint24> op [<varno> if JSOP_DEFLOCALFUN].
* Advance pc to point at op.
*/
pc += 1 + LITERAL_INDEX_LEN;
op = *pc;
cs = &js_CodeSpec[op];
fprintf(fp, " %s op %s", bytes, cs->name);
if ((cs->format & JOF_TYPEMASK) == JOF_INDEXCONST)
fprintf(fp, " %u", GET_VARNO(pc));
/*
* Adjust len to advance pc to skip op and any other immediates
* (namely, <varno> if JSOP_DEFLOCALFUN).
*/
JS_ASSERT(cs->length > ATOM_INDEX_LEN);
len += cs->length - (1 + ATOM_INDEX_LEN);
break;
default: {
char numBuf[12];
JS_snprintf(numBuf, sizeof numBuf, "%lx", (unsigned long) cs->format);
@ -1227,7 +1222,7 @@ DecompileDestructuringLHS(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc,
else if (op == JSOP_SETVAR)
atom = GetSlotAtom(jp, js_GetLocalVariable, i);
else if (op == JSOP_SETGVAR)
atom = GET_ATOM(cx, jp->script, pc);
atom = js_GetAtomFromBytecode(cx, jp->script, pc, 0);
else
lval = GetLocal(ss, i, JS_TRUE);
if (atom)
@ -1312,8 +1307,6 @@ DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc)
jsint i, lasti;
jsdouble d;
const char *lval;
jsbytecode *pc2;
jsatomid atomIndex;
JSAtom *atom;
jssrcnote *sn;
JSString *str;
@ -1353,19 +1346,8 @@ DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc)
case JSOP_UINT16: d = i = GET_UINT16(pc); goto do_getelem;
case JSOP_UINT24: d = i = GET_UINT24(pc); goto do_getelem;
/* Handle the extended literal form of JSOP_NUMBER. */
case JSOP_LITOPX:
atomIndex = GET_LITERAL_INDEX(pc);
pc2 = pc + 1 + LITERAL_INDEX_LEN;
op = *pc2;
LOCAL_ASSERT(op == JSOP_NUMBER);
goto do_getatom;
case JSOP_NUMBER:
atomIndex = GET_ATOM_INDEX(pc);
do_getatom:
atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex);
atom = js_GetAtomFromBytecode(cx, jp->script, pc, 0);
d = *ATOM_TO_DOUBLE(atom);
LOCAL_ASSERT(JSDOUBLE_IS_FINITE(d) && !JSDOUBLE_IS_NEGZERO(d));
i = (jsint)d;
@ -1379,8 +1361,7 @@ DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc)
LOCAL_ASSERT(op == JSOP_GETELEM);
/* Distinguish object from array by opcode or source note. */
if (saveop == JSOP_LITERAL ||
(sn && SN_TYPE(sn) == SRC_INITPROP)) {
if (sn && SN_TYPE(sn) == SRC_INITPROP) {
*OFF2STR(&ss->sprinter, head) = '{';
if (Sprint(&ss->sprinter, "%g: ", d) < 0)
return NULL;
@ -1396,13 +1377,9 @@ DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc)
}
break;
case JSOP_LITERAL:
atomIndex = GET_LITERAL_INDEX(pc);
goto do_getatom;
case JSOP_GETPROP:
*OFF2STR(&ss->sprinter, head) = '{';
atom = GET_ATOM(cx, jp->script, pc);
atom = js_GetAtomFromBytecode(cx, jp->script, pc, 0);
str = ATOM_TO_STRING(atom);
if (!QuoteString(&ss->sprinter, str,
js_IsIdentifier(str) ? 0 : (jschar)'\'')) {
@ -1535,7 +1512,6 @@ 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;
@ -1594,13 +1570,16 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
return NULL; \
JS_END_MACRO
#define LOAD_ATOM(PCOFF) \
(atom = js_GetAtomFromBytecode(cx, jp->script, pc, PCOFF))
/*
* 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); \
LOAD_ATOM(0); \
GET_QUOTE_AND_FMT(qfmt, ufmt, rval); \
JS_END_MACRO
@ -1632,8 +1611,21 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
* set to nop or otherwise mutated to suppress auto-parens.
*/
lastop = saveop;
op = saveop = (JSOp) *pc;
cs = &js_CodeSpec[saveop];
op = (JSOp) *pc;
cs = &js_CodeSpec[op];
if (cs->format & JOF_ATOMBASE) {
/*
* The decompiler uses js_GetAtomFromBytecode to get atoms and
* ignores these suffix/prefix bytecodes, thus simplifying code
* that must process JSOP_GETTER/JSOP_SETTER prefixes.
*/
pc += cs->length;
if (pc >= endpc)
break;
op = (JSOp) *pc;
cs = &js_CodeSpec[op];
}
saveop = op;
len = oplen = cs->length;
if (nb < 0 && -(nb + 1) == (intN)ss->top - cs->nuses + cs->ndefs)
@ -1784,10 +1776,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
switch (op) {
#define BEGIN_LITOPX_CASE(OP,PCOFF) \
case OP: \
pc2 = pc; \
atomIndex = GET_ATOM_INDEX(pc + PCOFF); \
do_##OP: \
atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex);
LOAD_ATOM(PCOFF);
#define END_LITOPX_CASE \
break;
@ -1972,7 +1961,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_PUSHOBJ:
case JSOP_BINDNAME:
do_JSOP_BINDNAME:
todo = Sprint(&ss->sprinter, "");
break;
@ -2776,7 +2764,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
goto do_fornameinloop;
case JSOP_FORNAME:
atom = GET_ATOM(cx, jp->script, pc);
LOAD_ATOM(0);
do_fornameinloop:
lval = "";
@ -2787,7 +2775,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_FORPROP:
xval = NULL;
atom = GET_ATOM(cx, jp->script, pc);
LOAD_ATOM(0);
if (!ATOM_IS_IDENTIFIER(atom)) {
xval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
(jschar)'\'');
@ -3004,10 +2992,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_SETCONST:
case JSOP_SETNAME:
case JSOP_SETGVAR:
atomIndex = GET_ATOM_INDEX(pc);
do_JSOP_SETCONST:
atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex);
LOAD_ATOM(0);
do_setname:
lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
@ -3115,7 +3100,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
break;
case JSOP_DELNAME:
atom = GET_ATOM(cx, jp->script, pc);
LOAD_ATOM(0);
lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
if (!lval)
return NULL;
@ -3176,7 +3161,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_DECNAME:
case JSOP_INCGVAR:
case JSOP_DECGVAR:
atom = GET_ATOM(cx, jp->script, pc);
LOAD_ATOM(0);
do_incatom:
lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
if (!lval)
@ -3238,7 +3223,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_NAMEDEC:
case JSOP_GVARINC:
case JSOP_GVARDEC:
atom = GET_ATOM(cx, jp->script, pc);
LOAD_ATOM(0);
do_atominc:
lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
if (!lval)
@ -3290,7 +3275,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_GETPROP:
case JSOP_GETXPROP:
atom = GET_ATOM(cx, jp->script, pc);
LOAD_ATOM(0);
do_getprop:
GET_QUOTE_AND_FMT(index_format, dot_format, rval);
@ -3342,7 +3327,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
#endif
case JSOP_SETPROP:
atom = GET_ATOM(cx, jp->script, pc);
LOAD_ATOM(0);
do_setprop:
GET_QUOTE_AND_FMT("%s[%s] %s= %s", "%s.%s %s= %s", xval);
@ -3418,7 +3403,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
break;
case JSOP_ARGSUB:
i = (jsint) GET_ATOM_INDEX(pc);
i = (jsint) GET_ARGNO(pc);
todo = Sprint(&ss->sprinter, "%s[%d]",
js_arguments_str, (int) i);
break;
@ -3448,7 +3433,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_NAME:
case JSOP_GETGVAR:
atom = GET_ATOM(cx, jp->script, pc);
LOAD_ATOM(0);
do_name:
lval = "";
do_qname:
@ -3462,7 +3447,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
break;
case JSOP_UINT16:
i = (jsint) GET_ATOM_INDEX(pc);
i = (jsint) GET_UINT16(pc);
goto do_sprint_int;
case JSOP_UINT24:
@ -3471,62 +3456,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
todo = Sprint(&ss->sprinter, "%u", (unsigned) i);
break;
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 NULL;
atom = js_GetAtom(cx, &jp->script->atomMap, atomIndex);
goto do_name;
case JSOP_LITOPX:
atomIndex = GET_LITERAL_INDEX(pc);
pc2 = pc + 1 + LITERAL_INDEX_LEN;
op = saveop = *pc2;
pc += len - (1 + ATOM_INDEX_LEN);
cs = &js_CodeSpec[op];
len = cs->length;
switch (op) {
case JSOP_ANONFUNOBJ: goto do_JSOP_ANONFUNOBJ;
case JSOP_BINDNAME: goto do_JSOP_BINDNAME;
case JSOP_CLOSURE: goto do_JSOP_CLOSURE;
#if JS_HAS_EXPORT_IMPORT
case JSOP_EXPORTNAME: goto do_JSOP_EXPORTNAME;
#endif
#if JS_HAS_XML_SUPPORT
case JSOP_GETMETHOD: goto do_JSOP_GETMETHOD;
case JSOP_SETMETHOD: goto do_JSOP_SETMETHOD;
#endif
case JSOP_NAMEDFUNOBJ: goto do_JSOP_NAMEDFUNOBJ;
case JSOP_NUMBER: goto do_JSOP_NUMBER;
case JSOP_OBJECT: goto do_JSOP_OBJECT;
#if JS_HAS_XML_SUPPORT
case JSOP_QNAMECONST: goto do_JSOP_QNAMECONST;
case JSOP_QNAMEPART: goto do_JSOP_QNAMEPART;
#endif
case JSOP_REGEXP: goto do_JSOP_REGEXP;
case JSOP_SETCONST: goto do_JSOP_SETCONST;
case JSOP_STRING: goto do_JSOP_STRING;
#if JS_HAS_XML_SUPPORT
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;
#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, 0)
val = ATOM_KEY(atom);
if (JSVAL_IS_INT(val)) {
@ -3556,13 +3485,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
case JSOP_REGEXP:
case JSOP_ANONFUNOBJ:
case JSOP_NAMEDFUNOBJ:
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);
LOAD_ATOM(0);
if (op == JSOP_OBJECT || op == JSOP_REGEXP) {
if (!js_regexp_toString(cx, ATOM_TO_OBJECT(atom), 0, NULL,
&val)) {
@ -3667,8 +3590,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
pc2 = pc;
off = GetJumpOffset(pc, pc2);
pc2 += jmplen;
npairs = GET_ATOM_INDEX(pc2);
pc2 += ATOM_INDEX_LEN;
npairs = GET_UINT16(pc2);
pc2 += UINT16_LEN;
table = (TableEntry *)
JS_malloc(cx, (size_t)npairs * sizeof *table);
@ -3684,7 +3607,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
} else {
table[k].label = NULL;
}
atom = GET_ATOM(cx, jp->script, pc2);
atom = GET_ATOM(cx, jp->script->atomMap.vector, pc2);
pc2 += ATOM_INDEX_LEN;
off2 = GetJumpOffset(pc, pc2);
pc2 += jmplen;
@ -3866,7 +3789,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
pc += len;
cs = &js_CodeSpec[op];
len = cs->length;
i = (jsint) GET_ATOM_INDEX(pc);
i = (jsint) GET_UINT16(pc);
if (Sprint(&ss->sprinter, "#%u=", (unsigned) i) < 0)
return NULL;
}
@ -3894,7 +3817,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
break;
case JSOP_INITPROP:
atom = GET_ATOM(cx, jp->script, pc);
LOAD_ATOM(0);
xval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
(jschar)
(ATOM_IS_IDENTIFIER(atom) ? 0 : '\''));
@ -3962,13 +3885,13 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
#if JS_HAS_SHARP_VARS
case JSOP_DEFSHARP:
i = (jsint) GET_ATOM_INDEX(pc);
i = (jsint) GET_UINT16(pc);
rval = POP_STR();
todo = Sprint(&ss->sprinter, "#%u=%s", (unsigned) i, rval);
break;
case JSOP_USESHARP:
i = (jsint) GET_ATOM_INDEX(pc);
i = (jsint) GET_UINT16(pc);
todo = Sprint(&ss->sprinter, "#%u#", (unsigned) i);
break;
#endif /* JS_HAS_SHARP_VARS */
@ -4677,12 +4600,9 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
*/
pcdepth = 0;
for (pc = script->main; pc < begin; pc += oplen) {
jsbytecode *pc2;
uint32 type;
intN nuses, ndefs;
/* Let pc2 be non-null only for JSOP_LITOPX. */
pc2 = NULL;
op = (JSOp) *pc;
if (op == JSOP_TRAP)
op = JS_GetTrapOpcode(cx, script, pc);
@ -4732,6 +4652,7 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
case JOF_TABLESWITCHX:
{
jsint jmplen, i, low, high;
jsbytecode *pc2;
jmplen = (type == JOF_TABLESWITCH) ? JUMP_OFFSET_LEN
: JUMPX_OFFSET_LEN;
@ -4758,7 +4679,7 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
: JUMPX_OFFSET_LEN;
pc2 = pc;
pc2 += jmplen;
npairs = GET_ATOM_INDEX(pc2);
npairs = GET_UINT16(pc2);
pc2 += ATOM_INDEX_LEN;
while (npairs) {
pc2 += ATOM_INDEX_LEN;
@ -4769,14 +4690,6 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
break;
}
case JOF_LITOPX:
pc2 = pc + 1 + LITERAL_INDEX_LEN;
op = *pc2;
cs = &js_CodeSpec[op];
JS_ASSERT(cs->length > ATOM_INDEX_LEN);
oplen += cs->length - (1 + ATOM_INDEX_LEN);
break;
default:;
}
@ -4804,13 +4717,11 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
JS_ASSERT(ndefs == 0);
ndefs = 2;
} else if (op == JSOP_ENTERBLOCK) {
jsatomid atomIndex;
JSAtom *atom;
JSObject *obj;
JS_ASSERT(ndefs == 0);
atomIndex = pc2 ? GET_LITERAL_INDEX(pc) : GET_ATOM_INDEX(pc);
atom = js_GetAtom(cx, &script->atomMap, atomIndex);
atom = js_GetAtomFromBytecode(cx, script, pc, 0);
obj = ATOM_TO_OBJECT(atom);
JS_ASSERT(OBJ_BLOCK_DEPTH(cx, obj) == pcdepth);
ndefs = OBJ_BLOCK_COUNT(cx, obj);

View File

@ -84,9 +84,8 @@ typedef enum JSOpLength {
#define JOF_TABLESWITCHX 10 /* extended (32-bit offset) table switch */
#define JOF_LOOKUPSWITCHX 11 /* extended (32-bit offset) lookup switch */
#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_2BYTE 13 /* 2-byte opcode, e.g., upper 8 bits of 24-bit
atom index */
#define JOF_LOCAL 14 /* block-local operand stack variable */
#define JOF_TYPEMASK 0x000f /* mask for above immediate types */
#define JOF_NAME 0x0010 /* name operation */
@ -109,6 +108,7 @@ typedef enum JSOpLength {
#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_ATOMBASE 0x40000 /* atom segment base setting prefix op */
#define JOF_TYPE_IS_EXTENDED_JUMP(t) \
((unsigned)((t) - JOF_JUMPX) <= (unsigned)(JOF_LOOKUPSWITCHX - JOF_JUMPX))
@ -117,11 +117,19 @@ typedef enum JSOpLength {
* Immediate operand getters, setters, and bounds.
*/
/* Common uint16 immediate format helpers. */
#define UINT16_LEN 2
#define UINT16_HI(i) ((jsbytecode)((i) >> 8))
#define UINT16_LO(i) ((jsbytecode)(i))
#define GET_UINT16(pc) ((uintN)(((pc)[1] << 8) | (pc)[2]))
#define SET_UINT16(pc,i) ((pc)[1] = UINT16_HI(i), (pc)[2] = UINT16_LO(i))
#define UINT16_LIMIT ((uintN)1 << 16)
/* Short (2-byte signed offset) relative jump macros. */
#define JUMP_OFFSET_LEN 2
#define JUMP_OFFSET_HI(off) ((jsbytecode)((off) >> 8))
#define JUMP_OFFSET_LO(off) ((jsbytecode)(off))
#define GET_JUMP_OFFSET(pc) ((int16)(((pc)[1] << 8) | (pc)[2]))
#define GET_JUMP_OFFSET(pc) ((int16)GET_UINT16(pc))
#define SET_JUMP_OFFSET(pc,off) ((pc)[1] = JUMP_OFFSET_HI(off), \
(pc)[2] = JUMP_OFFSET_LO(off))
#define JUMP_OFFSET_MIN ((int16)0x8000)
@ -138,7 +146,7 @@ typedef enum JSOpLength {
* found (via binary search) by its "before span-dependency optimization" pc
* offset (from script main entry point).
*/
#define GET_SPANDEP_INDEX(pc) ((uint16)(((pc)[1] << 8) | (pc)[2]))
#define GET_SPANDEP_INDEX(pc) ((uint16)GET_UINT16(pc))
#define SET_SPANDEP_INDEX(pc,i) ((pc)[1] = JUMP_OFFSET_HI(i), \
(pc)[2] = JUMP_OFFSET_LO(i))
#define SPANDEP_INDEX_MAX ((uint16)0xfffe)
@ -162,18 +170,20 @@ typedef enum JSOpLength {
/*
* 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.
* immediate operand index. A script with more than 64K literals must wrap the
* bytecode into JSOP_ATOMBASE and JSOP_RESETBASE pair.
*/
#define ATOM_INDEX_LEN 2
#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 GET_ATOM_INDEX(pc) GET_UINT16(pc)
#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 GET_ATOM(cx,atoms,pc) ((atoms)[GET_ATOM_INDEX(pc)])
#define GET_ATOMBASE(pc) (JS_ASSERT(*(pc) == JSOP_ATOMBASE), \
((uintN)((pc)[1])) << 16)
#define ATOMBASE_LEN 1
/* A full atom index for JSOP_UINT24 uses 24 bits of immediate operand. */
#define UINT24_HI(i) ((jsbytecode)((i) >> 16))
@ -186,14 +196,6 @@ typedef enum JSOpLength {
(pc)[2] = UINT24_MID(i), \
(pc)[3] = UINT24_LO(i))
/* Same format for JSOP_LITERAL, etc., but future-proof with different names. */
#define LITERAL_INDEX_LEN 3
#define LITERAL_INDEX_HI(i) UINT24_HI(i)
#define LITERAL_INDEX_MID(i) UINT24_MID(i)
#define LITERAL_INDEX_LO(i) UINT24_LO(i)
#define GET_LITERAL_INDEX(pc) GET_UINT24(pc)
#define SET_LITERAL_INDEX(pc,i) SET_UINT24(pc,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)
@ -201,13 +203,6 @@ typedef enum JSOpLength {
JS_STATIC_ASSERT(sizeof(jsatomid) * JS_BITS_PER_BYTE >=
ATOM_INDEX_LIMIT_LOG2 + 1);
/* Common uint16 immediate format helpers. */
#define UINT16_HI(i) ((jsbytecode)((i) >> 8))
#define UINT16_LO(i) ((jsbytecode)(i))
#define GET_UINT16(pc) ((uintN)(((pc)[1] << 8) | (pc)[2]))
#define SET_UINT16(pc,i) ((pc)[1] = UINT16_HI(i), (pc)[2] = UINT16_LO(i))
#define UINT16_LIMIT ((uintN)1 << 16)
/* Actual argument count operand format helpers. */
#define ARGC_HI(argc) UINT16_HI(argc)
#define ARGC_LO(argc) UINT16_LO(argc)
@ -267,6 +262,14 @@ js_printf(JSPrinter *jp, const char *format, ...);
extern JSBool
js_puts(JSPrinter *jp, const char *s);
/*
* A slower version of GET_ATOM when the caller does not want to maintain
* atoms table offset itself.
*/
extern JSAtom*
js_GetAtomFromBytecode(JSContext *cx, JSScript *script, jsbytecode *pc,
ptrdiff_t pcoff);
#ifdef DEBUG
/*
* Disassemblers, for debugging only.

View File

@ -407,15 +407,19 @@ OPDEF(JSOP_FOREACH, 186,"foreach", NULL, 1, 1, 1, 0, JOF_BYTE)
OPDEF(JSOP_DELDESC, 187,"deldesc", NULL, 1, 2, 1, 17, 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.
* Opcode to hold 24-bit immediate integer operands.
*/
OPDEF(JSOP_UINT24, 188,"uint24", NULL, 4, 0, 1, 16, JOF_UINT24)
OPDEF(JSOP_LITERAL, 189,"literal", NULL, 4, 0, 1, 19, JOF_UINT24)
OPDEF(JSOP_FINDNAME, 190,"findname", NULL, 4, 0, 2, 0, JOF_UINT24)
OPDEF(JSOP_LITOPX, 191,"litopx", NULL, 5, 0, 0, 0, JOF_LITOPX)
/*
* Opcodes to allow 24-bit atom indexes. Whenever an atom index exceeds the
* 16-bit limit, the atom-indexing bytecode must be bracketed by JSOP_ATOMBASE
* and JSOP_RESETBASE to provide the upper bits of the index. See jsemit.c,
* EmitAtomIndexOp.
*/
OPDEF(JSOP_ATOMBASE, 189,"atombase", NULL, 2, 0, 0, 0, JOF_2BYTE|JOF_ATOMBASE)
OPDEF(JSOP_RESETBASE, 190,"resetbase", NULL, 1, 0, 0, 0, JOF_BYTE)
OPDEF(JSOP_RESETBASE0, 191,"resetbase0", NULL, 1, 0, 0, 0, JOF_BYTE)
/*
* Opcodes to help the decompiler deal with XML.
@ -484,3 +488,11 @@ 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)
/*
* Optimize atom segments 1-3. These must be followed by JSOP_RESETBASE0 after
* the opcode that they prefix.
*/
OPDEF(JSOP_ATOMBASE1, 220,"atombase1", NULL, 1, 0, 0, 0, JOF_BYTE |JOF_ATOMBASE)
OPDEF(JSOP_ATOMBASE2, 221,"atombase2", NULL, 1, 0, 0, 0, JOF_BYTE |JOF_ATOMBASE)
OPDEF(JSOP_ATOMBASE3, 222,"atombase3", NULL, 1, 0, 0, 0, JOF_BYTE |JOF_ATOMBASE)

View File

@ -1515,12 +1515,10 @@ js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
* Special case: function definition needs no line number note because
* the function's script contains its starting line number.
*/
if (*pc == JSOP_DEFFUN ||
(*pc == JSOP_LITOPX && pc[1 + LITERAL_INDEX_LEN] == JSOP_DEFFUN)) {
atom = js_GetAtom(cx, &script->atomMap,
(*pc == JSOP_DEFFUN)
? GET_ATOM_INDEX(pc)
: GET_LITERAL_INDEX(pc));
if (js_CodeSpec[*pc].format & JOF_ATOMBASE)
pc += js_CodeSpec[*pc].length;
if (*pc == JSOP_DEFFUN) {
atom = js_GetAtomFromBytecode(cx, script, pc, 0);
fun = (JSFunction *) JS_GetPrivate(cx, ATOM_TO_OBJECT(atom));
JS_ASSERT(FUN_INTERPRETED(fun));
return fun->u.i.script->lineno;