diff --git a/js/src/js.c b/js/src/js.c index 07ab127fef2..004e0605fee 100644 --- a/js/src/js.c +++ b/js/src/js.c @@ -1277,8 +1277,7 @@ DumpAtom(JSHashEntry *he, int i, void *arg) FILE *fp = args->fp; JSAtom *atom = (JSAtom *)he; - fprintf(fp, "%3d %08x %5lu ", - i, (uintN)he->keyHash, (unsigned long)atom->number); + fprintf(fp, "%3d %08x ", i, (uintN)he->keyHash); if (ATOM_IS_STRING(atom)) fprintf(fp, "\"%s\"\n", js_AtomToPrintableString(args->cx, atom)); else if (ATOM_IS_INT(atom)) diff --git a/js/src/jsatom.c b/js/src/jsatom.c index 98438283609..def708824e0 100644 --- a/js/src/jsatom.c +++ b/js/src/jsatom.c @@ -155,10 +155,7 @@ const char js_ExecutionContext_str[] = "ExecutionContext"; const char js_current_str[] = "current"; #endif -#define HASH_OBJECT(o) (JS_PTR_TO_UINT32(o) >> JSVAL_TAGBITS) -#define HASH_INT(i) ((JSHashNumber)(i)) #define HASH_DOUBLE(dp) ((JSDOUBLE_HI32(*dp) ^ JSDOUBLE_LO32(*dp))) -#define HASH_BOOLEAN(b) ((JSHashNumber)(b)) JS_STATIC_DLL_CALLBACK(JSHashNumber) js_hash_atom_key(const void *key) @@ -166,20 +163,15 @@ js_hash_atom_key(const void *key) jsval v; jsdouble *dp; - /* Order JSVAL_IS_* tests by likelihood of success. */ v = (jsval)key; if (JSVAL_IS_STRING(v)) return js_HashString(JSVAL_TO_STRING(v)); - if (JSVAL_IS_INT(v)) - return HASH_INT(JSVAL_TO_INT(v)); if (JSVAL_IS_DOUBLE(v)) { dp = JSVAL_TO_DOUBLE(v); return HASH_DOUBLE(dp); } - if (JSVAL_IS_OBJECT(v)) - return HASH_OBJECT(JSVAL_TO_OBJECT(v)); - if (JSVAL_IS_BOOLEAN(v)) - return HASH_BOOLEAN(JSVAL_TO_BOOLEAN(v)); + JS_ASSERT(JSVAL_IS_INT(v) || v == JSVAL_TRUE || v == JSVAL_FALSE || + v == JSVAL_NULL || v == JSVAL_VOID); return (JSHashNumber)v; } @@ -228,8 +220,10 @@ js_free_table_space(void *priv, void *item) JS_STATIC_DLL_CALLBACK(JSHashEntry *) js_alloc_atom(void *priv, const void *key) { - JSAtomState *state = (JSAtomState *) priv; JSAtom *atom; +#ifdef JS_THREADSAFE + JSAtomState *state = (JSAtomState *) priv; +#endif atom = (JSAtom *) malloc(sizeof(JSAtom)); if (!atom) @@ -240,7 +234,6 @@ js_alloc_atom(void *priv, const void *key) atom->entry.key = key; atom->entry.value = NULL; atom->flags = 0; - atom->number = state->number++; return &atom->entry; } @@ -502,7 +495,7 @@ js_UnpinPinnedAtoms(JSAtomState *state) } static JSAtom * -js_AtomizeHashedKey(JSContext *cx, jsval key, JSHashNumber keyHash, uintN flags) +js_AtomizeHashedKey(JSContext *cx, jsval key, JSHashNumber keyHash) { JSAtomState *state; JSHashTable *table; @@ -523,41 +516,18 @@ js_AtomizeHashedKey(JSContext *cx, jsval key, JSHashNumber keyHash, uintN flags) } atom = (JSAtom *)he; - atom->flags |= flags; cx->weakRoots.lastAtom = atom; out: JS_UNLOCK(&state->lock,cx); return atom; } -JSAtom * -js_AtomizeBoolean(JSContext *cx, JSBool b, uintN flags) -{ - jsval key; - JSHashNumber keyHash; - - key = BOOLEAN_TO_JSVAL(b); - keyHash = HASH_BOOLEAN(b); - return js_AtomizeHashedKey(cx, key, keyHash, flags); -} - -JSAtom * -js_AtomizeInt(JSContext *cx, jsint i, uintN flags) -{ - jsval key; - JSHashNumber keyHash; - - key = INT_TO_JSVAL(i); - keyHash = HASH_INT(i); - return js_AtomizeHashedKey(cx, key, keyHash, flags); -} - /* Worst-case alignment grain and aligning macro for 2x-sized buffer. */ #define ALIGNMENT(t) JS_MAX(JSVAL_ALIGN, sizeof(t)) #define ALIGN(b,t) ((t*) &(b)[ALIGNMENT(t) - (jsuword)(b) % ALIGNMENT(t)]) JSAtom * -js_AtomizeDouble(JSContext *cx, jsdouble d, uintN flags) +js_AtomizeDouble(JSContext *cx, jsdouble d) { jsdouble *dp; JSHashNumber keyHash; @@ -602,7 +572,6 @@ js_AtomizeDouble(JSContext *cx, jsdouble d, uintN flags) } atom = (JSAtom *)he; - atom->flags |= flags; cx->weakRoots.lastAtom = atom; out: JS_UNLOCK(&state->lock,cx); @@ -760,18 +729,15 @@ js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length) } JSAtom * -js_AtomizePrimitiveValue(JSContext *cx, jsval value, uintN flags) +js_AtomizePrimitiveValue(JSContext *cx, jsval v) { - if (JSVAL_IS_STRING(value)) - return js_AtomizeString(cx, JSVAL_TO_STRING(value), flags); - if (JSVAL_IS_INT(value)) - return js_AtomizeInt(cx, JSVAL_TO_INT(value), flags); - if (JSVAL_IS_DOUBLE(value)) - return js_AtomizeDouble(cx, *JSVAL_TO_DOUBLE(value), flags); - if (JSVAL_IS_BOOLEAN(value)) - return js_AtomizeBoolean(cx, JSVAL_TO_BOOLEAN(value), flags); - JS_ASSERT(value == JSVAL_NULL || value == JSVAL_VOID); - return js_AtomizeHashedKey(cx, value, (JSHashNumber)value, flags); + if (JSVAL_IS_STRING(v)) + return js_AtomizeString(cx, JSVAL_TO_STRING(v), 0); + if (JSVAL_IS_DOUBLE(v)) + return js_AtomizeDouble(cx, *JSVAL_TO_DOUBLE(v)); + JS_ASSERT(JSVAL_IS_INT(v) || v == JSVAL_TRUE || v == JSVAL_FALSE || + v == JSVAL_NULL || v == JSVAL_VOID); + return js_AtomizeHashedKey(cx, v, (JSHashNumber)v); } JSAtom * @@ -789,7 +755,7 @@ JS_STATIC_DLL_CALLBACK(JSHashNumber) js_hash_atom_ptr(const void *key) { const JSAtom *atom = (const JSAtom *) key; - return atom->number; + return ATOM_HASH(atom); } JS_STATIC_DLL_CALLBACK(void *) @@ -870,7 +836,7 @@ js_IndexAtom(JSContext *cx, JSAtom *atom, JSAtomList *al) /* Insert each ale on al->list into the new hash table. */ for (ale2 = (JSAtomListElement *)al->list; ale2; ale2 = next) { next = ALE_NEXT(ale2); - ale2->entry.keyHash = ALE_ATOM(ale2)->number; + ale2->entry.keyHash = ATOM_HASH(ALE_ATOM(ale2)); hep = JS_HashTableRawLookup(al->table, ale2->entry.keyHash, ale2->entry.key); ale2->entry.next = *hep; @@ -879,12 +845,13 @@ js_IndexAtom(JSContext *cx, JSAtom *atom, JSAtomList *al) al->list = NULL; /* Set hep for insertion of atom's ale, immediately below. */ - hep = JS_HashTableRawLookup(al->table, atom->number, atom); + hep = JS_HashTableRawLookup(al->table, ATOM_HASH(atom), atom); } /* Finally, add an entry for atom into the hash bucket at hep. */ ale = (JSAtomListElement *) - JS_HashTableRawAdd(al->table, hep, atom->number, atom, NULL); + JS_HashTableRawAdd(al->table, hep, ATOM_HASH(atom), atom, + NULL); if (!ale) return NULL; } diff --git a/js/src/jsatom.h b/js/src/jsatom.h index 465a681b1be..306c6683337 100644 --- a/js/src/jsatom.h +++ b/js/src/jsatom.h @@ -66,7 +66,6 @@ struct JSAtom { JSHashEntry entry; /* key is jsval or unhidden atom if ATOM_HIDDEN */ uint32 flags; /* pinned, interned, and mark flags */ - jsatomid number; /* atom serial number and hash code */ }; #define ATOM_KEY(atom) ((jsval)(atom)->entry.key) @@ -79,6 +78,18 @@ struct JSAtom { #define ATOM_IS_BOOLEAN(atom) JSVAL_IS_BOOLEAN(ATOM_KEY(atom)) #define ATOM_TO_BOOLEAN(atom) JSVAL_TO_BOOLEAN(ATOM_KEY(atom)) +JS_STATIC_ASSERT(sizeof(JSHashNumber) == 4); +JS_STATIC_ASSERT(sizeof(JSAtom *) == JS_BYTES_PER_WORD); + +#if JS_BYTES_PER_WORD == 4 +# define ATOM_HASH(atom) ((JSHashNumber)(atom) >> 2) +#elif JS_BYTES_PER_WORD == 8 +# define ATOM_HASH(atom) (((JSHashNumber)(atom) >> 3) ^ \ + (JSHashNumber)((jsuword)(atom) >> 32)) +#else +# error "Unsupported configuration" +#endif + /* * Return a printable, lossless char[] representation of a string-type atom. * The lifetime of the result extends at least until the next GC activation, @@ -119,7 +130,8 @@ struct JSAtomList { #define ATOM_LIST_LOOKUP(_ale,_hep,_al,_atom) \ JS_BEGIN_MACRO \ if ((_al)->table) { \ - _hep = JS_HashTableRawLookup((_al)->table, _atom->number, _atom); \ + _hep = JS_HashTableRawLookup((_al)->table, ATOM_HASH(_atom), \ + _atom); \ _ale = *_hep ? (JSAtomListElement *) *_hep : NULL; \ } else { \ JSHashEntry **_alep = &(_al)->list; \ @@ -145,7 +157,6 @@ struct JSAtomMap { struct JSAtomState { JSRuntime *runtime; /* runtime that owns us */ JSHashTable *table; /* hash table containing all atoms */ - jsatomid number; /* one beyond greatest atom number */ jsatomid liveAtoms; /* number of live atoms after last GC */ /* The rt->emptyString atom, see jsstr.c's js_InitRuntimeStringState. */ @@ -365,29 +376,15 @@ extern void js_UnpinPinnedAtoms(JSAtomState *state); /* - * Find or create the atom for a Boolean value. If we create a new atom, give - * it the type indicated in flags. Return 0 on failure to allocate memory. + * Find or create the atom for a double value. Return null on failure to + * allocate memory. */ extern JSAtom * -js_AtomizeBoolean(JSContext *cx, JSBool b, uintN flags); +js_AtomizeDouble(JSContext *cx, jsdouble d); /* - * Find or create the atom for an integer value. If we create a new atom, give - * it the type indicated in flags. Return 0 on failure to allocate memory. - */ -extern JSAtom * -js_AtomizeInt(JSContext *cx, jsint i, uintN flags); - -/* - * Find or create the atom for a double value. If we create a new atom, give - * it the type indicated in flags. Return 0 on failure to allocate memory. - */ -extern JSAtom * -js_AtomizeDouble(JSContext *cx, jsdouble d, uintN flags); - -/* - * Find or create the atom for a string. If we create a new atom, give it the - * type indicated in flags. Return 0 on failure to allocate memory. + * Find or create the atom for a string. Return null on failure to allocate + * memory. */ extern JSAtom * js_AtomizeString(JSContext *cx, JSString *str, uintN flags); @@ -409,7 +406,7 @@ js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length); * This variant handles all primitive values. */ extern JSAtom * -js_AtomizePrimitiveValue(JSContext *cx, jsval value, uintN flags); +js_AtomizePrimitiveValue(JSContext *cx, jsval v); /* * Convert v to an atomized string. diff --git a/js/src/jsemit.c b/js/src/jsemit.c index 4ac7a65f37d..6fcd9408c5b 100644 --- a/js/src/jsemit.c +++ b/js/src/jsemit.c @@ -1527,20 +1527,29 @@ js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, jsdouble dval; jsint ival; JSAtom *valueAtom; + jsval v; JSAtomListElement *ale; /* XXX just do numbers for now */ if (pn->pn_type == TOK_NUMBER) { dval = pn->pn_dval; - valueAtom = (JSDOUBLE_IS_INT(dval, ival) && INT_FITS_IN_JSVAL(ival)) - ? js_AtomizeInt(cx, ival, 0) - : js_AtomizeDouble(cx, dval, 0); - if (!valueAtom) - return JS_FALSE; + if (JSDOUBLE_IS_INT(dval, ival) && INT_FITS_IN_JSVAL(ival)) { + v = INT_TO_JSVAL(ival); + } else { + /* + * We atomize double to root a jsdouble instance that we wrap as + * jsval and store in cg->constList. This works because atoms are + * protected from GC during compilation. + */ + valueAtom = js_AtomizeDouble(cx, dval); + if (!valueAtom) + return JS_FALSE; + v = ATOM_KEY(valueAtom); + } ale = js_IndexAtom(cx, atom, &cg->constList); if (!ale) return JS_FALSE; - ale->entry.value = (void *)ATOM_KEY(valueAtom); + ale->entry.value = (void *)v; } return JS_TRUE; } @@ -2578,7 +2587,7 @@ static JSBool EmitNumberOp(JSContext *cx, jsdouble dval, JSCodeGenerator *cg) { jsint ival; - jsatomid atomIndex; + uint32 u; ptrdiff_t off; jsbytecode *pc; JSAtom *atom; @@ -2589,33 +2598,36 @@ EmitNumberOp(JSContext *cx, jsdouble dval, JSCodeGenerator *cg) return js_Emit1(cx, cg, JSOP_ZERO) >= 0; if (ival == 1) return js_Emit1(cx, cg, JSOP_ONE) >= 0; + if ((jsint)(int8)ival == ival) + return js_Emit2(cx, cg, JSOP_INT8, (jsbytecode)(int8)ival) >= 0; - atomIndex = (jsatomid)ival; - if (atomIndex < JS_BIT(16)) { - EMIT_UINT16_IMM_OP(JSOP_UINT16, atomIndex); - return JS_TRUE; - } - - if (atomIndex < JS_BIT(24)) { + u = (uint32)ival; + if (u < JS_BIT(16)) { + EMIT_UINT16_IMM_OP(JSOP_UINT16, u); + } else if (u < JS_BIT(24)) { off = js_EmitN(cx, cg, JSOP_UINT24, 3); if (off < 0) return JS_FALSE; pc = CG_CODE(cg, off); - SET_UINT24(pc, atomIndex); - return JS_TRUE; + SET_UINT24(pc, u); + } else { + off = js_EmitN(cx, cg, JSOP_INT32, 4); + if (off < 0) + return JS_FALSE; + pc = CG_CODE(cg, off); + SET_INT32(pc, ival); } - - atom = js_AtomizeInt(cx, ival, 0); - } else { - atom = js_AtomizeDouble(cx, dval, 0); + return JS_TRUE; } + + atom = js_AtomizeDouble(cx, dval); if (!atom) return JS_FALSE; ale = js_IndexAtom(cx, atom, &cg->atomList); if (!ale) return JS_FALSE; - return EmitIndexOp(cx, JSOP_NUMBER, ALE_INDEX(ale), cg); + return EmitIndexOp(cx, JSOP_DOUBLE, ALE_INDEX(ale), cg); } static JSBool @@ -2759,7 +2771,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) { pn3->pn_val = INT_TO_JSVAL(i); } else { - atom = js_AtomizeDouble(cx, d, 0); + atom = js_AtomizeDouble(cx, d); if (!atom) { ok = JS_FALSE; goto release; @@ -3134,7 +3146,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) { if (pn3->pn_type == TOK_DEFAULT) continue; - atom = js_AtomizePrimitiveValue(cx, pn3->pn_val, 0); + atom = js_AtomizePrimitiveValue(cx, pn3->pn_val); if (!atom) goto bad; ale = js_IndexAtom(cx, atom, &cg->atomList); diff --git a/js/src/jsinterp.c b/js/src/jsinterp.c index 7d150e613a3..30fb8bde4f3 100644 --- a/js/src/jsinterp.c +++ b/js/src/jsinterp.c @@ -4126,6 +4126,18 @@ interrupt: PUSH_OPND(rval); END_CASE(JSOP_UINT24) + BEGIN_CASE(JSOP_INT8) + i = GET_INT8(pc); + rval = INT_TO_JSVAL(i); + PUSH_OPND(rval); + END_CASE(JSOP_INT8) + + BEGIN_CASE(JSOP_INT32) + i = GET_INT32(pc); + rval = INT_TO_JSVAL(i); + PUSH_OPND(rval); + END_CASE(JSOP_INT32) + BEGIN_CASE(JSOP_INDEXBASE) /* * Here atoms can exceed script->atomMap.length as we use atoms @@ -4145,11 +4157,11 @@ interrupt: atoms = script->atomMap.vector; END_CASE(JSOP_RESETBASE) - BEGIN_CASE(JSOP_NUMBER) + BEGIN_CASE(JSOP_DOUBLE) BEGIN_CASE(JSOP_STRING) LOAD_ATOM(0); PUSH_OPND(ATOM_KEY(atom)); - END_CASE(JSOP_NUMBER) + END_CASE(JSOP_DOUBLE) BEGIN_CASE(JSOP_OBJECT) LOAD_OBJECT(0); diff --git a/js/src/jsopcode.c b/js/src/jsopcode.c index 12ade451e5a..cf076ff2f2c 100644 --- a/js/src/jsopcode.c +++ b/js/src/jsopcode.c @@ -219,6 +219,7 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, JSObject *obj; jsval v; const char *bytes; + jsint i; op = (JSOp)*pc; if (op >= JSOP_LIMIT) { @@ -274,8 +275,8 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, case JOF_UINT16: case JOF_LOCAL: - fprintf(fp, " %u", GET_UINT16(pc)); - break; + i = (jsint)GET_UINT16(pc); + goto print_int; case JOF_2BYTE: fprintf(fp, " %u", (uintN)pc[1]); @@ -363,7 +364,19 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, case JOF_UINT24: JS_ASSERT(op == JSOP_UINT24); - fprintf(fp, " %u", GET_UINT24(pc)); + i = (jsint)GET_UINT24(pc); + goto print_int; + + case JOF_INT8: + JS_ASSERT(op == JSOP_INT8); + i = GET_INT8(pc); + goto print_int; + + case JOF_INT32: + JS_ASSERT(op == JSOP_INT32); + i = GET_INT32(pc); + print_int: + fprintf(fp, " %d", i); break; default: { @@ -1475,8 +1488,10 @@ DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc) case JSOP_ONE: d = i = 1; goto do_getelem; case JSOP_UINT16: d = i = GET_UINT16(pc); goto do_getelem; case JSOP_UINT24: d = i = GET_UINT24(pc); goto do_getelem; + case JSOP_INT8: d = i = GET_INT8(pc); goto do_getelem; + case JSOP_INT32: d = i = GET_INT32(pc); goto do_getelem; - case JSOP_NUMBER: + case JSOP_DOUBLE: GET_ATOM_FROM_BYTECODE(jp->script, pc, 0, atom); d = *ATOM_TO_DOUBLE(atom); LOCAL_ASSERT(JSDOUBLE_IS_FINITE(d) && !JSDOUBLE_IS_NEGZERO(d)); @@ -3772,15 +3787,22 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) case JSOP_UINT24: i = (jsint) GET_UINT24(pc); + goto do_sprint_int; + + case JSOP_INT8: + i = GET_INT8(pc); + goto do_sprint_int; + + case JSOP_INT32: + i = GET_INT32(pc); do_sprint_int: - todo = Sprint(&ss->sprinter, "%u", (unsigned) i); + todo = Sprint(&ss->sprinter, "%d", i); break; - BEGIN_LITOPX_CASE(JSOP_NUMBER, 0) + BEGIN_LITOPX_CASE(JSOP_DOUBLE, 0) val = ATOM_KEY(atom); - todo = JSVAL_IS_INT(val) - ? Sprint(&ss->sprinter, "%ld", (long) JSVAL_TO_INT(val)) - : SprintDoubleValue(&ss->sprinter, val, &saveop); + JS_ASSERT(JSVAL_IS_DOUBLE(val)); + todo = SprintDoubleValue(&ss->sprinter, val, &saveop); END_LITOPX_CASE BEGIN_LITOPX_CASE(JSOP_STRING, 0) diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h index db0f0a59839..f47c465a709 100644 --- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -90,7 +90,10 @@ typedef enum JSOpLength { #define JOF_OBJECT 15 /* unsigned 16-bit object pool index */ #define JOF_INDEXOBJECT 16 /* uint16 slot index + object pool index */ #define JOF_REGEXP 17 /* unsigned 16-bit regexp pool index */ +#define JOF_INT8 18 /* int8 immediate operand */ +#define JOF_INT32 19 /* int32 immediate operand */ #define JOF_TYPEMASK 0x001f /* mask for above immediate types */ + #define JOF_NAME (1U<<5) /* name operation */ #define JOF_PROP (2U<<5) /* obj.prop operation */ #define JOF_ELEM (3U<<5) /* obj[index] operation */ @@ -209,6 +212,17 @@ typedef enum JSOpLength { (pc)[2] = UINT24_MID(i), \ (pc)[3] = UINT24_LO(i)) +#define GET_INT8(pc) ((jsint)(int8)(pc)[1]) + +#define GET_INT32(pc) ((jsint)(((uint32)((pc)[1]) << 24) | \ + ((uint32)((pc)[2]) << 16) | \ + ((uint32)((pc)[3]) << 8) | \ + (uint32)(pc)[4])) +#define SET_INT32(pc,i) ((pc)[1] = (jsbytecode)((uint32)(i) >> 24), \ + (pc)[2] = (jsbytecode)((uint32)(i) >> 16), \ + (pc)[3] = (jsbytecode)((uint32)(i) >> 8), \ + (pc)[4] = (jsbytecode)(uint32)(i)) + /* Index limit is determined by SN_3BYTE_OFFSET_FLAG, see jsemit.h. */ #define INDEX_LIMIT_LOG2 23 #define INDEX_LIMIT ((uint32)1 << INDEX_LIMIT_LOG2) diff --git a/js/src/jsopcode.tbl b/js/src/jsopcode.tbl index 3918b40ebb9..8bd4f3321eb 100644 --- a/js/src/jsopcode.tbl +++ b/js/src/jsopcode.tbl @@ -79,12 +79,12 @@ * 13 +, -, etc. JSOP_ADD, JSOP_SUB, etc. * 14 *, /, % JSOP_MUL, JSOP_DIV, JSOP_MOD * 15 !, ~, etc. JSOP_NOT, JSOP_BITNOT, etc. - * 16 3.14, 0, etc. JSOP_NUMBER, JSOP_ZERO, etc. + * 16 3.14, 0, etc. JSOP_DOUBLE, JSOP_ZERO, etc. * 17 delete, new JSOP_DEL*, JSOP_NEW * 18 x.y, f(), etc. JSOP_GETPROP, JSOP_CALL, etc. * 19 x, null, etc. JSOP_NAME, JSOP_NULL, etc. * - * The push-numeric-constant operators, JSOP_ZERO, JSOP_NUMBER, etc., have + * The push-numeric-constant operators, JSOP_ZERO, JSOP_DOUBLE, etc., have * lower precedence than the member operators emitted for the . operator, to * cause the decompiler to parenthesize the . left operand, e.g. (0).foo. * Otherwise the . could be taken as a decimal point. We use the same level @@ -163,7 +163,7 @@ OPDEF(JSOP_SETELEM, 56, "setelem", NULL, 1, 3, 1, 3, JOF_BYTE | OPDEF(JSOP_CALLNAME, 57, "callname", NULL, 3, 0, 2, 19, JOF_CONST|JOF_NAME|JOF_CALLOP) OPDEF(JSOP_CALL, 58, "call", NULL, 3, -1, 1, 18, JOF_UINT16|JOF_INVOKE) OPDEF(JSOP_NAME, 59, "name", NULL, 3, 0, 1, 19, JOF_CONST|JOF_NAME) -OPDEF(JSOP_NUMBER, 60, "number", NULL, 3, 0, 1, 16, JOF_CONST) +OPDEF(JSOP_DOUBLE, 60, "double", NULL, 3, 0, 1, 16, JOF_CONST) OPDEF(JSOP_STRING, 61, "string", NULL, 3, 0, 1, 19, JOF_CONST) OPDEF(JSOP_ZERO, 62, "zero", "0", 1, 0, 1, 16, JOF_BYTE) OPDEF(JSOP_ONE, 63, "one", "1", 1, 0, 1, 16, JOF_BYTE) @@ -503,3 +503,9 @@ OPDEF(JSOP_CALLGVAR, 223, "callgvar", NULL, 3, 0, 2, 19, JOF_CONST| OPDEF(JSOP_CALLVAR, 224, "callvar", NULL, 3, 0, 2, 19, JOF_QVAR |JOF_NAME|JOF_CALLOP) OPDEF(JSOP_CALLARG, 225, "callarg", NULL, 3, 0, 2, 19, JOF_QARG |JOF_NAME|JOF_CALLOP) OPDEF(JSOP_CALLLOCAL, 226, "calllocal", NULL, 3, 0, 2, 19, JOF_LOCAL|JOF_NAME|JOF_CALLOP) + +/* + * Opcodes to hold 8-bit and 32-bit immediate integer operands. + */ +OPDEF(JSOP_INT8, 227, "int8", NULL, 2, 0, 1, 16, JOF_INT8) +OPDEF(JSOP_INT32, 228, "int32", NULL, 5, 0, 1, 16, JOF_INT32) diff --git a/js/src/jsparse.c b/js/src/jsparse.c index 19c7dd53040..44d6899aa22 100644 --- a/js/src/jsparse.c +++ b/js/src/jsparse.c @@ -2088,7 +2088,7 @@ HashFindPropValKey(JSDHashTable *table, const void *key) return (pnkey->pn_type == TOK_NUMBER) ? (JSDHashNumber) (JSDOUBLE_HI32(pnkey->pn_dval) ^ JSDOUBLE_LO32(pnkey->pn_dval)) - : (JSDHashNumber) pnkey->pn_atom->number; + : ATOM_HASH(pnkey->pn_atom); } JS_STATIC_DLL_CALLBACK(JSBool) @@ -6100,7 +6100,7 @@ FoldType(JSContext *cx, JSParseNode *pn, JSTokenType type) return JS_FALSE; pn->pn_dval = d; pn->pn_type = TOK_NUMBER; - pn->pn_op = JSOP_NUMBER; + pn->pn_op = JSOP_DOUBLE; } break; @@ -6211,7 +6211,7 @@ FoldBinaryNumeric(JSContext *cx, JSOp op, JSParseNode *pn1, JSParseNode *pn2, if (pn2 != pn) RecycleTree(pn2, tc); pn->pn_type = TOK_NUMBER; - pn->pn_op = JSOP_NUMBER; + pn->pn_op = JSOP_DOUBLE; pn->pn_arity = PN_NULLARY; pn->pn_dval = d; return JS_TRUE; @@ -6795,7 +6795,7 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc) return JS_TRUE; } pn->pn_type = TOK_NUMBER; - pn->pn_op = JSOP_NUMBER; + pn->pn_op = JSOP_DOUBLE; pn->pn_arity = PN_NULLARY; pn->pn_dval = d; RecycleTree(pn1, tc); diff --git a/js/src/jsscope.c b/js/src/jsscope.c index 772af6cb17b..30908854d2d 100644 --- a/js/src/jsscope.c +++ b/js/src/jsscope.c @@ -229,13 +229,22 @@ JS_FRIEND_DATA(JSScopeStats) js_scope_stats; # define METER(x) /* nothing */ #endif +JS_STATIC_ASSERT(sizeof(JSHashNumber) == 4); +JS_STATIC_ASSERT(sizeof(jsid) == JS_BYTES_PER_WORD); + +#if JS_BYTES_PER_WORD == 4 +# define HASH_ID(id) ((JSHashNumber)(id)) +#elif JS_BYTES_PER_WORD == 8 +# define HASH_ID(id) ((JSHashNumber)(id) ^ (JSHashNumber)((id) >> 32)) +#else +# error "Unsupported configuration" +#endif + /* * Double hashing needs the second hash code to be relatively prime to table * size, so we simply make hash2 odd. The inputs to multiplicative hash are - * the golden ratio, expressed as a fixed-point 32 bit fraction, and the int - * property index or named property's atom number (observe that most objects - * have either no indexed properties, or almost all indexed and a few names, - * so collisions between index and atom number are unlikely). + * the golden ratio, expressed as a fixed-point 32 bit fraction, and the id + * itself. */ #define SCOPE_HASH0(id) (HASH_ID(id) * JS_GOLDEN_RATIO) #define SCOPE_HASH1(hash0,shift) ((hash0) >> (shift)) diff --git a/js/src/jsscope.h b/js/src/jsscope.h index 6fedaa83193..20b917309db 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -351,9 +351,6 @@ js_DestroyScope(JSContext *cx, JSScope *scope); #define ID_TO_VALUE(id) (JSID_IS_ATOM(id) ? ATOM_JSID_TO_JSVAL(id) : \ JSID_IS_OBJECT(id) ? OBJECT_JSID_TO_JSVAL(id) : \ (jsval)(id)) -#define HASH_ID(id) (JSID_IS_ATOM(id) ? JSID_TO_ATOM(id)->number : \ - JSID_IS_OBJECT(id) ? (jsatomid) JSID_CLRTAG(id) : \ - (jsatomid) JSID_TO_INT(id)) extern JS_FRIEND_API(JSScopeProperty **) js_SearchScope(JSScope *scope, jsid id, JSBool adding); diff --git a/js/src/jsxdrapi.c b/js/src/jsxdrapi.c index 39ed113ce8d..c5c3038227b 100644 --- a/js/src/jsxdrapi.c +++ b/js/src/jsxdrapi.c @@ -630,11 +630,11 @@ js_XDRAtom(JSXDRState *xdr, JSAtom **atomp) if (type == JSVAL_DOUBLE) { if (!XDRDoubleValue(xdr, &d)) return JS_FALSE; - atom = js_AtomizeDouble(xdr->cx, d, 0); + atom = js_AtomizeDouble(xdr->cx, d); } else { if (!XDRValueBody(xdr, type, &v)) return JS_FALSE; - atom = js_AtomizePrimitiveValue(xdr->cx, v, 0); + atom = js_AtomizePrimitiveValue(xdr->cx, v); } if (!atom) diff --git a/js/src/jsxdrapi.h b/js/src/jsxdrapi.h index 83f5a7df8e6..cf0e6c5e0bf 100644 --- a/js/src/jsxdrapi.h +++ b/js/src/jsxdrapi.h @@ -201,7 +201,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id); * before deserialization of bytecode. If the saved version does not match * the current version, abort deserialization and invalidate the file. */ -#define JSXDR_BYTECODE_VERSION (0xb973c0de - 13) +#define JSXDR_BYTECODE_VERSION (0xb973c0de - 14) /* * Library-private functions.