diff --git a/js/src/js.c b/js/src/js.c index 120672d0c14d..a0b71d9fab37 100644 --- a/js/src/js.c +++ b/js/src/js.c @@ -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; } diff --git a/js/src/jsemit.c b/js/src/jsemit.c index 576bfba78d3b..62d5ae90fa4f 100644 --- a/js/src/jsemit.c +++ b/js/src/jsemit.c @@ -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; } diff --git a/js/src/jsinterp.c b/js/src/jsinterp.c index 189315cf7d4c..889799bdf47b 100644 --- a/js/src/jsinterp.c +++ b/js/src/jsinterp.c @@ -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) diff --git a/js/src/jsobj.c b/js/src/jsobj.c index 0a74023802ba..28c42b3c7d0a 100644 --- a/js/src/jsobj.c +++ b/js/src/jsobj.c @@ -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; } diff --git a/js/src/jsopcode.c b/js/src/jsopcode.c index 089b79242cac..7755acc4513b 100644 --- a/js/src/jsopcode.c +++ b/js/src/jsopcode.c @@ -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 op [ 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, 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); diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h index 3675b92fdc2b..f2c4dacfda86 100644 --- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -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. diff --git a/js/src/jsopcode.tbl b/js/src/jsopcode.tbl index ea83cf58e94d..6a07bec29241 100644 --- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -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) diff --git a/js/src/jsscript.c b/js/src/jsscript.c index d53c247021d0..2b5cb294d758 100644 --- a/js/src/jsscript.c +++ b/js/src/jsscript.c @@ -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;