From 8f6c06b1485db5d755b0a659e2d78b4fe07883b2 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Wed, 2 Jun 2010 19:09:04 -0700 Subject: [PATCH] Remove jsboxedword, change jsid to be a jsval --- js/src/jsapi.cpp | 64 +++---- js/src/jsapi.h | 10 +- js/src/jsarray.cpp | 38 ++--- js/src/jsarray.h | 4 +- js/src/jsatom.cpp | 192 ++------------------- js/src/jsatom.h | 24 +-- js/src/jsatominlines.h | 17 +- js/src/jscntxt.cpp | 2 +- js/src/jscntxt.h | 46 +----- js/src/jscntxtinlines.h | 18 +- js/src/jsdbgapi.cpp | 16 +- js/src/jsemit.cpp | 162 +++++++----------- js/src/jsemit.h | 14 +- js/src/jsexn.cpp | 3 +- js/src/jsfun.cpp | 36 ++-- js/src/jsfun.h | 2 + js/src/jsgc.cpp | 284 ++----------------------------- js/src/jsgc.h | 76 ++++----- js/src/jsinterp.cpp | 84 ++-------- js/src/jsinterp.h | 9 - js/src/jsiter.cpp | 93 ++++------- js/src/jsiter.h | 6 +- js/src/jsobj.cpp | 30 ++-- js/src/jsobj.h | 2 + js/src/json.cpp | 10 +- js/src/jsopcode.cpp | 30 ++-- js/src/jsopcode.h | 7 +- js/src/jsops.cpp | 54 +++--- js/src/jsparse.cpp | 31 ++-- js/src/jsparse.h | 4 +- js/src/jspropertytree.cpp | 18 +- js/src/jsprvtd.h | 24 +++ js/src/jspubtd.h | 340 ++------------------------------------ js/src/jsregexp.cpp | 10 +- js/src/jsscope.cpp | 35 ++-- js/src/jsscope.h | 24 +-- js/src/jsscopeinlines.h | 6 +- js/src/jsscript.cpp | 48 ++++-- js/src/jsscript.h | 20 ++- js/src/jsstr.cpp | 2 +- js/src/jsstr.h | 2 + js/src/jstracer.cpp | 2 +- js/src/jstypedarray.cpp | 8 +- js/src/jsxdrapi.cpp | 30 +--- js/src/jsxml.cpp | 106 +++++------- js/src/jsxml.h | 2 +- js/src/shell/js.cpp | 26 +-- 47 files changed, 549 insertions(+), 1522 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index e7dde193a4e..bf7355d0639 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1332,7 +1332,7 @@ static JSStdName object_prototype_names[] = { }; JS_PUBLIC_API(JSBool) -JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsid id, +JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id, JSBool *resolved) { JSString *idstr; @@ -1976,7 +1976,7 @@ JS_PrintTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, } else if (FUN_OBJECT(fun) != obj) { JS_snprintf(buf, bufsize, "%p", fun); } else { - if (fun->atom && ATOM_IS_STRING(fun->atom)) + if (fun->atom) js_PutEscapedString(buf, bufsize, ATOM_TO_STRING(fun->atom), 0); } @@ -2533,12 +2533,6 @@ JS_DestroyIdArray(JSContext *cx, JSIdArray *ida) cx->free(ida->self); } -JS_PUBLIC_API(jsval) -JSID_TO_JSVAL(jsid id) -{ - return Jsvalify(IdToValue(id)); -} - JS_PUBLIC_API(JSBool) JS_ValueToId(JSContext *cx, jsval v, jsid *idp) { @@ -2550,11 +2544,11 @@ JS_PUBLIC_API(void) JS_IdToValue(JSContext *cx, jsid id, jsval *vp) { CHECK_REQUEST(cx); - *vp = Jsvalify(IdToValue(id)); + *vp = ID_TO_JSVAL(id); } JS_PUBLIC_API(JSBool) -JS_PropertyStub(JSContext *cx, JSObject *obj, jsid id, jsval *vp) +JS_PropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { return JS_TRUE; } @@ -2566,7 +2560,7 @@ JS_EnumerateStub(JSContext *cx, JSObject *obj) } JS_PUBLIC_API(JSBool) -JS_ResolveStub(JSContext *cx, JSObject *obj, jsid id) +JS_ResolveStub(JSContext *cx, JSObject *obj, jsval id) { return JS_TRUE; } @@ -3041,8 +3035,8 @@ JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name, } static JSBool -LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop, - Value *vp) +LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, jsid id, + JSProperty *prop, Value *vp) { if (!prop) { /* XXX bad API: no way to tell "not defined" from "void value" */ @@ -3067,7 +3061,7 @@ LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop, else vp->setBoolean(true); } else if (obj2->isDenseArray()) { - ok = js_GetDenseArrayElementValue(cx, obj2, prop, vp); + ok = js_GetDenseArrayElementValue(cx, obj2, id, vp); } else { /* XXX bad API: no way to return "defined but value unknown" */ vp->setBoolean(true); @@ -3317,14 +3311,11 @@ JS_HasPropertyById(JSContext *cx, JSObject *obj, jsid id, JSBool *foundp) JS_PUBLIC_API(JSBool) JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp) { - JSObject *obj2; - JSProperty *prop; - - CHECK_REQUEST(cx); - return LookupProperty(cx, obj, name, JSRESOLVE_QUALIFIED, &obj2, &prop) && - LookupResult(cx, obj, obj2, prop, Valueify(vp)); + JSAtom *atom = js_Atomize(cx, name, strlen(name), 0); + return atom && JS_LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), vp); } + JS_PUBLIC_API(JSBool) JS_LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp) { @@ -3333,7 +3324,7 @@ JS_LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp) CHECK_REQUEST(cx); return LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop) && - LookupResult(cx, obj, obj2, prop, Valueify(vp)); + LookupResult(cx, obj, obj2, id, prop, Valueify(vp)); } JS_PUBLIC_API(JSBool) @@ -3361,7 +3352,7 @@ JS_LookupPropertyWithFlagsById(JSContext *cx, JSObject *obj, jsid id, ? js_LookupPropertyWithFlags(cx, obj, id, flags, objp, &prop) >= 0 : obj->lookupProperty(cx, id, objp, &prop); if (ok) - ok = LookupResult(cx, obj, *objp, prop, Valueify(vp)); + ok = LookupResult(cx, obj, *objp, id, prop, Valueify(vp)); return ok; } @@ -3584,19 +3575,13 @@ JS_HasUCProperty(JSContext *cx, JSObject *obj, } JS_PUBLIC_API(JSBool) -JS_LookupUCProperty(JSContext *cx, JSObject *obj, - const jschar *name, size_t namelen, - jsval *vp) +JS_LookupUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, jsval *vp) { - JSObject *obj2; - JSProperty *prop; - - CHECK_REQUEST(cx); - return LookupUCProperty(cx, obj, name, namelen, JSRESOLVE_QUALIFIED, - &obj2, &prop) && - LookupResult(cx, obj, obj2, prop, Valueify(vp)); + JSAtom *atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0); + return atom && JS_LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), vp); } + JS_PUBLIC_API(JSBool) JS_GetUCProperty(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, @@ -3753,15 +3738,10 @@ JS_HasElement(JSContext *cx, JSObject *obj, jsint index, JSBool *foundp) JS_PUBLIC_API(JSBool) JS_LookupElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp) { - JSObject *obj2; - JSProperty *prop; - - CHECK_REQUEST(cx); - return LookupPropertyById(cx, obj, INT_TO_JSID(index), JSRESOLVE_QUALIFIED, - &obj2, &prop) && - LookupResult(cx, obj, obj2, prop, Valueify(vp)); + return JS_LookupPropertyById(cx, obj, INT_TO_JSID(index), vp); } + JS_PUBLIC_API(JSBool) JS_GetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp) { @@ -3864,7 +3844,7 @@ prop_iter_trace(JSTracer *trc, JSObject *obj) } else { /* Non-native case: mark each id in the JSIdArray private. */ JSIdArray *ida = (JSIdArray *) pdata; - MarkBoxedWordRange(trc, ida->length, ida->vector, "prop iter"); + MarkIdRange(trc, ida->length, ida->vector, "prop iter"); } } @@ -3945,7 +3925,7 @@ JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp) sprop = sprop->parent; if (!sprop) { - *idp = JSBOXEDWORD_VOID; + *idp = JSVAL_VOID; } else { iterobj->setPrivate(sprop->parent); *idp = sprop->id; @@ -3955,7 +3935,7 @@ JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp) ida = (JSIdArray *) iterobj->getPrivate(); JS_ASSERT(i <= ida->length); if (i == 0) { - *idp = JSBOXEDWORD_VOID; + *idp = JSVAL_VOID; } else { *idp = ida->vector[--i]; iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Tag(i)); diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 1e15b6a7998..2c2e9003457 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -778,7 +778,7 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj); * loops any classes not yet resolved lazily. */ extern JS_PUBLIC_API(JSBool) -JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsid id, +JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id, JSBool *resolved); extern JS_PUBLIC_API(JSBool) @@ -977,7 +977,7 @@ JS_ClearNewbornRoots(JSContext *cx); * associated with cx. For example: * * JSBool - * my_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) + * my_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) * { * JSBool ok; * @@ -1585,7 +1585,7 @@ JS_IdToValue(JSContext *cx, jsid id, jsval *vp); * Global object classes in embeddings that enable JS_HAS_XML_SUPPORT (E4X) * should handle this id specially before converting id via JSVAL_TO_INT. */ -#define JS_DEFAULT_XML_NAMESPACE_ID ((jsid) JSBOXEDWORD_VOID) +#define JS_DEFAULT_XML_NAMESPACE_ID ((jsid) JSVAL_VOID) /* * JSNewResolveOp flag bits. @@ -1598,13 +1598,13 @@ JS_IdToValue(JSContext *cx, jsid id, jsval *vp); #define JSRESOLVE_WITH 0x20 /* resolve inside a with statement */ extern JS_PUBLIC_API(JSBool) -JS_PropertyStub(JSContext *cx, JSObject *obj, jsid id, jsval *vp); +JS_PropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp); extern JS_PUBLIC_API(JSBool) JS_EnumerateStub(JSContext *cx, JSObject *obj); extern JS_PUBLIC_API(JSBool) -JS_ResolveStub(JSContext *cx, JSObject *obj, jsid id); +JS_ResolveStub(JSContext *cx, JSObject *obj, jsval id); extern JS_PUBLIC_API(JSBool) JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp); diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 96ef717cdbc..5236ac7dd39 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -160,22 +160,22 @@ INDEX_TOO_BIG(jsuint index) * an atomized string. */ JSBool -js_IdIsIndex(jsboxedword idw, jsuint *indexp) +js_IdIsIndex(jsid id, jsuint *indexp) { - if (JSBOXEDWORD_IS_INT(idw)) { + if (JSID_IS_INT(id)) { jsint i; - i = JSBOXEDWORD_TO_INT(idw); + i = JSID_TO_INT(id); if (i < 0) return JS_FALSE; *indexp = (jsuint)i; return JS_TRUE; } - /* NB: idw should be a string, but jsxml.c may call us with an object idw. */ - if (!JSBOXEDWORD_IS_STRING(idw)) + /* NB: id should be a string, but jsxml.c may call us with an object id. */ + if (!JSID_IS_ATOM(id)) return JS_FALSE; - JSString *str = JSBOXEDWORD_TO_STRING(idw); + JSString *str = JSID_TO_STRING(id); jschar *cp = str->chars(); if (JS7_ISDEC(*cp) && str->length() < sizeof(MAXSTR)) { jsuint index = JS7_UNDEC(*cp++); @@ -272,7 +272,7 @@ js_IndexToId(JSContext *cx, jsuint index, jsid *idp) { JSString *str; - if (index <= JSBOXEDWORD_INT_MAX) { + if (index <= JSVAL_INT_MAX) { *idp = INT_TO_JSID(index); return JS_TRUE; } @@ -291,7 +291,7 @@ BigIndexToId(JSContext *cx, JSObject *obj, jsuint index, JSBool createAtom, JSAtom *atom; JS_STATIC_ASSERT((jsuint)-1 == 4294967295U); - JS_ASSERT(index > JSBOXEDWORD_INT_MAX); + JS_ASSERT(index > JSVAL_INT_MAX); start = JS_ARRAY_END(buf); do { @@ -314,7 +314,7 @@ BigIndexToId(JSContext *cx, JSObject *obj, jsuint index, JSBool createAtom, clasp == &js_ObjectClass)) { atom = js_GetExistingStringAtom(cx, start, JS_ARRAY_END(buf) - start); if (!atom) { - *idp = JSBOXEDWORD_VOID; + *idp = JSVAL_VOID; return JS_TRUE; } } else { @@ -425,7 +425,7 @@ static bool IndexToId(JSContext* cx, JSObject* obj, jsdouble index, JSBool* hole, jsid* idp, JSBool createAtom = JS_FALSE) { - if (index <= JSBOXEDWORD_INT_MAX) { + if (index <= JSVAL_INT_MAX) { *idp = INT_TO_JSID(int(index)); return JS_TRUE; } @@ -433,7 +433,7 @@ IndexToId(JSContext* cx, JSObject* obj, jsdouble index, JSBool* hole, jsid* idp, if (index <= jsuint(-1)) { if (!BigIndexToId(cx, obj, jsuint(index), createAtom, idp)) return JS_FALSE; - if (hole && JSBOXEDWORD_IS_VOID(*idp)) + if (hole && JSVAL_IS_VOID(*idp)) *hole = JS_TRUE; return JS_TRUE; } @@ -517,7 +517,7 @@ SetArrayElement(JSContext *cx, JSObject *obj, jsdouble index, const Value &v) if (!IndexToId(cx, obj, index, NULL, idr.addr(), JS_TRUE)) return JS_FALSE; - JS_ASSERT(!JSBOXEDWORD_IS_VOID(idr.id())); + JS_ASSERT(!JSVAL_IS_VOID(idr.id())); Value tmp = v; return obj->setProperty(cx, idr.id(), &tmp); @@ -544,7 +544,7 @@ DeleteArrayElement(JSContext *cx, JSObject *obj, jsdouble index) if (!IndexToId(cx, obj, index, NULL, idr.addr())) return JS_FALSE; - if (JSBOXEDWORD_IS_VOID(idr.id())) + if (JSVAL_IS_VOID(idr.id())) return JS_TRUE; Value junk; @@ -690,7 +690,7 @@ array_length_setter(JSContext *cx, JSObject *obj, jsid id, Value *vp) for (;;) { if (!JS_CHECK_OPERATION_LIMIT(cx) || !JS_NextProperty(cx, iter, &id)) return false; - if (JSBOXEDWORD_IS_VOID(id)) + if (JSVAL_IS_VOID(id)) break; if (js_IdIsIndex(id, &index) && index - newlen < gap && !obj->deleteProperty(cx, id, &junk)) { @@ -728,7 +728,7 @@ array_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, return js_LookupProperty(cx, obj, id, objp, propp); if (IsDenseArrayId(cx, obj, id)) { - *propp = (JSProperty *) id; + *propp = (JSProperty *) 1; /* non-null to indicate found */ *objp = obj; return JS_TRUE; } @@ -745,15 +745,13 @@ array_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, static void array_dropProperty(JSContext *cx, JSObject *obj, JSProperty *prop) { - JS_ASSERT(IsDenseArrayId(cx, obj, (jsid) prop)); + JS_ASSERT(obj->isDenseArray()); } JSBool -js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, JSProperty *prop, - Value *vp) +js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - jsid id = (jsid) prop; - JS_ASSERT(IsDenseArrayId(cx, obj, id)); + JS_ASSERT(obj->isDenseArray()); uint32 i; if (!js_IdIsIndex(id, &i)) { diff --git a/js/src/jsarray.h b/js/src/jsarray.h index efd093095e4..954d7ca0320 100644 --- a/js/src/jsarray.h +++ b/js/src/jsarray.h @@ -49,7 +49,7 @@ #define ARRAY_CAPACITY_MIN 7 extern JSBool -js_IdIsIndex(jsboxedword idw, jsuint *indexp); +js_IdIsIndex(jsid id, jsuint *indexp); extern js::Class js_ArrayClass, js_SlowArrayClass; @@ -201,7 +201,7 @@ js_PrototypeHasIndexedProperties(JSContext *cx, JSObject *obj); * Utility to access the value from the id returned by array_lookupProperty. */ JSBool -js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, JSProperty *prop, +js_GetDenseArrayElementValue(JSContext *cx, JSObject *obj, jsid id, js::Value *vp); /* Array constructor native. Exposed only so the JIT can know its address. */ diff --git a/js/src/jsatom.cpp b/js/src/jsatom.cpp index 7770ccfb1a4..ab83eb6bc6e 100644 --- a/js/src/jsatom.cpp +++ b/js/src/jsatom.cpp @@ -269,25 +269,25 @@ const char js_current_str[] = "current"; #endif /* - * JSAtomState.doubleAtoms and JSAtomState.stringAtoms hashtable entry. To - * support pinned and interned string atoms, we use the lowest bits of the - * keyAndFlags field to store ATOM_PINNED and ATOM_INTERNED flags. + * JSAtomState.stringAtoms hashtable entry. To support pinned and interned + * string atoms, we use the lowest bits of the keyAndFlags field to store + * ATOM_PINNED and ATOM_INTERNED flags. */ typedef struct JSAtomHashEntry { JSDHashEntryHdr hdr; - jsboxedword keyAndFlags; + jsuword keyAndFlags; } JSAtomHashEntry; #define ATOM_ENTRY_FLAG_MASK (ATOM_PINNED | ATOM_INTERNED) -JS_STATIC_ASSERT(ATOM_ENTRY_FLAG_MASK < JSBOXEDWORD_ALIGN); +JS_STATIC_ASSERT(ATOM_ENTRY_FLAG_MASK < JS_GCTHING_ALIGN); /* * Helper macros to access and modify JSAtomHashEntry. */ #define TO_ATOM_ENTRY(hdr) ((JSAtomHashEntry *) hdr) #define ATOM_ENTRY_KEY(entry) \ - ((void *)((entry)->keyAndFlags & ~ATOM_ENTRY_FLAG_MASK)) + ((JSString *)((entry)->keyAndFlags & ~ATOM_ENTRY_FLAG_MASK)) #define ATOM_ENTRY_FLAGS(entry) \ ((uintN)((entry)->keyAndFlags & ATOM_ENTRY_FLAG_MASK)) #define INIT_ATOM_ENTRY(entry, key) \ @@ -297,29 +297,12 @@ JS_STATIC_ASSERT(ATOM_ENTRY_FLAG_MASK < JSBOXEDWORD_ALIGN); #define CLEAR_ATOM_ENTRY_FLAGS(entry, flags) \ ((void)((entry)->keyAndFlags &= ~(jsuword)(flags))) -static JSDHashNumber -HashDouble(JSDHashTable *table, const void *key); - -static JSBool -MatchDouble(JSDHashTable *table, const JSDHashEntryHdr *hdr, const void *key); - static JSDHashNumber HashString(JSDHashTable *table, const void *key); static JSBool MatchString(JSDHashTable *table, const JSDHashEntryHdr *hdr, const void *key); -static const JSDHashTableOps DoubleHashOps = { - JS_DHashAllocTable, - JS_DHashFreeTable, - HashDouble, - MatchDouble, - JS_DHashMoveEntryStub, - JS_DHashClearEntryStub, - JS_DHashFinalizeStub, - NULL -}; - static const JSDHashTableOps StringHashOps = { JS_DHashAllocTable, JS_DHashFreeTable, @@ -331,55 +314,19 @@ static const JSDHashTableOps StringHashOps = { NULL }; -#define IS_DOUBLE_TABLE(table) ((table)->ops == &DoubleHashOps) -#define IS_STRING_TABLE(table) ((table)->ops == &StringHashOps) - -#define IS_INITIALIZED_STATE(state) IS_DOUBLE_TABLE(&(state)->doubleAtoms) - -static JSDHashNumber -HashDouble(JSDHashTable *table, const void *key) -{ - JS_ASSERT(IS_DOUBLE_TABLE(table)); - return JS_HASH_DOUBLE(*(jsdouble *)key); -} +#define IS_INITIALIZED_STATE(state) ((state)->stringAtoms.ops != NULL) static JSDHashNumber HashString(JSDHashTable *table, const void *key) { - JS_ASSERT(IS_STRING_TABLE(table)); return js_HashString((JSString *)key); } -static JSBool -MatchDouble(JSDHashTable *table, const JSDHashEntryHdr *hdr, const void *key) -{ - JSAtomHashEntry *entry = TO_ATOM_ENTRY(hdr); - jsdouble d1, d2; - - JS_ASSERT(IS_DOUBLE_TABLE(table)); - if (entry->keyAndFlags == 0) { - /* See comments in MatchString. */ - return JS_FALSE; - } - - d1 = *(jsdouble *)ATOM_ENTRY_KEY(entry); - d2 = *(jsdouble *)key; - if (JSDOUBLE_IS_NaN(d1)) - return JSDOUBLE_IS_NaN(d2); -#if defined(XP_WIN) - /* XXX MSVC miscompiles such that (NaN == 0) */ - if (JSDOUBLE_IS_NaN(d2)) - return JS_FALSE; -#endif - return d1 == d2; -} - static JSBool MatchString(JSDHashTable *table, const JSDHashEntryHdr *hdr, const void *key) { JSAtomHashEntry *entry = TO_ATOM_ENTRY(hdr); - JS_ASSERT(IS_STRING_TABLE(table)); if (entry->keyAndFlags == 0) { /* * This happens when js_AtomizeString adds a new hash entry and @@ -395,7 +342,7 @@ MatchString(JSDHashTable *table, const JSDHashEntryHdr *hdr, const void *key) */ return JS_FALSE; } - return js_EqualStrings((JSString *)ATOM_ENTRY_KEY(entry), (JSString *)key); + return js_EqualStrings(ATOM_ENTRY_KEY(entry), (JSString *)key); } /* @@ -405,7 +352,6 @@ MatchString(JSDHashTable *table, const JSDHashEntryHdr *hdr, const void *key) * atomized strings with just 1K entries. */ #define JS_STRING_HASH_COUNT 1024 -#define JS_DOUBLE_HASH_COUNT 64 JSBool js_InitAtomState(JSRuntime *rt) @@ -416,7 +362,6 @@ js_InitAtomState(JSRuntime *rt) * The caller must zero the state before calling this function. */ JS_ASSERT(!state->stringAtoms.ops); - JS_ASSERT(!state->doubleAtoms.ops); if (!JS_DHashTableInit(&state->stringAtoms, &StringHashOps, NULL, sizeof(JSAtomHashEntry), @@ -424,17 +369,6 @@ js_InitAtomState(JSRuntime *rt) state->stringAtoms.ops = NULL; return JS_FALSE; } - JS_ASSERT(IS_STRING_TABLE(&state->stringAtoms)); - - if (!JS_DHashTableInit(&state->doubleAtoms, &DoubleHashOps, - NULL, sizeof(JSAtomHashEntry), - JS_DHASH_DEFAULT_CAPACITY(JS_DOUBLE_HASH_COUNT))) { - state->doubleAtoms.ops = NULL; - JS_DHashTableFinish(&state->stringAtoms); - state->stringAtoms.ops = NULL; - return JS_FALSE; - } - JS_ASSERT(IS_DOUBLE_TABLE(&state->doubleAtoms)); #ifdef JS_THREADSAFE js_InitLock(&state->lock); @@ -455,9 +389,8 @@ js_string_uninterner(JSDHashTable *table, JSDHashEntryHdr *hdr, * Any string entry that remains at this point must be initialized, as the * last GC should clean any uninitialized ones. */ - JS_ASSERT(IS_STRING_TABLE(table)); JS_ASSERT(entry->keyAndFlags != 0); - str = (JSString *)ATOM_ENTRY_KEY(entry); + str = ATOM_ENTRY_KEY(entry); js_FinalizeStringRT(rt, str); return JS_DHASH_NEXT; @@ -478,7 +411,6 @@ js_FinishAtomState(JSRuntime *rt) JS_DHashTableEnumerate(&state->stringAtoms, js_string_uninterner, rt); JS_DHashTableFinish(&state->stringAtoms); - JS_DHashTableFinish(&state->doubleAtoms); #ifdef JS_THREADSAFE js_FinishLock(&state->lock); @@ -513,7 +445,6 @@ static JSDHashOperator js_atom_unpinner(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, void *arg) { - JS_ASSERT(IS_STRING_TABLE(table)); CLEAR_ATOM_ENTRY_FLAGS(TO_ATOM_ENTRY(hdr), ATOM_PINNED); return JS_DHASH_NEXT; } @@ -542,8 +473,7 @@ js_locked_atom_tracer(JSDHashTable *table, JSDHashEntryHdr *hdr, return JS_DHASH_NEXT; } JS_SET_TRACING_INDEX(trc, "locked_atom", (size_t)number); - MarkRaw(trc, ATOM_ENTRY_KEY(entry), - IS_STRING_TABLE(table) ? JSTRACE_STRING : JSTRACE_DOUBLE); + MarkRaw(trc, ATOM_ENTRY_KEY(entry), JSTRACE_STRING); return JS_DHASH_NEXT; } @@ -555,7 +485,6 @@ js_pinned_atom_tracer(JSDHashTable *table, JSDHashEntryHdr *hdr, JSTracer *trc = (JSTracer *)arg; uintN flags = ATOM_ENTRY_FLAGS(entry); - JS_ASSERT(IS_STRING_TABLE(table)); if (flags & (ATOM_PINNED | ATOM_INTERNED)) { JS_SET_TRACING_INDEX(trc, flags & ATOM_PINNED @@ -573,12 +502,10 @@ js_TraceAtomState(JSTracer *trc) JSRuntime *rt = trc->context->runtime; JSAtomState *state = &rt->atomState; - if (rt->gcKeepAtoms) { - JS_DHashTableEnumerate(&state->doubleAtoms, js_locked_atom_tracer, trc); + if (rt->gcKeepAtoms) JS_DHashTableEnumerate(&state->stringAtoms, js_locked_atom_tracer, trc); - } else { + else JS_DHashTableEnumerate(&state->stringAtoms, js_pinned_atom_tracer, trc); - } } static JSDHashOperator @@ -606,70 +533,15 @@ js_SweepAtomState(JSContext *cx) { JSAtomState *state = &cx->runtime->atomState; - JS_DHashTableEnumerate(&state->doubleAtoms, js_atom_sweeper, NULL); JS_DHashTableEnumerate(&state->stringAtoms, js_atom_sweeper, NULL); /* * Optimize for simplicity and mutate table generation numbers even if the * sweeper has not removed any entries. */ - state->doubleAtoms.generation++; state->stringAtoms.generation++; } -JSAtom * -js_AtomizeDouble(JSContext *cx, jsdouble d) -{ - JSAtomState *state; - JSDHashTable *table; - JSAtomHashEntry *entry; - uint32 gen; - jsdouble *key; - jsboxedword w; - - state = &cx->runtime->atomState; - table = &state->doubleAtoms; - - JS_LOCK(cx, &state->lock); - entry = TO_ATOM_ENTRY(JS_DHashTableOperate(table, &d, JS_DHASH_ADD)); - if (!entry) - goto failed_hash_add; - if (entry->keyAndFlags == 0) { - gen = ++table->generation; - JS_UNLOCK(cx, &state->lock); - - key = js_NewWeaklyRootedDoubleAtom(cx, d); - if (!key) - return NULL; - - JS_LOCK(cx, &state->lock); - if (table->generation == gen) { - JS_ASSERT(entry->keyAndFlags == 0); - } else { - entry = TO_ATOM_ENTRY(JS_DHashTableOperate(table, key, - JS_DHASH_ADD)); - if (!entry) - goto failed_hash_add; - if (entry->keyAndFlags != 0) - goto finish; - ++table->generation; - } - INIT_ATOM_ENTRY(entry, key); - } - - finish: - w = DOUBLE_TO_JSBOXEDWORD((jsdouble *)ATOM_ENTRY_KEY(entry)); - cx->weakRoots.lastAtom = (JSAtom *)w; - JS_UNLOCK(cx, &state->lock); - - return (JSAtom *)w; - - failed_hash_add: - JS_UNLOCK(cx, &state->lock); - JS_ReportOutOfMemory(cx); - return NULL; -} - JSAtom * js_AtomizeString(JSContext *cx, JSString *str, uintN flags) { @@ -723,7 +595,7 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags) if (!entry) goto failed_hash_add; if (entry->keyAndFlags != 0) { - key = (JSString *)ATOM_ENTRY_KEY(entry); + key = ATOM_ENTRY_KEY(entry); } else { /* * We created a new hashtable entry. Unless str is already allocated @@ -768,7 +640,7 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags) if (!entry) goto failed_hash_add; if (entry->keyAndFlags != 0) { - key = (JSString *)ATOM_ENTRY_KEY(entry); + key = ATOM_ENTRY_KEY(entry); goto finish; } ++table->generation; @@ -857,35 +729,13 @@ js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length) JS_LOCK(cx, &state->lock); hdr = JS_DHashTableOperate(&state->stringAtoms, &str, JS_DHASH_LOOKUP); str2 = JS_DHASH_ENTRY_IS_BUSY(hdr) - ? (JSString *)ATOM_ENTRY_KEY(TO_ATOM_ENTRY(hdr)) + ? ATOM_ENTRY_KEY(TO_ATOM_ENTRY(hdr)) : NULL; JS_UNLOCK(cx, &state->lock); return str2 ? STRING_TO_ATOM(str2) : NULL; } -JSBool -js_AtomizePrimitiveValue(JSContext *cx, jsboxedword w, JSAtom **atomp) -{ - JSAtom *atom; - - if (JSBOXEDWORD_IS_STRING(w)) { - atom = js_AtomizeString(cx, JSBOXEDWORD_TO_STRING(w), 0); - if (!atom) - return JS_FALSE; - } else if (JSBOXEDWORD_IS_DOUBLE(w)) { - atom = js_AtomizeDouble(cx, *JSBOXEDWORD_TO_DOUBLE(w)); - if (!atom) - return JS_FALSE; - } else { - JS_ASSERT(JSBOXEDWORD_IS_INT(w) || JSBOXEDWORD_IS_BOOLEAN(w) || - JSBOXEDWORD_IS_NULL(w) || JSBOXEDWORD_IS_VOID(w)); - atom = (JSAtom *)w; - } - *atomp = atom; - return JS_TRUE; -} - #ifdef DEBUG static JSDHashOperator @@ -894,7 +744,7 @@ atom_dumper(JSDHashTable *table, JSDHashEntryHdr *hdr, { JSAtomHashEntry *entry = TO_ATOM_ENTRY(hdr); FILE *fp = (FILE *)arg; - void *key; + JSString *key; uintN flags; fprintf(fp, "%3u %08x ", number, (uintN)entry->hdr.keyHash); @@ -902,12 +752,7 @@ atom_dumper(JSDHashTable *table, JSDHashEntryHdr *hdr, fputs("", fp); } else { key = ATOM_ENTRY_KEY(entry); - if (IS_DOUBLE_TABLE(table)) { - fprintf(fp, "%.16g", *(jsdouble *)key); - } else { - JS_ASSERT(IS_STRING_TABLE(table)); - js_FileEscapedString(fp, (JSString *)key, '"'); - } + js_FileEscapedString(fp, key, '"'); flags = ATOM_ENTRY_FLAGS(entry); if (flags != 0) { fputs((flags & (ATOM_PINNED | ATOM_INTERNED)) @@ -933,7 +778,6 @@ js_DumpAtoms(JSContext *cx, FILE *fp) putc('\n', fp); fprintf(fp, "doubleAtoms table contents:\n"); - JS_DHashTableEnumerate(&state->doubleAtoms, atom_dumper, fp); #ifdef JS_DHASHMETER JS_DHashTableDumpMeter(&state->doubleAtoms, atom_dumper, fp); #endif @@ -1306,7 +1150,7 @@ js_InternNonIntElementIdSlow(JSContext *cx, JSObject *obj, const Value &idval, if (!js_IsFunctionQName(cx, &idval.asObject(), idp)) return JS_FALSE; if (*idp != 0) { - *vp = IdToValue(*idp); + *vp = ID_TO_VALUE(*idp); return true; } diff --git a/js/src/jsatom.h b/js/src/jsatom.h index fd4319f53e4..3f9f27850b4 100644 --- a/js/src/jsatom.h +++ b/js/src/jsatom.h @@ -57,14 +57,10 @@ #define ATOM_NOCOPY 0x4 /* don't copy atom string bytes */ #define ATOM_TMPSTR 0x8 /* internal, to avoid extra string */ -#define ATOM_KEY(atom) ((jsboxedword)(atom)) -#define ATOM_IS_DOUBLE(atom) JSBOXEDWORD_IS_DOUBLE(ATOM_KEY(atom)) -#define ATOM_TO_DOUBLE(atom) JSBOXEDWORD_TO_DOUBLE(ATOM_KEY(atom)) -#define ATOM_IS_STRING(atom) JSBOXEDWORD_IS_STRING(ATOM_KEY(atom)) -#define ATOM_TO_STRING(atom) JSBOXEDWORD_TO_STRING(ATOM_KEY(atom)) +#define STRING_TO_ATOM(str) (JS_ASSERT(str->isAtomized()), \ + (JSAtom *)str) +#define ATOM_TO_STRING(atom) ((JSString *)atom) #define ATOM_TO_JSVAL(atom) STRING_TO_JSVAL(ATOM_TO_STRING(atom)) -#define STRING_TO_ATOM(str) (JS_ASSERT(str->isAtomized()), \ - (JSAtom *)STRING_TO_JSBOXEDWORD(str)) #if JS_BYTES_PER_WORD == 4 # define ATOM_HASH(atom) ((JSHashNumber)(atom) >> 2) @@ -204,7 +200,6 @@ struct JSAtomMap { struct JSAtomState { JSDHashTable stringAtoms; /* hash table with shared strings */ - JSDHashTable doubleAtoms; /* hash table with shared doubles */ #ifdef JS_THREADSAFE JSThinLock lock; #endif @@ -447,13 +442,6 @@ js_InitCommonAtoms(JSContext *cx); extern void js_FinishCommonAtoms(JSContext *cx); -/* - * Find or create the atom for a double value. Return null on failure to - * allocate memory. - */ -extern JSAtom * -js_AtomizeDouble(JSContext *cx, jsdouble d); - /* * Find or create the atom for a string. Return null on failure to allocate * memory. @@ -474,12 +462,6 @@ js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags); extern JSAtom * js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length); -/* - * This variant handles all primitive values. - */ -JSBool -js_AtomizePrimitiveValue(JSContext *cx, jsboxedword w, JSAtom **atomp); - #ifdef DEBUG extern JS_FRIEND_API(void) diff --git a/js/src/jsatominlines.h b/js/src/jsatominlines.h index 1a8247b782f..87ef01b68ae 100644 --- a/js/src/jsatominlines.h +++ b/js/src/jsatominlines.h @@ -88,24 +88,11 @@ js_ValueToStringId(JSContext *cx, const js::Value &v, jsid *idp) return false; } -inline bool -js_Int32ToId(JSContext* cx, int32 index, jsid* id) -{ - if (INT32_FITS_IN_JSID(index)) { - *id = INT_TO_JSID(index); - return true; - } - JSString* str = js_NumberToString(cx, index); - if (!str) - return false; - return js_ValueToStringId(cx, js::StringTag(str), id); -} - inline bool js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval, jsid *idp) { - JS_ASSERT_IF(idval.isInt32(), !INT32_FITS_IN_JSID(idval.asInt32())); + JS_ASSERT(!idval.isInt32()); #if JS_HAS_XML_SUPPORT extern bool js_InternNonIntElementIdSlow(JSContext *, JSObject *, @@ -121,7 +108,7 @@ inline bool js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval, jsid *idp, js::Value *vp) { - JS_ASSERT_IF(idval.isInt32(), !INT32_FITS_IN_JSID(idval.asInt32())); + JS_ASSERT(!idval.isInt32()); #if JS_HAS_XML_SUPPORT extern bool js_InternNonIntElementIdSlow(JSContext *, JSObject *, diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 9fa445f58ac..77eeed761d6 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -1374,7 +1374,7 @@ resolving_HashKey(JSDHashTable *table, const void *ptr) { const JSResolvingKey *key = (const JSResolvingKey *)ptr; - return (JSDHashNumber(uintptr_t(key->obj)) >> JSBOXEDWORD_TAGBITS) ^ key->id; + return (JSDHashNumber(uintptr_t(key->obj)) >> JS_GCTHING_ALIGN) ^ key->id; } JS_PUBLIC_API(JSBool) diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 048afc54b3b..36f4ca806b7 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -1213,7 +1213,6 @@ struct JSRuntime { JSGCArena *gcEmptyArenaList; #endif JSGCArenaList gcArenaList[FINALIZE_LIMIT]; - JSGCDoubleArenaList gcDoubleArenaList; js::RootedValueMap gcRootsHash; JSDHashTable gcLocksHash; jsrefcount gcKeepAtoms; @@ -2206,8 +2205,7 @@ class AutoGCRooter { OBJECT = -11, /* js::AutoObjectRooter */ STRING = -12, /* js::AutoStringRooter */ ID = -13, /* js::AutoIdRooter */ - VALVECTOR = -14, /* js::AutoValueVector */ - BOXEDVECTOR = -15 /* js::AutoBoxedWordVector */ + VALVECTOR = -14 /* js::AutoValueVector */ }; private: @@ -3033,48 +3031,6 @@ class AutoValueVector : private AutoGCRooter JS_DECL_USE_GUARD_OBJECT_NOTIFIER }; -class AutoBoxedWordVector : private AutoGCRooter -{ - public: - explicit AutoBoxedWordVector(JSContext *cx - JS_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoGCRooter(cx, BOXEDVECTOR), vector(cx) - { - JS_GUARD_OBJECT_NOTIFIER_INIT; - } - - size_t length() const { return vector.length(); } - - bool append(jsid id) { return vector.append(id); } - - void popBack() { vector.popBack(); } - - bool resize(size_t newLength) { - return vector.resize(newLength); - } - - bool reserve(size_t newLength) { - return vector.reserve(newLength); - } - - jsid operator[](size_t i) { return vector[i]; } - jsid operator[](size_t i) const { return vector[i]; } - - const jsid *begin() const { return vector.begin(); } - jsid *begin() { return vector.begin(); } - - const jsid *end() const { return vector.end(); } - jsid *end() { return vector.end(); } - - jsid back() const { return vector.back(); } - - friend void AutoGCRooter::trace(JSTracer *trc); - - private: - Vector vector; - JS_DECL_USE_GUARD_OBJECT_NOTIFIER -}; - static JS_ALWAYS_INLINE void MakeValueRangeGCSafe(Value *vec, uintN len) { diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index 0df9471dd40..a2f7159f695 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -170,7 +170,7 @@ StackSpace::popInlineFrame(JSContext *cx, JSStackFrame *up, JSStackFrame *down) void AutoIdArray::trace(JSTracer *trc) { JS_ASSERT(tag == IDARRAY); - MarkBoxedWordRange(trc, idArray->length, idArray->vector, "JSAutoIdArray.idArray"); + MarkIdRange(trc, idArray->length, idArray->vector, "JSAutoIdArray.idArray"); } class AutoNamespaces : protected AutoGCRooter { @@ -215,7 +215,7 @@ AutoGCRooter::trace(JSTracer *trc) case IDARRAY: { JSIdArray *ida = static_cast(this)->idArray; - MarkBoxedWordRange(trc, ida->length, ida->vector, "js::AutoIdArray.idArray"); + MarkIdRange(trc, ida->length, ida->vector, "js::AutoIdArray.idArray"); return; } @@ -228,15 +228,15 @@ AutoGCRooter::trace(JSTracer *trc) MarkValue(trc, desc.value, "PropertyDescriptor::value"); MarkValue(trc, desc.get, "PropertyDescriptor::get"); MarkValue(trc, desc.set, "PropertyDescriptor::set"); - MarkBoxedWord(trc, desc.id, "desc.id"); + MarkId(trc, desc.id, "desc.id"); } return; } case NAMESPACES: { JSXMLArray &array = static_cast(this)->array; - MarkObjectVector(trc, array.length, reinterpret_cast(array.vector), - "JSXMLArray"); + MarkObjectRange(trc, array.length, reinterpret_cast(array.vector), + "JSXMLArray"); array.cursors->trace(trc); return; } @@ -256,7 +256,7 @@ AutoGCRooter::trace(JSTracer *trc) return; case ID: - MarkBoxedWord(trc, static_cast(this)->idval, "js::AutoIdRooter.val"); + MarkId(trc, static_cast(this)->idval, "js::AutoIdRooter.val"); return; case VALVECTOR: { @@ -264,12 +264,6 @@ AutoGCRooter::trace(JSTracer *trc) MarkValueRange(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector"); return; } - - case BOXEDVECTOR: { - Vector &vector = static_cast(this)->vector; - MarkBoxedWordRange(trc, vector.length(), vector.begin(), "js::AutoIdVector.vector"); - return; - } } JS_ASSERT(tag >= 0); diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index e1022303e1c..84a21a3e5c7 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -764,7 +764,7 @@ js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, PropertyOp setter) if (JSID_IS_ATOM(id)) { atom = JSID_TO_ATOM(id); } else if (JSID_IS_INT(id)) { - if (!js_ValueToStringId(cx, IdToValue(id), &id)) + if (!js_ValueToStringId(cx, ID_TO_VALUE(id), &id)) return NULL; atom = JSID_TO_ATOM(id); } else { @@ -803,7 +803,7 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsid id, if (JSID_IS_INT(id)) { propid = id; } else { - if (!js_ValueToStringId(cx, IdToValue(id), &propid)) + if (!js_ValueToStringId(cx, ID_TO_VALUE(id), &propid)) return JS_FALSE; propid = js_CheckForStringIndex(propid); } @@ -1451,7 +1451,7 @@ JS_PUBLIC_API(JSBool) JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, JSPropertyDesc *pd) { - pd->id = Jsvalify(IdToValue(sprop->id)); + pd->id = ID_TO_JSVAL(sprop->id); JSBool wasThrowing = cx->throwing; AutoValueRooter lastException(cx, cx->exception); @@ -1493,7 +1493,7 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, JSScopeProperty *aprop; for (aprop = scope->lastProperty(); aprop; aprop = aprop->parent) { if (aprop != sprop && aprop->slot == sprop->slot) { - pd->alias = Jsvalify(IdToValue(aprop->id)); + pd->alias = ID_TO_JSVAL(aprop->id); break; } } @@ -1679,12 +1679,8 @@ GetAtomTotalSize(JSContext *cx, JSAtom *atom) size_t nbytes; nbytes = sizeof(JSAtom *) + sizeof(JSDHashEntryStub); - if (ATOM_IS_STRING(atom)) { - nbytes += sizeof(JSString); - nbytes += (ATOM_TO_STRING(atom)->flatLength() + 1) * sizeof(jschar); - } else if (ATOM_IS_DOUBLE(atom)) { - nbytes += sizeof(jsdouble); - } + nbytes += sizeof(JSString); + nbytes += (ATOM_TO_STRING(atom)->flatLength() + 1) * sizeof(jschar); return nbytes; } diff --git a/js/src/jsemit.cpp b/js/src/jsemit.cpp index 17f55bb2898..637625e1ec3 100644 --- a/js/src/jsemit.cpp +++ b/js/src/jsemit.cpp @@ -101,7 +101,8 @@ JSCodeGenerator::JSCodeGenerator(Parser *parser, numSpanDeps(0), numJumpTargets(0), spanDepTodo(0), arrayCompDepth(0), emitLevel(0), - constMap(parser->context) + constMap(parser->context), + constList(parser->context) { flags = TCF_COMPILING; memset(&prolog, 0, sizeof prolog); @@ -1546,37 +1547,13 @@ js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg) return JS_TRUE; } -static JS_ALWAYS_INLINE JSAtom * -JSBOXEDWORD_TO_ATOM(jsboxedword w) -{ - JS_STATIC_ASSERT(sizeof(jsboxedword) == sizeof(JSAtom *)); - return (JSAtom *)w; -} - JSBool js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, JSParseNode *pn) { - jsdouble dval; - int32_t ival; - JSAtom *valueAtom; - /* XXX just do numbers for now */ if (pn->pn_type == TOK_NUMBER) { - dval = pn->pn_dval; - if (JSDOUBLE_IS_INT32(dval, ival) && INT32_FITS_IN_JSBOXEDWORD(ival)) { - valueAtom = JSBOXEDWORD_TO_ATOM(INT_TO_JSBOXEDWORD(ival)); - } else { - /* - * We atomize double to root a jsdouble instance that we wrap as - * jsboxedword 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; - } - if (!cg->constMap.put(atom, valueAtom)) + if (!cg->constMap.put(atom, NumberTag(pn->pn_dval))) return JS_FALSE; } return JS_TRUE; @@ -1628,43 +1605,13 @@ js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp, JSStmtInfo *stmt (((attrs) & (JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_GETTER)) == \ (JSPROP_READONLY | JSPROP_PERMANENT)) -static JSAtom *NO_CONSTANT = (JSAtom *)SPECIAL_TO_JSBOXEDWORD(0xabcd); - -/* - * Outside of the compiler (specifically, switch statements), atoms can only be - * interned strings. Thus, this conversion is specific to the compiler. - */ -static bool -ValueToCompilerConstant(JSContext *cx, const Value &v, JSAtom **constp) -{ - jsboxedword w; - if (v.isNull()) - w = JSBOXEDWORD_NULL; - else if (v.isUndefined()) - w = JSBOXEDWORD_VOID; - else if (v.isInt32() && INT32_FITS_IN_JSBOXEDWORD(v.asInt32())) - w = INT_TO_JSBOXEDWORD(v.asInt32()); - else if (v.isNumber()) - return (*constp = js_AtomizeDouble(cx, v.asNumber())) != NULL; - else if (v.isString()) - w = STRING_TO_JSBOXEDWORD(v.asString()); - else if (v.isObject()) - w = OBJECT_TO_JSBOXEDWORD(&v.asObject()); - else if (v.isBoolean()) - w = BOOLEAN_TO_JSBOXEDWORD(v.asBoolean()); - else - JS_NOT_REACHED("invalid value"); - *constp = JSBOXEDWORD_TO_ATOM(w); - return true; -} - /* * The function sets vp to NO_CONSTANT when the atom does not corresponds to a * name defining a constant. */ static JSBool LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, - JSAtom **constp) + Value *constp) { JSBool ok; JSStmtInfo *stmt; @@ -1677,7 +1624,7 @@ LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, * This enables propagating consts from top-level into switch cases in a * function compiled along with the top-level script. */ - *constp = NO_CONSTANT; + constp->setMagic(JS_NO_CONSTANT); do { if (cg->inFunction() && cg->compileAndGo()) { /* XXX this will need revising if 'const' becomes block-scoped. */ @@ -1686,7 +1633,7 @@ LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, return JS_TRUE; if (JSCodeGenerator::ConstMap::Ptr p = cg->constMap.lookup(atom)) { - JS_ASSERT(p->value != NO_CONSTANT); + JS_ASSERT(!p->value.isMagic(JS_NO_CONSTANT)); *constp = p->value; return JS_TRUE; } @@ -1717,9 +1664,8 @@ LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom, ok = obj->getAttributes(cx, ATOM_TO_JSID(atom), prop, &attrs); if (ok && IS_CONSTANT_PROPERTY(attrs)) { Value v; - ok = obj->getProperty(cx, ATOM_TO_JSID(atom), &v); - if (ok) - ok = ValueToCompilerConstant(cx, v, constp); + if (obj->getProperty(cx, ATOM_TO_JSID(atom), &v)) + *constp = v; } } if (prop) @@ -2947,7 +2893,6 @@ EmitElemOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg) } right = &rtmp; right->pn_type = TOK_STRING; - JS_ASSERT(ATOM_IS_STRING(pn->pn_atom)); right->pn_op = js_IsIdentifier(ATOM_TO_STRING(pn->pn_atom)) ? JSOP_QNAMEPART : JSOP_STRING; @@ -2996,8 +2941,6 @@ EmitNumberOp(JSContext *cx, jsdouble dval, JSCodeGenerator *cg) uint32 u; ptrdiff_t off; jsbytecode *pc; - JSAtom *atom; - JSAtomListElement *ale; if (JSDOUBLE_IS_INT32(dval, ival)) { if (ival == 0) @@ -3026,14 +2969,26 @@ EmitNumberOp(JSContext *cx, jsdouble dval, JSCodeGenerator *cg) return JS_TRUE; } - atom = js_AtomizeDouble(cx, dval); - if (!atom) + if (!cg->constList.append(DoubleTag(dval))) return JS_FALSE; - ale = cg->atomList.add(cg->parser, atom); - if (!ale) - return JS_FALSE; - return EmitIndexOp(cx, JSOP_DOUBLE, ALE_INDEX(ale), cg); + return EmitIndexOp(cx, JSOP_DOUBLE, cg->constList.length() - 1, cg); +} + +/* + * To avoid bloating all parse nodes for the special case of switch, values are + * allocated in the temp pool and pointed to by the parse node. These values + * are not currently recycled (like parse nodes) and the temp pool is only + * flushed at the end of compiling a script, so these values are technically + * leaked. This would only be a problem for scripts containing a large number + * of large switches, which seems unlikely. + */ +static Value * +AllocateSwitchConstant(JSContext *cx) +{ + Value *pv; + JS_ARENA_ALLOCATE_TYPE(pv, Value, &cx->tempPool); + return pv; } static JSBool @@ -3046,9 +3001,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, JSParseNode *pn2, *pn3, *pn4; uint32 caseCount, tableLength; JSParseNode **table; - jsdouble d; int32_t i, low, high; - JSAtom *atom; JSAtomListElement *ale; intN noteIndex; size_t switchSize, tableSize; @@ -3162,30 +3115,22 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, pn4 = pn3->pn_left; while (pn4->pn_type == TOK_RP) pn4 = pn4->pn_kid; + + Value constVal; switch (pn4->pn_type) { case TOK_NUMBER: - d = pn4->pn_dval; - if (JSDOUBLE_IS_INT32(d, i) && INT32_FITS_IN_JSBOXEDWORD(i)) { - pn3->pn_val = INT_TO_JSBOXEDWORD(i); - } else { - atom = js_AtomizeDouble(cx, d); - if (!atom) { - ok = JS_FALSE; - goto release; - } - pn3->pn_val = ATOM_KEY(atom); - } + constVal.setNumber(pn4->pn_dval); break; case TOK_STRING: - pn3->pn_val = ATOM_KEY(pn4->pn_atom); + constVal.setString(ATOM_TO_STRING(pn4->pn_atom)); break; case TOK_NAME: if (!pn4->maybeExpr()) { - ok = LookupCompileTimeConstant(cx, cg, pn4->pn_atom, &atom); + ok = LookupCompileTimeConstant(cx, cg, pn4->pn_atom, &constVal); if (!ok) goto release; - if (atom != NO_CONSTANT) { - if (!JSBOXEDWORD_IS_PRIMITIVE(ATOM_KEY(atom))) { + if (!constVal.isMagic(JS_NO_CONSTANT)) { + if (constVal.isObject()) { /* * XXX JSOP_LOOKUPSWITCH does not support const- * propagated object values, see bug 407186. @@ -3193,7 +3138,6 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, switchOp = JSOP_CONDSWITCH; continue; } - pn3->pn_val = ATOM_KEY(atom); constPropagated = JS_TRUE; break; } @@ -3201,15 +3145,15 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, /* FALL THROUGH */ case TOK_PRIMARY: if (pn4->pn_op == JSOP_TRUE) { - pn3->pn_val = JSBOXEDWORD_TRUE; + constVal.setBoolean(true); break; } if (pn4->pn_op == JSOP_FALSE) { - pn3->pn_val = JSBOXEDWORD_FALSE; + constVal.setBoolean(false); break; } if (pn4->pn_op == JSOP_NULL) { - pn3->pn_val = JSBOXEDWORD_NULL; + constVal.setNull(); break; } /* FALL THROUGH */ @@ -3217,16 +3161,23 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, switchOp = JSOP_CONDSWITCH; continue; } + JS_ASSERT(constVal.isPrimitive()); - JS_ASSERT(JSBOXEDWORD_IS_PRIMITIVE(ATOM_KEY(pn3->pn_val))); + pn3->pn_pval = AllocateSwitchConstant(cx); + if (!pn3->pn_pval) { + ok = JS_FALSE; + goto release; + } + + *pn3->pn_pval = constVal; if (switchOp != JSOP_TABLESWITCH) continue; - if (!JSBOXEDWORD_IS_INT(ATOM_KEY(pn3->pn_val))) { + if (!pn3->pn_pval->isInt32()) { switchOp = JSOP_LOOKUPSWITCH; continue; } - i = JSBOXEDWORD_TO_INT(ATOM_KEY(pn3->pn_val)); + i = pn3->pn_pval->asInt32(); if ((jsuint)(i + (jsint)JS_BIT(15)) >= (jsuint)JS_BIT(16)) { switchOp = JSOP_LOOKUPSWITCH; continue; @@ -3289,7 +3240,7 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, * switch generation and use conditional switch if it exceeds * the limit. */ - if (caseCount + cg->atomList.count > JS_BIT(16)) + if (caseCount + cg->constList.length() > JS_BIT(16)) switchOp = JSOP_CONDSWITCH; } } @@ -3421,7 +3372,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; - i = JSBOXEDWORD_TO_INT(ATOM_KEY(pn3->pn_val)); + i = pn3->pn_pval->asInt32(); i -= low; JS_ASSERT((uint32)i < tableLength); table[i] = pn3; @@ -3564,12 +3515,9 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn, for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) { if (pn3->pn_type == TOK_DEFAULT) continue; - if (!js_AtomizePrimitiveValue(cx, ATOM_KEY(pn3->pn_val), &atom)) + if (!cg->constList.append(*pn3->pn_pval)) goto bad; - ale = cg->atomList.add(cg->parser, atom); - if (!ale) - goto bad; - SET_INDEX(pc, ALE_INDEX(ale)); + SET_INDEX(pc, cg->constList.length() - 1); pc += INDEX_LEN; off = pn3->pn_offset - top; @@ -7465,3 +7413,13 @@ JSCGObjectList::finish(JSObjectArray *array) } while ((objbox = objbox->emitLink) != NULL); JS_ASSERT(cursor == array->vector); } + +void +JSGCConstList::finish(JSConstArray *array) +{ + JS_ASSERT(array->length == list.length()); + Value *src = list.begin(), *srcend = list.end(); + Value *dst = array->vector; + for (; src != srcend; ++src, ++dst) + *dst = *src; +} diff --git a/js/src/jsemit.h b/js/src/jsemit.h index a660619e8bf..9b8f8679631 100644 --- a/js/src/jsemit.h +++ b/js/src/jsemit.h @@ -430,6 +430,16 @@ struct JSCGObjectList { void finish(JSObjectArray *array); }; +class JSGCConstList { + js::Vector list; + public: + JSGCConstList(JSContext *cx) : list(cx) {} + bool append(js::Value v) { return list.append(v); } + size_t length() const { return list.length(); } + void finish(JSConstArray *array); + +}; + struct JSCodeGenerator : public JSTreeContext { JSArenaPool *codePool; /* pointer to thread code arena pool */ @@ -469,9 +479,11 @@ struct JSCodeGenerator : public JSTreeContext uintN emitLevel; /* js_EmitTree recursion level */ - typedef js::HashMap ConstMap; + typedef js::HashMap ConstMap; ConstMap constMap; /* compile time constants */ + JSGCConstList constList; /* constants to be included with the script */ + JSCGObjectList objectList; /* list of emitted objects */ JSCGObjectList regexpList; /* list of emitted regexp that will be cloned during execution */ diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index 79d94653a13..9c4e5ce4323 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -1041,7 +1041,8 @@ js_InitExceptionClasses(JSContext *cx, JSObject *obj) } /* Add the name property to the prototype. */ - if (!JS_DefineProperty(cx, proto, js_name_str, ATOM_TO_JSVAL(atom), + if (!JS_DefineProperty(cx, proto, js_name_str, + STRING_TO_JSVAL(ATOM_TO_STRING(atom)), NULL, NULL, JSPROP_ENUMERATE)) { return NULL; } diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 65e01dd11a7..51fd25aa2c5 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -298,9 +298,9 @@ args_delProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) uintN arg = uintN(JSID_TO_INT(id)); if (arg < obj->getArgsLength()) obj->setArgsElement(arg, Value(JS_ARGS_HOLE)); - } else if (id == ATOM_KEY(cx->runtime->atomState.lengthAtom)) { + } else if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) { obj->setArgsLengthOverridden(); - } else if (id == ATOM_KEY(cx->runtime->atomState.calleeAtom)) { + } else if (id == ATOM_TO_JSID(cx->runtime->atomState.calleeAtom)) { obj->setArgsCallee(Value(JS_ARGS_HOLE)); } return true; @@ -393,6 +393,9 @@ WrapEscapingClosure(JSContext *cx, JSStackFrame *fp, JSObject *funobj, JSFunctio : 0, (script->trynotesOffset != 0) ? script->trynotes()->length + : 0, + (script->constOffset != 0) + ? script->consts()->length : 0); if (!wscript) return NULL; @@ -509,11 +512,11 @@ ArgGetter(JSContext *cx, JSObject *obj, jsid id, Value *vp) *vp = v; } } - } else if (id == ATOM_KEY(cx->runtime->atomState.lengthAtom)) { + } else if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) { if (!obj->isArgsLengthOverridden()) vp->setInt32(obj->getArgsLength()); } else { - JS_ASSERT(id == ATOM_KEY(cx->runtime->atomState.calleeAtom)); + JS_ASSERT(id == ATOM_TO_JSID(cx->runtime->atomState.calleeAtom)); const Value &v = obj->getArgsCallee(); if (!v.isMagic(JS_ARGS_HOLE)) { /* @@ -562,8 +565,8 @@ ArgSetter(JSContext *cx, JSObject *obj, jsid id, Value *vp) } } } else { - JS_ASSERT(id == ATOM_KEY(cx->runtime->atomState.lengthAtom) || - id == ATOM_KEY(cx->runtime->atomState.calleeAtom)); + JS_ASSERT(id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom) || + id == ATOM_TO_JSID(cx->runtime->atomState.calleeAtom)); } /* @@ -589,10 +592,10 @@ args_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, uint32 arg = uint32(JSID_TO_INT(id)); if (arg < obj->getArgsLength() && !obj->getArgsElement(arg).isMagic(JS_ARGS_HOLE)) valid = true; - } else if (id == ATOM_KEY(cx->runtime->atomState.lengthAtom)) { + } else if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) { if (!obj->isArgsLengthOverridden()) valid = true; - } else if (id == ATOM_KEY(cx->runtime->atomState.calleeAtom)) { + } else if (id == ATOM_TO_JSID(cx->runtime->atomState.calleeAtom)) { if (!obj->getArgsCallee().isMagic(JS_ARGS_HOLE)) valid = true; } @@ -602,8 +605,8 @@ args_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, * XXX ECMA specs DontEnum even for indexed properties, contrary to * other array-like objects. */ - Value undef = undefinedValue(); - if (!js_DefineProperty(cx, obj, id, &undef, ArgGetter, ArgSetter, JSPROP_SHARED)) + Value tmp = UndefinedTag(); + if (!js_DefineProperty(cx, obj, id, &tmp, ArgGetter, ArgSetter, JSPROP_SHARED)) return JS_FALSE; *objp = obj; } @@ -1381,7 +1384,7 @@ fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) if (vp->isObject()) { callbacks = JS_GetSecurityCallbacks(cx); if (callbacks && callbacks->checkObjectAccess) { - id = ATOM_KEY(cx->runtime->atomState.callerAtom); + id = ATOM_TO_JSID(cx->runtime->atomState.callerAtom); if (!callbacks->checkObjectAccess(cx, obj, id, JSACC_READ, Jsvalify(vp))) return JS_FALSE; } @@ -1460,7 +1463,7 @@ fun_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp) * prototype property. */ atom = cx->runtime->atomState.classPrototypeAtom; - if (id == ATOM_KEY(atom)) { + if (id == ATOM_TO_JSID(atom)) { JS_ASSERT(!IsInternalFunctionObject(obj)); /* @@ -1496,7 +1499,7 @@ fun_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp) LazyFunctionProp *lfp = &lazy_function_props[i]; atom = OFFSET_TO_ATOM(cx->runtime, lfp->atomOffset); - if (id == ATOM_KEY(atom)) { + if (id == ATOM_TO_JSID(atom)) { JS_ASSERT(!IsInternalFunctionObject(obj)); if (!js_DefineNativeProperty(cx, obj, @@ -2637,12 +2640,6 @@ js_ReportIsNotFunction(JSContext *cx, const Value *vp, uintN flags) JS_STATIC_ASSERT(2 <= MAX_ARRAY_LOCALS); JS_STATIC_ASSERT(MAX_ARRAY_LOCALS < JS_BITMASK(16)); -/* - * We use the lowest bit of the string atom to distinguish const from var - * name when there is only single name or when names are stored as an array. - */ -JS_STATIC_ASSERT((JSBOXEDWORD_TYPE_STRING & 1) == 0); - /* * When we use a hash table to store the local names, we use a singly linked * list to record the indexes of duplicated parameter names to preserve the @@ -2696,7 +2693,6 @@ HashLocalName(JSContext *cx, JSLocalNameMap *map, JSAtom *name, return JS_TRUE; } #endif - JS_ASSERT(ATOM_IS_STRING(name)); entry = (JSLocalNameHashEntry *) JS_DHashTableOperate(&map->names, name, JS_DHASH_ADD); if (!entry) { diff --git a/js/src/jsfun.h b/js/src/jsfun.h index aeb84855ada..44b399a6b21 100644 --- a/js/src/jsfun.h +++ b/js/src/jsfun.h @@ -205,6 +205,8 @@ struct JSFunction : public JSObject } }; +JS_STATIC_ASSERT(sizeof(JSFunction) % JS_GCTHING_ALIGN == 0); + /* * Trace-annotated native. This expands to a JSFunctionSpec initializer (like * JS_FN in jsapi.h). fastcall is a FastNative; trcinfo is a diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 15ebffebd4c..d0d4c2dfa2f 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -825,8 +825,6 @@ InitGCArenaLists(JSRuntime *rt) arenaList->thingKind = i; arenaList->thingSize = GetFinalizableThingSize(i); } - rt->gcDoubleArenaList.head = NULL; - rt->gcDoubleArenaList.cursor = NULL; } static void @@ -836,8 +834,6 @@ FinishGCArenaLists(JSRuntime *rt) rt->gcArenaList[i].head = NULL; rt->gcArenaList[i].cursor = NULL; } - rt->gcDoubleArenaList.head = NULL; - rt->gcDoubleArenaList.cursor = NULL; rt->gcBytes = 0; @@ -983,7 +979,6 @@ JS_FRIEND_API(void) js_DumpGCStats(JSRuntime *rt, FILE *fp) { static const char *const GC_ARENA_NAMES[] = { - "double", "object", "function", #if JS_HAS_XML_SUPPORT @@ -999,7 +994,7 @@ js_DumpGCStats(JSRuntime *rt, FILE *fp) "external_string_6", "external_string_7", }; - JS_STATIC_ASSERT(JS_ARRAY_LENGTH(GC_ARENA_NAMES) == FINALIZE_LIMIT + 1); + JS_STATIC_ASSERT(JS_ARRAY_LENGTH(GC_ARENA_NAMES) == FINALIZE_LIMIT); fprintf(fp, "\nGC allocation statistics:\n\n"); @@ -1019,23 +1014,17 @@ js_DumpGCStats(JSRuntime *rt, FILE *fp) size_t sumLocalAlloc = 0; size_t sumFail = 0; size_t sumRetry = 0; - for (int i = -1; i < (int) FINALIZE_LIMIT; i++) { + for (int i = 0; i < (int) FINALIZE_LIMIT; i++) { size_t thingSize, thingsPerArena; JSGCArenaStats *st; - if (i == -1) { - thingSize = sizeof(jsdouble); - thingsPerArena = DOUBLES_PER_ARENA; - st = &rt->gcStats.doubleArenaStats; - } else { - thingSize = rt->gcArenaList[i].thingSize; - thingsPerArena = ThingsPerArena(thingSize); - st = &rt->gcStats.arenaStats[i]; - } + thingSize = rt->gcArenaList[i].thingSize; + thingsPerArena = ThingsPerArena(thingSize); + st = &rt->gcStats.arenaStats[i]; if (st->maxarenas == 0) continue; fprintf(fp, "%s arenas (thing size %lu, %lu things per arena):", - GC_ARENA_NAMES[i + 1], UL(thingSize), UL(thingsPerArena)); + GC_ARENA_NAMES[i], UL(thingSize), UL(thingsPerArena)); putc('\n', fp); fprintf(fp, " arenas before GC: %lu\n", UL(st->narenas)); fprintf(fp, " new arenas before GC: %lu (%.1f%%)\n", @@ -1068,23 +1057,17 @@ js_DumpGCStats(JSRuntime *rt, FILE *fp) } fputs("Never used arenas:\n", fp); - for (int i = -1; i < (int) FINALIZE_LIMIT; i++) { + for (int i = 0; i < (int) FINALIZE_LIMIT; i++) { size_t thingSize, thingsPerArena; JSGCArenaStats *st; - if (i == -1) { - thingSize = sizeof(jsdouble); - thingsPerArena = DOUBLES_PER_ARENA; - st = &rt->gcStats.doubleArenaStats; - } else { - thingSize = rt->gcArenaList[i].thingSize; - thingsPerArena = ThingsPerArena(thingSize); - st = &rt->gcStats.arenaStats[i]; - } + thingSize = rt->gcArenaList[i].thingSize; + thingsPerArena = ThingsPerArena(thingSize); + st = &rt->gcStats.arenaStats[i]; if (st->maxarenas != 0) continue; fprintf(fp, "%s (thing size %lu, %lu things per arena)\n", - GC_ARENA_NAMES[i + 1], UL(thingSize), UL(thingsPerArena)); + GC_ARENA_NAMES[i], UL(thingSize), UL(thingsPerArena)); } fprintf(fp, "\nTOTAL STATS:\n"); fprintf(fp, " bytes allocated: %lu\n", UL(rt->gcBytes)); @@ -1331,14 +1314,12 @@ JSGCFreeLists::purge() *p = NULL; } } - doubles = NULL; } void JSGCFreeLists::moveTo(JSGCFreeLists *another) { *another = *this; - doubles = NULL; PodArrayZero(finalizables); JS_ASSERT(isEmpty()); } @@ -1557,179 +1538,6 @@ js_NewFinalizableGCThing(JSContext *cx, unsigned thingKind) return thing; } -static JSGCThing * -TurnUsedArenaIntoDoubleList(JSGCArena *a) -{ - JSGCThing *head; - JSGCThing **tailp = &head; - jsuword thing = a->toPageStart(); - jsbitmap *markBitmap = a->getMarkBitmap(); - jsbitmap *lastMarkWord = markBitmap + GC_MARK_BITMAP_WORDS - 1; - - for (jsbitmap *m = markBitmap; m <= lastMarkWord; ++m) { - JS_ASSERT(thing < a->toPageStart() + GC_ARENA_SIZE); - JS_ASSERT((thing - a->toPageStart()) % - (JS_BITS_PER_WORD * sizeof(jsdouble)) == 0); - - jsbitmap bits = *m; - if (bits == jsbitmap(-1)) { - thing += JS_BITS_PER_WORD * sizeof(jsdouble); - } else { - /* - * We have some zero bits. Turn corresponding cells into a list - * unrolling the loop for better performance. - */ - const unsigned unroll = 4; - const jsbitmap unrollMask = (jsbitmap(1) << unroll) - 1; - JS_STATIC_ASSERT((JS_BITS_PER_WORD & unrollMask) == 0); - - for (unsigned n = 0; n != JS_BITS_PER_WORD; n += unroll) { - jsbitmap bitsChunk = bits & unrollMask; - bits >>= unroll; - if (bitsChunk == unrollMask) { - thing += unroll * sizeof(jsdouble); - } else { -#define DO_BIT(bit) \ - if (!(bitsChunk & (jsbitmap(1) << (bit)))) { \ - JS_ASSERT(thing - a->toPageStart() <= \ - (DOUBLES_PER_ARENA - 1) * sizeof(jsdouble));\ - JSGCThing *t = reinterpret_cast(thing); \ - *tailp = t; \ - tailp = &t->link; \ - } \ - thing += sizeof(jsdouble); - DO_BIT(0); - DO_BIT(1); - DO_BIT(2); - DO_BIT(3); -#undef DO_BIT - } - } - } - } - *tailp = NULL; - return head; -} - -static JSGCThing * -RefillDoubleFreeList(JSContext *cx) -{ - JS_ASSERT(!GetGCFreeLists(cx)->doubles); - - JSRuntime *rt = cx->runtime; - JS_ASSERT(!rt->gcRunning); - - JS_LOCK_GC(rt); - - bool canGC = !JS_ON_TRACE(cx) && !JS_THREAD_DATA(cx)->waiveGCQuota; - bool doGC = canGC && IsGCThresholdReached(rt); - JSGCArena *a; - for (;;) { - if (doGC) { - LastDitchGC(cx); - METER(rt->gcStats.doubleArenaStats.retry++); - canGC = false; - - /* See comments in RefillFinalizableFreeList. */ - JSGCThing *freeList = GetGCFreeLists(cx)->doubles; - if (freeList) { - JS_UNLOCK_GC(rt); - return freeList; - } - } - - /* - * Loop until we find arena with some free doubles. We turn arenas - * into free lists outside the lock to minimize contention between - * threads. - */ - while (!!(a = rt->gcDoubleArenaList.cursor)) { - rt->gcDoubleArenaList.cursor = a->getInfo()->prev; - JS_UNLOCK_GC(rt); - JSGCThing *list = TurnUsedArenaIntoDoubleList(a); - if (list) - return list; - JS_LOCK_GC(rt); - } - a = NewGCArena(cx); - if (a) - break; - if (!canGC) { - METER(rt->gcStats.doubleArenaStats.fail++); - JS_UNLOCK_GC(rt); - return NULL; - } - doGC = true; - } - - JSGCArenaInfo *ainfo = a->getInfo(); - ainfo->list = NULL; - ainfo->freeList = NULL; - ainfo->prev = rt->gcDoubleArenaList.head; - rt->gcDoubleArenaList.head = a; - JS_UNLOCK_GC(rt); - - ainfo->hasMarkedDoubles = false; - return MakeNewArenaFreeList(a, sizeof(jsdouble)); -} - -jsdouble * -js_NewWeaklyRootedDoubleAtom(JSContext *cx, jsdouble d) -{ - /* Updates of metering counters here are not thread-safe. */ - METER(cx->runtime->gcStats.doubleArenaStats.alloc++); - - JSGCThing **freeListp = &JS_THREAD_DATA(cx)->gcFreeLists.doubles; - JSGCThing *thing = *freeListp; - if (thing) { - METER(cx->runtime->gcStats.doubleArenaStats.localalloc++); - JS_ASSERT(!JS_THREAD_DATA(cx)->localRootStack); - CheckGCFreeListLink(thing); - *freeListp = thing->link; - - jsdouble *dp = reinterpret_cast(thing); - *dp = d; - cx->weakRoots.newbornDouble = dp; - return dp; - } - - JSLocalRootStack *lrs = JS_THREAD_DATA(cx)->localRootStack; - for (;;) { - if (lrs) { - freeListp = &lrs->gcFreeLists.doubles; - thing = *freeListp; - if (thing) { - METER(cx->runtime->gcStats.doubleArenaStats.localalloc++); - break; - } - } - thing = RefillDoubleFreeList(cx); - if (thing) { - JS_ASSERT(!*freeListp || *freeListp == thing); - break; - } - - if (!JS_ON_TRACE(cx)) { - /* Trace code handle this on its own. */ - js_ReportOutOfMemory(cx); - METER(cx->runtime->gcStats.doubleArenaStats.fail++); - } - return NULL; - } - - CheckGCFreeListLink(thing); - *freeListp = thing->link; - - jsdouble *dp = &thing->dbl; - *dp = d; - cx->weakRoots.newbornDouble = dp; - /* - * N.B. We any active local root scope, since this function is called only - * from the compiler to create double atoms. - */ - return dp; -} - JSBool js_LockGCThingRT(JSRuntime *rt, void *thing) { @@ -2093,14 +1901,7 @@ MarkRaw(JSTracer *trc, void *thing, uint32 kind) void MarkGCThingRaw(JSTracer *trc, void *thing) { -#ifdef DEBUG - /* - * The incoming thing should be a real gc-thing, not a boxed, word-sized - * primitive value. - */ - jsboxedword w = (jsboxedword)thing; - JS_ASSERT(JSBOXEDWORD_IS_OBJECT(w)); -#endif + JS_ASSERT(size_t(thing) % JS_GCTHING_ALIGN == 0); if (!thing) return; @@ -2141,17 +1942,6 @@ gc_root_traversal(JSTracer *trc, const RootEntry &entry) } } } - if (!root_points_to_gcArenaList) { - for (JSGCArena *a = rt->gcDoubleArenaList.head; - a; - a = a->getInfo()->prev) { - if (thing - a->toPageStart() < - DOUBLES_PER_ARENA * sizeof(jsdouble)) { - root_points_to_gcArenaList = true; - break; - } - } - } if (!root_points_to_gcArenaList && entry.value.name) { fprintf(stderr, "JS API usage error: the address passed to JS_AddNamedRoot currently holds an\n" @@ -2232,10 +2022,8 @@ JSWeakRoots::mark(JSTracer *trc) newbornNames[i]); } } - if (newbornDouble) - MarkGCThing(trc, newbornDouble, "newborn_double"); if (lastAtom) - MarkBoxedWord(trc, ATOM_TO_JSID(lastAtom), "lastAtom"); + MarkString(trc, ATOM_TO_STRING(lastAtom), "lastAtom"); MarkGCThing(trc, lastInternalResult, "lastInternalResult"); } @@ -2631,7 +2419,6 @@ struct GCTimer { uint64 startSweep; uint64 sweepObjectEnd; uint64 sweepStringEnd; - uint64 sweepDoubleEnd; uint64 sweepDestroyEnd; uint64 end; @@ -2666,8 +2453,7 @@ struct GCTimer { (double)(sweepDestroyEnd - startSweep) / 1e6, (double)(sweepObjectEnd - startSweep) / 1e6, (double)(sweepStringEnd - sweepObjectEnd) / 1e6, - (double)(sweepDoubleEnd - sweepStringEnd) / 1e6, - (double)(sweepDestroyEnd - sweepDoubleEnd) / 1e6); + (double)(sweepDestroyEnd - sweepStringEnd) / 1e6); fprintf(gcFile, "%10d, %10d \n", newChunkCount, destroyChunkCount); fflush(gcFile); @@ -2694,39 +2480,6 @@ struct GCTimer { # define GCTIMER_END(last) ((void) 0) #endif -static void -SweepDoubles(JSRuntime *rt) -{ -#ifdef JS_GCMETER - uint32 nlivearenas = 0, nkilledarenas = 0, nthings = 0; -#endif - JSGCArena **ap = &rt->gcDoubleArenaList.head; - while (JSGCArena *a = *ap) { - JSGCArenaInfo *ainfo = a->getInfo(); - if (!ainfo->hasMarkedDoubles) { - /* No marked double values in the arena. */ - *ap = ainfo->prev; - ReleaseGCArena(rt, a); - METER(nkilledarenas++); - } else { -#ifdef JS_GCMETER - jsdouble *thing = reinterpret_cast(a->toPageStart()); - jsdouble *end = thing + DOUBLES_PER_ARENA; - for (; thing != end; ++thing) { - if (IsMarkedGCThing(thing)) - METER(nthings++); - } - METER(nlivearenas++); -#endif - ainfo->hasMarkedDoubles = false; - ap = &ainfo->prev; - } - } - METER(UpdateArenaStats(&rt->gcStats.doubleArenaStats, - nlivearenas, nkilledarenas, nthings)); - rt->gcDoubleArenaList.cursor = rt->gcDoubleArenaList.head; -} - #ifdef JS_THREADSAFE namespace js { @@ -2841,12 +2594,6 @@ GC(JSContext *cx GCTIMER_PARAM) rt->gcMarkingTracer = &trc; JS_ASSERT(IS_GC_MARKING_TRACER(&trc)); - for (JSGCArena *a = rt->gcDoubleArenaList.head; a;) { - JSGCArenaInfo *ainfo = a->getInfo(); - JS_ASSERT(!ainfo->hasMarkedDoubles); - a = ainfo->prev; - } - js_TraceRuntime(&trc); js_MarkScriptFilenames(rt); @@ -2936,9 +2683,6 @@ GC(JSContext *cx GCTIMER_PARAM) } TIMESTAMP(sweepStringEnd); - SweepDoubles(rt); - TIMESTAMP(sweepDoubleEnd); - /* * Sweep the runtime's property tree after finalizing objects, in case any * had watchpoints referencing tree nodes. diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 20e74fdb670..8141ae21fc4 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -132,13 +132,6 @@ typedef struct JSPtrTable { extern JSBool js_RegisterCloseableIterator(JSContext *cx, JSObject *obj); -/* - * Return a pointer to a new GC-allocated and weakly-rooted jsdouble number, - * or null when the allocation fails. - */ -extern jsdouble * -js_NewWeaklyRootedDoubleAtom(JSContext *cx, jsdouble d); - #ifdef JS_TRACER extern JSBool js_ReserveObjects(JSContext *cx, size_t nobjects); @@ -296,13 +289,7 @@ struct JSGCArenaList { */ }; -struct JSGCDoubleArenaList { - JSGCArena *head; /* list start */ - JSGCArena *cursor; /* next arena with free cells */ -}; - struct JSGCFreeLists { - JSGCThing *doubles; JSGCThing *finalizables[FINALIZE_LIMIT]; void purge(); @@ -310,8 +297,6 @@ struct JSGCFreeLists { #ifdef DEBUG bool isEmpty() const { - if (doubles) - return false; for (size_t i = 0; i != JS_ARRAY_LENGTH(finalizables); ++i) { if (finalizables[i]) return false; @@ -327,7 +312,6 @@ js_DestroyScriptsToGC(JSContext *cx, JSThreadData *data); struct JSWeakRoots { /* Most recently created things by type, members of the GC's root set. */ void *finalizableNewborns[FINALIZE_LIMIT]; - jsdouble *newbornDouble; /* Atom root for the last-looked-up atom on this context. */ JSAtom *lastAtom; @@ -447,7 +431,6 @@ struct JSGCStats { uint32 maxnchunks; /* maximum number of allocated chunks */ JSGCArenaStats arenaStats[FINALIZE_LIMIT]; - JSGCArenaStats doubleArenaStats; }; extern JS_FRIEND_API(void) @@ -476,13 +459,40 @@ Mark(JSTracer *trc, void *thing, uint32 kind, const char *name) } static inline void -MarkObjectVector(JSTracer *trc, uint32 len, JSObject **vec, const char *name) +MarkString(JSTracer *trc, JSString *str, const char *name) +{ + JS_SET_TRACING_NAME(trc, name); + MarkRaw(trc, str, JSTRACE_STRING); +} + +static inline void +MarkStringRange(JSTracer *trc, size_t len, JSString **vec, const char *name) { for (uint32 i = 0; i < len; i++) { - if (JSObject *obj = vec[i]) { - JS_SET_TRACING_INDEX(trc, name, i); - MarkRaw(trc, obj, JSTRACE_OBJECT); - } + if (JSString *str = vec[i]) + MarkString(trc, str, name); + } +} + +static inline void +MarkAtomRange(JSTracer *trc, size_t len, JSAtom **vec, const char *name) +{ + MarkStringRange(trc, len, reinterpret_cast(vec), name); +} + +static inline void +MarkObject(JSTracer *trc, JSObject *obj, const char *name) +{ + JS_SET_TRACING_NAME(trc, name); + MarkRaw(trc, obj, JSTRACE_OBJECT); +} + +static inline void +MarkObjectRange(JSTracer *trc, size_t len, JSObject **vec, const char *name) +{ + for (uint32 i = 0; i < len; i++) { + if (JSObject *obj = vec[i]) + MarkObject(trc, obj, name); } } @@ -517,29 +527,21 @@ MarkValueRange(JSTracer *trc, size_t len, Value *vec, const char *name) } static inline void -MarkBoxedWord(JSTracer *trc, jsboxedword w, const char *name) +MarkId(JSTracer *trc, jsid id, const char *name) { - if (JSBOXEDWORD_IS_GCTHING(w)) { - JS_SET_TRACING_NAME(trc, name); - MarkRaw(trc, JSBOXEDWORD_TO_GCTHING(w), JSBOXEDWORD_TRACE_KIND(w)); - } + MarkValue(trc, Valueify(id), name); } static inline void -MarkBoxedWordRange(JSTracer *trc, jsboxedword *beg, jsboxedword *end, const char *name) +MarkIdRange(JSTracer *trc, jsid *beg, jsid *end, const char *name) { - for (jsboxedword *wp = beg; wp < end; ++wp) { - if (JSBOXEDWORD_IS_GCTHING(*wp)) { - JS_SET_TRACING_INDEX(trc, name, wp - beg); - MarkRaw(trc, JSBOXEDWORD_TO_GCTHING(*wp), JSBOXEDWORD_TRACE_KIND(*wp)); - } - } + MarkValueRange(trc, Valueify(beg), Valueify(end), name); } -inline void -MarkBoxedWordRange(JSTracer *trc, size_t len, jsboxedword *vec, const char *name) +static inline void +MarkIdRange(JSTracer *trc, size_t len, jsid *vec, const char *name) { - MarkBoxedWordRange(trc, vec, vec + len, name); + MarkValueRange(trc, len, Valueify(vec), name); } /* N.B. Assumes JS_SET_TRACING_NAME/INDEX has already been called. */ diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 77591a637aa..4c9542e36cb 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -341,7 +341,7 @@ js_OnUnknownMethod(JSContext *cx, Value *vp) if (!js_IsFunctionQName(cx, obj, &id)) return false; if (id != 0) - vp[0] = IdToValue(id); + vp[0] = ID_TO_VALUE(id); } #endif obj = NewObjectWithGivenProto(cx, &js_NoSuchMethodClass, NULL, NULL); @@ -934,7 +934,7 @@ CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs, : isFunction ? js_function_str : js_var_str; - name = js_ValueToPrintableString(cx, IdToValue(id)); + name = js_ValueToPrintableString(cx, ID_TO_VALUE(id)); if (!name) return JS_FALSE; return !!JS_ReportErrorFlagsAndNumber(cx, report, @@ -1109,65 +1109,11 @@ InvokeConstructor(JSContext *cx, const InvokeArgsGuard &args, JSBool clampReturn return JS_TRUE; } -Value -BoxedWordToValue(jsboxedword w) -{ - if (JSBOXEDWORD_IS_STRING(w)) - return StringTag(JSBOXEDWORD_TO_STRING(w)); - if (JSBOXEDWORD_IS_INT(w)) - return Int32Tag(JSBOXEDWORD_TO_INT(w)); - if (JSBOXEDWORD_IS_DOUBLE(w)) - return DoubleTag(*JSBOXEDWORD_TO_DOUBLE(w)); - if (JSBOXEDWORD_IS_OBJECT(w)) - return ObjectOrNullTag(JSBOXEDWORD_TO_OBJECT(w)); - if (JSBOXEDWORD_IS_VOID(w)) - return UndefinedTag(); - return BooleanTag(!!JSBOXEDWORD_TO_BOOLEAN(w)); -} - -bool -ValueToBoxedWord(JSContext *cx, const Value &v, jsboxedword *wp) -{ - int32_t i; - if (v.isInt32() && - INT32_FITS_IN_JSID((i = v.asInt32()))) { - *wp = INT_TO_JSBOXEDWORD(i); - return true; - } - if (v.isString()) { - *wp = STRING_TO_JSBOXEDWORD(v.asString()); - return true; - } - if (v.isObjectOrNull()) { - *wp = OBJECT_TO_JSBOXEDWORD(v.asObjectOrNull()); - return true; - } - if (v.isBoolean()) { - *wp = BOOLEAN_TO_JSBOXEDWORD(v.asBoolean()); - return true; - } - if (v.isUndefined()) { - *wp = JSBOXEDWORD_VOID; - return true; - } - double *dp = js_NewWeaklyRootedDoubleAtom(cx, v.asNumber()); - if (!dp) - return false; - *wp = DOUBLE_TO_JSBOXEDWORD(dp); - return true; -} - -Value -IdToValue(jsid id) -{ - return BoxedWordToValue(id); -} - bool ValueToId(JSContext *cx, const Value &v, jsid *idp) { int32_t i; - if (ValueFitsInInt32(v, &i) && INT32_FITS_IN_JSID(i)) { + if (ValueFitsInInt32(v, &i)) { *idp = INT_TO_JSID(i); return true; } @@ -2011,21 +1957,14 @@ IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval) if (iterobj->getClass() == &js_IteratorClass.base) { NativeIterator *ni = (NativeIterator *) iterobj->getPrivate(); JS_ASSERT(ni->props_cursor < ni->props_end); - jsboxedword w = *ni->props_cursor; - if (JSBOXEDWORD_IS_STRING(w)) - rval->setString(JSBOXEDWORD_TO_STRING(w)); - else if (ni->flags & JSITER_FOREACH) - /* XXX: this begs for a for-each-specialized iterator: we are - * boxing going both directions! */ - *rval = BoxedWordToValue(*ni->props_cursor); - else - goto slow_path; - - ni->props_cursor++; - return true; + *rval = *ni->props_cursor; + if (rval->isString() || (ni->flags & JSITER_FOREACH)) { + ni->props_cursor++; + return true; + } + /* Take the slow path if we have to stringify a numeric property name. */ } - slow_path: - return !!js_IteratorNext(cx, iterobj, rval); + return js_IteratorNext(cx, iterobj, rval); } @@ -2198,6 +2137,9 @@ Interpret(JSContext *cx) #define LOAD_FUNCTION(PCOFF) \ (fun = script->getFunction(GET_FULL_INDEX(PCOFF))) +#define LOAD_DOUBLE(PCOFF, dbl) \ + (dbl = script->getConst(GET_FULL_INDEX(PCOFF)).asDouble()) + #ifdef JS_TRACER #ifdef MOZ_TRACEVIS diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index 2d6af15b766..9b09293bd28 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -392,15 +392,6 @@ GetInstancePrivate(JSContext *cx, JSObject *obj, Class *clasp, Value *argv) return obj->getPrivate(); } -extern Value -BoxedWordToValue(jsboxedword w); - -extern bool -ValueToBoxedWord(JSContext *cx, const Value &v, jsboxedword *w); - -extern Value -IdToValue(jsid id); - extern bool ValueToId(JSContext *cx, const Value &v, jsid *idp); diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 46178ce74be..57e9c588aeb 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -103,7 +103,7 @@ ExtendedClass js_IteratorClass = { void NativeIterator::mark(JSTracer *trc) { - MarkBoxedWordRange(trc, props_array, props_end, "props"); + MarkValueRange(trc, props_array, props_end, "props"); } /* @@ -133,23 +133,22 @@ iterator_trace(JSTracer *trc, JSObject *obj) } static inline bool -NewKeyValuePair(JSContext *cx, const Value &key, const Value &val, jsboxedword *wp) +NewKeyValuePair(JSContext *cx, jsid key, const Value &val, Value *rval) { - Value vec[2]; - vec[0] = key; - vec[1] = val; + Value vec[2] = { ID_TO_VALUE(key), val }; AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(vec), vec); JSObject *aobj = js_NewArrayObject(cx, 2, vec); if (!aobj) return false; - *wp = OBJECT_TO_JSBOXEDWORD(aobj); + rval->setNonFunObj(*aobj); return true; } static inline bool -Enumerate(JSContext *cx, JSObject *obj, jsid id, bool enumerable, uintN flags, - Value *tmpRoot, HashSet& ht, AutoBoxedWordVector& vec) +Enumerate(JSContext *cx, JSObject *obj, jsid id, + bool enumerable, uintN flags, HashSet& ht, + AutoValueVector& vec) { JS_ASSERT(JSID_IS_INT(id) || JSID_IS_ATOM(id)); @@ -159,48 +158,38 @@ Enumerate(JSContext *cx, JSObject *obj, jsid id, bool enumerable, uintN flags, if (JS_UNLIKELY(!!p)) return true; /* no need to add properties to the hash table at the end of the prototype chain */ - if (obj->getProto() && !ht.add(p, id)) { - JS_ReportOutOfMemory(cx); + if (obj->getProto() && !ht.add(p, id)) return false; - } } if (enumerable) { - if (!vec.append(id)) { - JS_ReportOutOfMemory(cx); + if (!vec.append(ID_TO_VALUE(id))) return false; - } if (flags & JSITER_FOREACH) { - jsboxedword *wp = vec.end() - 1; - if (!obj->getProperty(cx, id, tmpRoot)) + Value *vp = vec.end() - 1; + + if (!obj->getProperty(cx, id, vp)) + return false; + if ((flags & JSITER_KEYVALUE) && !NewKeyValuePair(cx, id, *vp, vp)) return false; - if (flags & JSITER_KEYVALUE) { - if (!NewKeyValuePair(cx, IdToValue(id), *tmpRoot, wp)) - return false; - } else { - /* XXX: this begs for a for-each-specialized iterator: we are - * boxing going both directions! */ - if (!ValueToBoxedWord(cx, *tmpRoot, wp)) - return false; - } } } return true; } static bool -EnumerateNativeProperties(JSContext *cx, JSObject *obj, uintN flags, Value *tmpRoot, - HashSet &ht, AutoBoxedWordVector& props) +EnumerateNativeProperties(JSContext *cx, JSObject *obj, uintN flags, + HashSet &ht, AutoValueVector& props) { - AutoBoxedWordVector sprops(cx); + AutoValueVector sprops(cx); JS_LOCK_OBJ(cx, obj); /* Collect all unique properties from this object's scope. */ JSScope *scope = obj->scope(); for (JSScopeProperty *sprop = scope->lastProperty(); sprop; sprop = sprop->parent) { - if (sprop->id != JSBOXEDWORD_VOID && + if (sprop->id != JSVAL_VOID && !sprop->isAlias() && - !Enumerate(cx, obj, sprop->id, sprop->enumerable(), flags, tmpRoot, ht, sprops)) { + !Enumerate(cx, obj, sprop->id, sprop->enumerable(), flags, ht, sprops)) { return false; } } @@ -219,8 +208,8 @@ EnumerateNativeProperties(JSContext *cx, JSObject *obj, uintN flags, Value *tmpR } static bool -EnumerateDenseArrayProperties(JSContext *cx, JSObject *obj, uintN flags, Value *tmpRoot, - HashSet &ht, AutoBoxedWordVector& props) +EnumerateDenseArrayProperties(JSContext *cx, JSObject *obj, uintN flags, + HashSet &ht, AutoValueVector& props) { size_t count = obj->getDenseArrayCount(); @@ -230,7 +219,7 @@ EnumerateDenseArrayProperties(JSContext *cx, JSObject *obj, uintN flags, Value * for (size_t i = 0; i < capacity; ++i, ++vp) { if (!vp->isMagic(JS_ARRAY_HOLE)) { /* Dense arrays never get so large that i would not fit into an integer id. */ - if (!Enumerate(cx, obj, INT_TO_JSID(i), true, flags, tmpRoot, ht, props)) + if (!Enumerate(cx, obj, INT_TO_JSID(i), true, flags, ht, props)) return false; } } @@ -248,8 +237,7 @@ InitNativeIterator(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarray, ui return false; } - AutoBoxedWordVector props(cx); - AutoValueRooter avr(cx); + AutoValueVector props(cx); while (obj) { Class *clasp = obj->getClass(); @@ -258,17 +246,17 @@ InitNativeIterator(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarray, ui !(clasp->flags & JSCLASS_NEW_ENUMERATE)) { if (!clasp->enumerate(cx, obj)) return false; - if (!EnumerateNativeProperties(cx, obj, flags, avr.addr(), ht, props)) + if (!EnumerateNativeProperties(cx, obj, flags, ht, props)) return false; } else if (obj->isDenseArray()) { - if (!EnumerateDenseArrayProperties(cx, obj, flags, avr.addr(), ht, props)) + if (!EnumerateDenseArrayProperties(cx, obj, flags, ht, props)) return false; } else { Value state; if (!obj->enumerate(cx, JSENUMERATE_INIT, &state, NULL)) return false; if (state.isMagic(JS_NATIVE_ENUMERATE)) { - if (!EnumerateNativeProperties(cx, obj, flags, avr.addr(), ht, props)) + if (!EnumerateNativeProperties(cx, obj, flags, ht, props)) return false; } else { while (true) { @@ -277,7 +265,7 @@ InitNativeIterator(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarray, ui return false; if (state.isNull()) break; - if (!Enumerate(cx, obj, id, true, flags, avr.addr(), ht, props)) + if (!Enumerate(cx, obj, id, true, flags, ht, props)) return false; } } @@ -292,15 +280,13 @@ InitNativeIterator(JSContext *cx, JSObject *obj, uintN flags, uint32 *sarray, ui size_t plength = props.length(); NativeIterator *ni = (NativeIterator *) - cx->malloc(sizeof(NativeIterator) + plength * sizeof(jsboxedword) + slength * sizeof(uint32)); - if (!ni) { - JS_ReportOutOfMemory(cx); + cx->malloc(sizeof(NativeIterator) + plength * sizeof(Value) + slength * sizeof(uint32)); + if (!ni) return false; - } - ni->props_array = ni->props_cursor = (jsboxedword *) (ni + 1); + ni->props_array = ni->props_cursor = (Value *) (ni + 1); ni->props_end = ni->props_array + plength; if (plength) - memcpy(ni->props_array, props.begin(), plength * sizeof(jsboxedword)); + memcpy(ni->props_array, props.begin(), plength * sizeof(Value)); ni->shapes_array = (uint32 *) ni->props_end; ni->shapes_length = slength; ni->shapes_key = key; @@ -322,12 +308,12 @@ EnumerateOwnProperties(JSContext *cx, JSObject *obj, JSIdArray **idap) /* Morph the NativeIterator into a JSIdArray. The caller will deallocate it. */ JS_ASSERT(sizeof(NativeIterator) > sizeof(JSIdArray)); - JS_ASSERT(ni->props_array == (jsboxedword *) (ni + 1)); + JS_ASSERT(ni->props_array == (Value *) (ni + 1)); size_t length = size_t(ni->props_end - ni->props_array); JSIdArray *ida = (JSIdArray *) (uintptr_t(ni->props_array) - (sizeof(JSIdArray) - sizeof(jsid))); ida->self = ni; ida->length = length; - JS_ASSERT(&ida->vector[0] == &ni->props_array[0]); + JS_ASSERT(&ida->vector[0] == (jsid *)&ni->props_array[0]); *idap = ida; return true; } @@ -653,19 +639,10 @@ js_IteratorNext(JSContext *cx, JSObject *iterobj, Value *rval) */ NativeIterator *ni = iterobj->getNativeIterator(); JS_ASSERT(ni->props_cursor < ni->props_end); + *rval = *ni->props_cursor++; - /* Stringifying of array indices is a common case. */ - jsboxedword w = *ni->props_cursor++; - if (JSBOXEDWORD_IS_INT(w)) { - rval->setInt32(JSBOXEDWORD_TO_INT(w)); - } else if (JSBOXEDWORD_IS_STRING(w)) { - rval->setString(JSBOXEDWORD_TO_STRING(w)); + if (rval->isString() || (ni->flags & JSITER_FOREACH)) return true; - } else { - *rval = BoxedWordToValue(w); - if (ni->flags & JSITER_FOREACH) - return true; - } JSString *str; jsint i; diff --git a/js/src/jsiter.h b/js/src/jsiter.h index 143bfcef448..cb6366e07db 100644 --- a/js/src/jsiter.h +++ b/js/src/jsiter.h @@ -58,9 +58,9 @@ #define JSITER_OWNONLY 0x8 /* iterate over obj's own properties only */ struct NativeIterator { - jsboxedword *props_array; - jsboxedword *props_cursor; - jsboxedword *props_end; + js::Value *props_array; + js::Value *props_cursor; + js::Value *props_end; uint32 *shapes_array; uint32 shapes_length; uint32 shapes_key; diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index de5dc210702..52b5c3dd601 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -277,7 +277,7 @@ js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj, static JSHashNumber js_hash_object(const void *key) { - return JSHashNumber(uintptr_t(key) >> JSBOXEDWORD_TAGBITS); + return JSHashNumber(uintptr_t(key) >> JS_GCTHING_ALIGN); } static JSHashEntry * @@ -657,7 +657,7 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp) * Convert id to a value and then to a string. Decide early whether we * prefer get/set or old getter/setter syntax. */ - idstr = js_ValueToString(cx, IdToValue(id)); + idstr = js_ValueToString(cx, ID_TO_VALUE(id)); if (!idstr) { ok = JS_FALSE; obj2->dropProperty(cx, prop); @@ -1430,7 +1430,7 @@ obj_watch_handler(JSContext *cx, JSObject *obj, jsid id, jsval old, return JS_TRUE; generation = cx->resolvingTable->generation; - argv[0] = IdToValue(id); + argv[0] = ID_TO_VALUE(id); argv[1] = Valueify(old); argv[2] = Valueify(*nvp); ok = InternalCall(cx, obj, ObjectOrNullTag(callable), 3, argv, Valueify(nvp)); @@ -1911,7 +1911,7 @@ obj_keys(JSContext *cx, uintN argc, Value *vp) * to by a QName, actually appears as a string jsid -- but in the * interests of fidelity we pass object jsids through unchanged. */ - aobj->setDenseArrayElement(i, IdToValue(id)); + aobj->setDenseArrayElement(i, ID_TO_VALUE(id)); } } @@ -2047,7 +2047,7 @@ Reject(JSContext *cx, uintN errorNumber, bool throwError, jsid id, bool *rval) { if (throwError) { jsid idstr; - if (!js_ValueToStringId(cx, IdToValue(id), &idstr)) + if (!js_ValueToStringId(cx, ID_TO_VALUE(id), &idstr)) return JS_FALSE; JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, errorNumber, JS_GetStringBytes(JSID_TO_STRING(idstr))); @@ -2117,8 +2117,8 @@ DefinePropertyOnObject(JSContext *cx, JSObject *obj, const PropertyDescriptor &d if (!js_CheckAccess(cx, obj, desc.id, JSACC_WATCH, &dummy, &dummyAttrs)) return JS_FALSE; - Value undef = undefinedValue(); - return js_DefineProperty(cx, obj, desc.id, &undef, + Value tmp = UndefinedTag(); + return js_DefineProperty(cx, obj, desc.id, &tmp, desc.getter(), desc.setter(), desc.attrs); } @@ -3899,8 +3899,8 @@ js_CheckForStringIndex(jsid id) if (cp != end || (negative && index == 0)) return id; - if (oldIndex < JSBOXEDWORD_INT_MAX / 10 || - (oldIndex == JSBOXEDWORD_INT_MAX / 10 && c <= (JSBOXEDWORD_INT_MAX % 10))) { + if (oldIndex < JSVAL_INT_MAX / 10 || + (oldIndex == JSVAL_INT_MAX / 10 && c <= (JSVAL_INT_MAX % 10))) { if (negative) index = 0 - index; id = INT_TO_JSID((jsint)index); @@ -4745,7 +4745,7 @@ js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN getHow, /* Ok, bad undefined property reference: whine about it. */ if (!js_ReportValueErrorFlags(cx, flags, JSMSG_UNDEFINED_PROP, - JSDVG_IGNORE_STACK, IdToValue(id), + JSDVG_IGNORE_STACK, ID_TO_VALUE(id), NULL, NULL, NULL)) { return JS_FALSE; } @@ -4823,7 +4823,7 @@ JSBool ReportReadOnly(JSContext* cx, jsid id, uintN flags) { return js_ReportValueErrorFlags(cx, flags, JSMSG_READ_ONLY, - JSDVG_IGNORE_STACK, IdToValue(id), NULL, + JSDVG_IGNORE_STACK, ID_TO_VALUE(id), NULL, NULL, NULL); } @@ -5534,11 +5534,11 @@ js_Construct(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval) } JSBool -js_HasInstance(JSContext *cx, JSObject *obj, const Value *vp, JSBool *bp) +js_HasInstance(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp) { Class *clasp = obj->getClass(); if (clasp->hasInstance) - return clasp->hasInstance(cx, obj, vp, bp); + return clasp->hasInstance(cx, obj, v, bp); #ifdef NARCISSUS { jsval fval, rval; @@ -6233,8 +6233,6 @@ JS_FRIEND_API(void) DumpAtom(JSAtom *atom) { fprintf(stderr, "JSAtom* (%p) = ", (void *) atom); - if (!JSBOXEDWORD_IS_STRING(ATOM_KEY(atom))) - fprintf(stderr, "\n"); DumpString(ATOM_TO_STRING(atom)); } @@ -6300,7 +6298,7 @@ JS_FRIEND_API(void) DumpId(jsid id) { fprintf(stderr, "jsid %p = ", (void *) id); - dumpValue(IdToValue(id)); + dumpValue(ID_TO_VALUE(id)); fputc('\n', stderr); } diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 82b41fde518..1437f354d6a 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -672,6 +672,8 @@ struct JSObject { inline void initArrayClass(); }; +JS_STATIC_ASSERT(sizeof(JSObject) % JS_GCTHING_ALIGN == 0); + #define JSSLOT_START(clasp) (((clasp)->flags & JSCLASS_HAS_PRIVATE) \ ? JSSLOT_PRIVATE + 1 \ : JSSLOT_PRIVATE) diff --git a/js/src/json.cpp b/js/src/json.cpp index 517bda663ee..65cb514abb4 100644 --- a/js/src/json.cpp +++ b/js/src/json.cpp @@ -285,7 +285,7 @@ JO(JSContext *cx, jsval *vp, StringifyContext *scx) outputValue = JSVAL_VOID; if (!usingWhitelist) { - if (!js_ValueToStringId(cx, IdToValue(ida[i]), &id)) + if (!js_ValueToStringId(cx, ID_TO_VALUE(ida[i]), &id)) return JS_FALSE; } else { // skip non-index properties @@ -331,7 +331,7 @@ JO(JSContext *cx, jsval *vp, StringifyContext *scx) return JS_FALSE; // Be careful below, this string is weakly rooted - JSString *s = js_ValueToString(cx, IdToValue(id)); + JSString *s = js_ValueToString(cx, ID_TO_VALUE(id)); if (!s) return JS_FALSE; @@ -402,7 +402,7 @@ static JSBool CallReplacerFunction(JSContext *cx, jsid id, JSObject *holder, StringifyContext *scx, jsval *vp) { if (scx->replacer && scx->replacer->isCallable()) { - jsval vec[2] = { Jsvalify(IdToValue(id)), *vp}; + jsval vec[2] = { ID_TO_JSVAL(id), *vp}; if (!JS_CallFunctionValue(cx, holder, OBJECT_TO_JSVAL(scx->replacer), 2, vec, vp)) return JS_FALSE; } @@ -596,7 +596,7 @@ Walk(JSContext *cx, jsid id, JSObject *holder, jsval reviver, jsval *vp) // return reviver.call(holder, key, value); jsval value = *vp; - JSString *key = js_ValueToString(cx, IdToValue(id)); + JSString *key = js_ValueToString(cx, ID_TO_VALUE(id)); if (!key) return false; @@ -1188,7 +1188,7 @@ js_ConsumeJSONText(JSContext *cx, JSONParser *jp, const jschar *data, uint32 len static JSBool json_toSource(JSContext *cx, uintN argc, jsval *vp) { - *vp = ATOM_TO_JSVAL(CLASS_ATOM(cx, JSON)); + *vp = STRING_TO_JSVAL(ATOM_TO_STRING(CLASS_ATOM(cx, JSON))); return JS_TRUE; } #endif diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index 292a6257bb0..96b3bf4faed 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -132,16 +132,6 @@ const char *js_CodeName[] = { /************************************************************************/ -// Convert an atom to a double, also allowing the possibility that the -// atom is a double, which the standard ATOM_TO_JSVAL API does not. -static jsval -ExtAtomToJsval(const JSAtom *atom) -{ - return ATOM_IS_DOUBLE(atom) - ? DOUBLE_TO_JSVAL(*ATOM_TO_DOUBLE(atom)) - : ATOM_TO_JSVAL(atom); -} - static ptrdiff_t GetJumpOffset(jsbytecode *pc, jsbytecode *pc2) { @@ -382,7 +372,7 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, index = js_GetIndexFromBytecode(cx, script, pc, 0); if (type == JOF_ATOM) { JS_GET_SCRIPT_ATOM(script, pc, index, atom); - v = ExtAtomToJsval(atom); + v = ATOM_TO_JSVAL(atom); } else { if (type == JOF_OBJECT) obj = script->getObject(index); @@ -450,7 +440,7 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, off = GetJumpOffset(pc, pc2); pc2 += jmplen; - bytes = ToDisassemblySource(cx, ExtAtomToJsval(atom)); + bytes = ToDisassemblySource(cx, ATOM_TO_JSVAL(atom)); if (!bytes) return 0; fprintf(fp, "\n\t%s: %d", bytes, (intN) off); @@ -474,7 +464,7 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, index = js_GetIndexFromBytecode(cx, script, pc, SLOTNO_LEN); if (type == JOF_SLOTATOM) { JS_GET_SCRIPT_ATOM(script, pc, index, atom); - v = ExtAtomToJsval(atom); + v = ATOM_TO_JSVAL(atom); } else { obj = script->getObject(index); v = OBJECT_TO_JSVAL(obj); @@ -1568,8 +1558,7 @@ DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc) case JSOP_INT32: d = i = GET_INT32(pc); goto do_getelem; case JSOP_DOUBLE: - GET_DOUBLE_FROM_BYTECODE(jp->script, pc, 0, atom); - d = *ATOM_TO_DOUBLE(atom); + GET_DOUBLE_FROM_BYTECODE(jp->script, pc, 0, d); LOCAL_ASSERT(JSDOUBLE_IS_FINITE(d) && !JSDOUBLE_IS_NEGZERO(d)); i = (jsint)d; @@ -3867,7 +3856,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) do_getarg_prop: atom = GetArgOrVarAtom(ss->printer, i); LOCAL_ASSERT(atom); - LOCAL_ASSERT(ATOM_IS_STRING(atom)); lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0); if (!lval || !PushOff(ss, STR2OFF(&ss->sprinter, lval), op)) return NULL; @@ -4027,11 +4015,13 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) break; case JSOP_DOUBLE: - GET_DOUBLE_FROM_BYTECODE(jp->script, pc, 0, atom); - val = DOUBLE_TO_JSVAL(*ATOM_TO_DOUBLE(atom)); - LOCAL_ASSERT(JSVAL_IS_DOUBLE(val)); + { + double d; + GET_DOUBLE_FROM_BYTECODE(jp->script, pc, 0, d); + val = DOUBLE_TO_JSVAL(d); todo = SprintDoubleValue(&ss->sprinter, val, &saveop); break; + } case JSOP_STRING: LOAD_ATOM(0); @@ -4314,7 +4304,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) pc2 += INDEX_LEN; off2 = GetJumpOffset(pc, pc2); pc2 += jmplen; - table[k].key = ExtAtomToJsval(atom); + table[k].key = ATOM_TO_JSVAL(atom); table[k].offset = off2; } diff --git a/js/src/jsopcode.h b/js/src/jsopcode.h index 194dc70403b..3e6dddf248c 100644 --- a/js/src/jsopcode.h +++ b/js/src/jsopcode.h @@ -334,12 +334,11 @@ js_GetIndexFromBytecode(JSContext *cx, JSScript *script, jsbytecode *pc, * See the assertions in the JSOP_DOUBLE and JSOP_LOOKUPSWTICH* opcode cases in * jsops.cpp. */ -#define GET_DOUBLE_FROM_BYTECODE(script, pc, pcoff, atom) \ +#define GET_DOUBLE_FROM_BYTECODE(script, pc, pcoff, dbl) \ JS_BEGIN_MACRO \ uintN index_ = js_GetIndexFromBytecode(cx, (script), (pc), (pcoff)); \ - JS_ASSERT(index_ < (script)->atomMap.length); \ - (atom) = (script)->atomMap.vector[index_]; \ - JS_ASSERT(ATOM_IS_DOUBLE(atom)); \ + JS_ASSERT(index_ < (script)->consts()->length); \ + (dbl) = (script)->getConst(index_).asDouble(); \ JS_END_MACRO #define GET_OBJECT_FROM_BYTECODE(script, pc, pcoff, obj) \ diff --git a/js/src/jsops.cpp b/js/src/jsops.cpp index af3627ef6f3..cdbdca649ca 100644 --- a/js/src/jsops.cpp +++ b/js/src/jsops.cpp @@ -441,9 +441,9 @@ END_CASE(JSOP_ANDX) #define FETCH_ELEMENT_ID(obj, n, id) \ JS_BEGIN_MACRO \ const Value &idval_ = regs.sp[n]; \ - int32_t i; \ - if (ValueFitsInInt32(idval_, &i) && INT32_FITS_IN_JSID(i)) { \ - id = INT_TO_JSID(i); \ + int32_t i_; \ + if (ValueFitsInInt32(idval_, &i_)) { \ + id = INT_TO_JSID(i_); \ } else { \ if (!js_InternNonIntElementId(cx, obj, idval_, &id, ®s.sp[n])) \ goto error; \ @@ -458,10 +458,10 @@ END_CASE(JSOP_ANDX) regs.sp -= spdec; \ if (cond == (diff_ != 0)) { \ ++regs.pc; \ - len = GET_JUMP_OFFSET(regs.pc); \ + len = GET_JUMP_OFFSET(regs.pc); \ BRANCH(len); \ } \ - len = 1 + JSOP_IFEQ_LENGTH; \ + len = 1 + JSOP_IFEQ_LENGTH; \ DO_NEXT_OP(len); \ } \ JS_END_MACRO @@ -826,7 +826,7 @@ END_CASE(JSOP_BITAND) #define EXTENDED_EQUALITY_OP(OP) \ if (((clasp = l->getClass())->flags & JSCLASS_IS_EXTENDED) && \ ((ExtendedClass *)clasp)->equality) { \ - if (!((ExtendedClass *)clasp)->equality(cx, l, &lval, &cond)) \ + if (!((ExtendedClass *)clasp)->equality(cx, l, &rval, &cond)) \ goto error; \ cond = cond OP JS_TRUE; \ } else @@ -1049,7 +1049,6 @@ BEGIN_CASE(JSOP_ADD) #if JS_HAS_XML_SUPPORT if (lval.isNonFunObj() && lval.asObject().isXML() && rval.isNonFunObj() && rval.asObject().isXML()) { - Value rval; if (!js_ConcatenateXML(cx, &lval.asObject(), &rval.asObject(), &rval)) goto error; regs.sp--; @@ -2074,13 +2073,8 @@ BEGIN_CASE(JSOP_GETELEM) copyFrom = ®s.sp[-1]; } } - int32_t i32 = rref.asInt32(); - if (INT32_FITS_IN_JSID(i32)) - id = INT_TO_JSID(i32); - else - goto intern_big_int; + id = INT_TO_JSID(rref.asInt32()); } else { - intern_big_int: if (!js_InternNonIntElementId(cx, obj, rref, &id)) goto error; } @@ -2504,10 +2498,10 @@ END_CASE(JSOP_RESETBASE) BEGIN_CASE(JSOP_DOUBLE) { JS_ASSERT(!fp->imacpc); - JS_ASSERT(size_t(atoms - script->atomMap.vector) < script->atomMap.length); - JSAtom *atom; - LOAD_ATOM(0, atom); - PUSH_DOUBLE(*ATOM_TO_DOUBLE(atom)); + JS_ASSERT(size_t(atoms - script->atomMap.vector) <= script->atomMap.length); + double dbl; + LOAD_DOUBLE(0, dbl); + PUSH_DOUBLE(dbl); } END_CASE(JSOP_DOUBLE) @@ -2681,9 +2675,8 @@ BEGIN_CASE(JSOP_LOOKUPSWITCH) bool match; #define SEARCH_PAIRS(MATCH_CODE) \ for (;;) { \ - JS_ASSERT(GET_INDEX(pc2) < script->atomMap.length); \ - JSAtom *atom = atoms[GET_INDEX(pc2)]; \ - jsboxedword rval = ATOM_KEY(atom); \ + JS_ASSERT(GET_INDEX(pc2) < script->consts()->length); \ + Value rval = script->consts()->vector[GET_INDEX(pc2)]; \ MATCH_CODE \ pc2 += INDEX_LEN; \ if (match) \ @@ -2699,25 +2692,18 @@ BEGIN_CASE(JSOP_LOOKUPSWITCH) JSString *str = lval.asString(); JSString *str2; SEARCH_PAIRS( - match = (JSBOXEDWORD_IS_STRING(rval) && - ((str2 = JSBOXEDWORD_TO_STRING(rval)) == str || + match = (rval.isString() && + ((str2 = rval.asString()) == str || js_EqualStrings(str2, str))); ) } else if (lval.isNumber()) { - double dbl = lval.asNumber(); + double ldbl = lval.asNumber(); SEARCH_PAIRS( - match = (JSBOXEDWORD_IS_INT(rval) && dbl == (double)JSBOXEDWORD_TO_INT(rval)) || - (JSBOXEDWORD_IS_DOUBLE(rval) && dbl == *JSBOXEDWORD_TO_DOUBLE(rval)); - ) - } else if (lval.isUndefined() || lval.isBoolean()) { - jsint s = lval.isUndefined() ? 2 : lval.asBoolean(); - SEARCH_PAIRS( - match = JSBOXEDWORD_IS_SPECIAL(rval) && JSBOXEDWORD_TO_SPECIAL(rval) == s; + match = rval.isNumber() && ldbl == rval.asNumber(); ) } else { - JS_ASSERT(lval.isNull()); SEARCH_PAIRS( - match = JSBOXEDWORD_IS_NULL(rval); + match = (lval == rval); ) } #undef SEARCH_PAIRS @@ -3990,7 +3976,7 @@ BEGIN_CASE(JSOP_ANYNAME) jsid id; if (!js_GetAnyName(cx, &id)) goto error; - PUSH_COPY(IdToValue(id)); + PUSH_COPY(ID_TO_VALUE(id)); } END_CASE(JSOP_ANYNAME) @@ -4076,7 +4062,7 @@ BEGIN_CASE(JSOP_BINDXMLNAME) if (!js_FindXMLProperty(cx, lval, &obj, &id)) goto error; regs.sp[-1].setObjectOrNull(obj); - PUSH_COPY(IdToValue(id)); + PUSH_COPY(ID_TO_VALUE(id)); } END_CASE(JSOP_BINDXMLNAME) diff --git a/js/src/jsparse.cpp b/js/src/jsparse.cpp index fee724cc13c..a4e24176a4f 100644 --- a/js/src/jsparse.cpp +++ b/js/src/jsparse.cpp @@ -90,6 +90,8 @@ #include "jsdhash.h" #endif +#include "jsatominlines.h" + using namespace js; /* @@ -4094,7 +4096,7 @@ CloneParseTree(JSParseNode *opn, JSTreeContext *tc) NULLCHECK(pn->pn_right = CloneParseTree(opn->pn_right, tc)); else pn->pn_right = pn->pn_left; - pn->pn_val = opn->pn_val; + pn->pn_pval = opn->pn_pval; pn->pn_iflags = opn->pn_iflags; break; @@ -7984,8 +7986,11 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot) return NULL; pn3->pn_dval = tokenStream.currentToken().t_dval; if (tc->needStrictChecks()) { - atom = js_AtomizeDouble(context, pn3->pn_dval); - if (!atom) + /* + * Use string-valued atoms for detecting duplicate + * properties so that 1 and "1" properly collide. + */ + if (!js_ValueToAtom(context, DoubleTag(pn3->pn_dval), &atom)) return NULL; } else { atom = NULL; /* for the compiler */ @@ -8013,8 +8018,11 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot) return NULL; pn3->pn_dval = tokenStream.currentToken().t_dval; if (tc->needStrictChecks()) { - atom = js_AtomizeDouble(context, pn3->pn_dval); - if (!atom) + /* + * Use string-valued atoms for detecting duplicate + * properties so that 1 and "1" properly collide. + */ + if (!js_ValueToAtom(context, DoubleTag(pn3->pn_dval), &atom)) return NULL; } else { atom = NULL; /* for the compiler */ @@ -8098,19 +8106,6 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot) attributesMask = 0; } - /* - * Use only string-valued atoms for detecting duplicate - * properties so that 1 and "1" properly collide. - */ - if (ATOM_IS_DOUBLE(atom)) { - JSString *str = js_NumberToString(context, pn3->pn_dval); - if (!str) - return JS_FALSE; - atom = js_AtomizeString(context, str, 0); - if (!atom) - return JS_FALSE; - } - JSAtomListElement *ale = seen.lookup(atom); if (ale) { if (ALE_INDEX(ale) & attributesMask) { diff --git a/js/src/jsparse.h b/js/src/jsparse.h index c5fd9bc7de2..ceb2840ab26 100644 --- a/js/src/jsparse.h +++ b/js/src/jsparse.h @@ -320,7 +320,7 @@ struct JSParseNode { struct { /* two kids if binary */ JSParseNode *left; JSParseNode *right; - jsboxedword val; /* switch case value */ + js::Value *pval; /* switch case value */ uintN iflags; /* JSITER_* flags for TOK_FOR node */ } binary; struct { /* one kid if unary */ @@ -372,7 +372,7 @@ struct JSParseNode { #define pn_kid3 pn_u.ternary.kid3 #define pn_left pn_u.binary.left #define pn_right pn_u.binary.right -#define pn_val pn_u.binary.val +#define pn_pval pn_u.binary.pval #define pn_iflags pn_u.binary.iflags #define pn_kid pn_u.unary.kid #define pn_num pn_u.unary.num diff --git a/js/src/jspropertytree.cpp b/js/src/jspropertytree.cpp index a7910b2f926..65806b66448 100644 --- a/js/src/jspropertytree.cpp +++ b/js/src/jspropertytree.cpp @@ -234,8 +234,8 @@ PropertyTree::insertChild(JSContext *cx, JSScopeProperty *parent, { JS_ASSERT(parent); JS_ASSERT(!child->parent); - JS_ASSERT(!JSBOXEDWORD_IS_NULL(parent->id)); - JS_ASSERT(!JSBOXEDWORD_IS_NULL(child->id)); + JS_ASSERT(!JSVAL_IS_NULL(parent->id)); + JS_ASSERT(!JSVAL_IS_NULL(child->id)); JSScopeProperty **childp = &parent->kids; if (JSScopeProperty *kids = *childp) { @@ -331,7 +331,7 @@ PropertyTree::removeChild(JSContext *cx, JSScopeProperty *child) JSScopeProperty *parent = child->parent; JS_ASSERT(parent); - JS_ASSERT(!JSBOXEDWORD_IS_NULL(parent->id)); + JS_ASSERT(!JSVAL_IS_NULL(parent->id)); JSScopeProperty *kids = parent->kids; if (!KIDS_IS_CHUNKY(kids)) { @@ -468,7 +468,7 @@ PropertyTree::getChild(JSContext *cx, JSScopeProperty *parent, uint32 shape, if (sprop) goto out; } else { - JS_ASSERT(!JSBOXEDWORD_IS_NULL(parent->id)); + JS_ASSERT(!JSVAL_IS_NULL(parent->id)); /* * Because chunks are appended at the end and never deleted except by @@ -616,7 +616,7 @@ js_MeterPropertyTree(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, void JSScopeProperty::dump(JSContext *cx, FILE *fp) { - JS_ASSERT(!JSBOXEDWORD_IS_NULL(id)); + JS_ASSERT(!JSVAL_IS_NULL(id)); if (JSID_IS_INT(id)) { fprintf(fp, "[%ld]", (long) JSID_TO_INT(id)); @@ -626,7 +626,7 @@ JSScopeProperty::dump(JSContext *cx, FILE *fp) str = JSID_TO_STRING(id); } else { JS_ASSERT(JSID_IS_OBJECT(id)); - str = js_ValueToString(cx, IdToValue(id)); + str = js_ValueToString(cx, ID_TO_VALUE(id)); fputs("object ", fp); } if (!str) @@ -724,7 +724,7 @@ OrphanNodeKids(JSContext *cx, JSScopeProperty *sprop) if (!kid) break; - if (!JSBOXEDWORD_IS_NULL(kid->id)) { + if (!JSVAL_IS_NULL(kid->id)) { JS_ASSERT(kid->parent == sprop); kid->parent = NULL; } @@ -733,7 +733,7 @@ OrphanNodeKids(JSContext *cx, JSScopeProperty *sprop) } else { JSScopeProperty *kid = kids; - if (!JSBOXEDWORD_IS_NULL(kid->id)) { + if (!JSVAL_IS_NULL(kid->id)) { JS_ASSERT(kid->parent == sprop); kid->parent = NULL; } @@ -856,7 +856,7 @@ js::SweepScopeProperties(JSContext *cx) for (JSScopeProperty *sprop = (JSScopeProperty *) a->base; sprop < limit; sprop++) { /* If the id is null, sprop is already on the freelist. */ - if (JSBOXEDWORD_IS_NULL(sprop->id)) + if (JSVAL_IS_NULL(sprop->id)) continue; /* diff --git a/js/src/jsprvtd.h b/js/src/jsprvtd.h index 9b444b60d3d..1a087a795dc 100644 --- a/js/src/jsprvtd.h +++ b/js/src/jsprvtd.h @@ -57,12 +57,36 @@ #include "jspubtd.h" #include "jsutil.h" +/* Internal identifier (jsid) macros. */ + +#define JSID_IS_ATOM(id) JSVAL_IS_STRING((jsval)(id)) +#define JSID_TO_ATOM(id) ((JSAtom *)JSVAL_TO_STRING((jsval)(id))) +#define JSID_TO_STRING(id) ATOM_TO_STRING(JSID_TO_ATOM(id)) +#define ATOM_TO_JSID(atom) ((jsid)STRING_TO_JSVAL((JSString *)atom)) + +#define JSID_IS_INT(id) JSVAL_IS_INT((jsval)(id)) +#define JSID_TO_INT(id) JSVAL_TO_INT((jsval)(id)) +#define INT_TO_JSID(i) ((jsid)INT_TO_JSVAL(i)) +#define INT_JSVAL_TO_JSID(v) ((jsid)(v)) +#define INT_JSID_TO_JSVAL(id) ((jsval)(id)) + +#define JSID_IS_OBJECT(id) JSVAL_IS_OBJECT((jsval)(id)) +#define JSID_TO_OBJECT(id) JSVAL_TO_OBJECT((jsval)(id)) +#define OBJECT_TO_JSID(obj) ((jsid)OBJECT_TO_JSVAL(obj)) +#define OBJECT_JSVAL_TO_JSID(v) ((jsid)v) + +#define ID_TO_VALUE(id) (Valueify(id)) +#define ID_TO_JSVAL(id) ((jsval)(id)) + /* * Convenience constants. */ #define JS_BITS_PER_UINT32_LOG2 5 #define JS_BITS_PER_UINT32 32 +/* The alignment required of objects stored in GC arenas. */ +const uintN JS_GCTHING_ALIGN = 8; + /* Scalar typedefs. */ typedef uint8 jsbytecode; typedef uint8 jssrcnote; diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h index d7d3b4ca3c7..536c0ff01ee 100644 --- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -238,6 +238,7 @@ JSValueMask32; #endif typedef VALUE_ALIGNMENT uint64 jsval; +typedef VALUE_ALIGNMENT uint64 jsid; #define BUILD_JSVAL(mask32, payload) ((jsval)((((uint64)(uint32)(mask32)) << 32) | (uint32)(payload))) @@ -249,7 +250,8 @@ typedef enum JSWhyMagic * to js_Enumerate, which really means the object can be * enumerated like a native object. */ JS_NO_ITER_VALUE, /* there is not a pending iterator value */ - JS_GENERATOR_CLOSING /* exception value thrown when closing a generator */ + JS_GENERATOR_CLOSING, /* exception value thrown when closing a generator */ + JS_NO_CONSTANT /* compiler sentinel value */ } JSWhyMagic; #if !defined(IS_LITTLE_ENDIAN) @@ -608,324 +610,6 @@ JSVAL_TRACE_KIND_IMPL(jsval_layout l) return (uint32)(l.s.mask32 == JSVAL_MASK32_STRING); } -/* - * Boxed word macros (private engine detail) - * - * N.B. jsboxedword and the JSBOXEDWORD macros are engine-private. Callers - * should use only JSID macros (below) instead. - * - * The jsboxedword type is used by atoms and jsids. Eventually, the ability to - * atomize any primitive will be removed and atoms will simply be unboxed, - * interned JSString*s. However, jsids will always need boxing. Using a - * one-word boxing scheme instead of the normal jsval 16-byte unboxed scheme - * allows jsids to be passed by value without penalty, since jsids never are - * doubles nor are jsids used to build typemaps for entering/leaving trace. - */ - -typedef jsword jsboxedword; - -#define JSBOXEDWORD_TYPE_OBJECT 0x0 -#define JSBOXEDWORD_TYPE_INT 0x1 -#define JSBOXEDWORD_TYPE_DOUBLE 0x2 -#define JSBOXEDWORD_TYPE_STRING 0x4 -#define JSBOXEDWORD_TYPE_SPECIAL 0x6 - -/* Type tag bitfield length and derived macros. */ -#define JSBOXEDWORD_TAGBITS 3 -#define JSBOXEDWORD_TAGMASK ((jsboxedword) JS_BITMASK(JSBOXEDWORD_TAGBITS)) -#define JSBOXEDWORD_ALIGN JS_BIT(JSBOXEDWORD_TAGBITS) - -static const jsboxedword JSBOXEDWORD_NULL = (jsboxedword)0x0; -static const jsboxedword JSBOXEDWORD_FALSE = (jsboxedword)0x6; -static const jsboxedword JSBOXEDWORD_TRUE = (jsboxedword)0xe; -static const jsboxedword JSBOXEDWORD_VOID = (jsboxedword)0x16; - -static JS_ALWAYS_INLINE JSBool -JSBOXEDWORD_IS_NULL(jsboxedword w) -{ - return w == JSBOXEDWORD_NULL; -} - -static JS_ALWAYS_INLINE JSBool -JSBOXEDWORD_IS_VOID(jsboxedword w) -{ - return w == JSBOXEDWORD_VOID; -} - -static JS_ALWAYS_INLINE unsigned -JSBOXEDWORD_TAG(jsboxedword w) -{ - return (unsigned)(w & JSBOXEDWORD_TAGMASK); -} - -static JS_ALWAYS_INLINE jsboxedword -JSBOXEDWORD_SETTAG(jsboxedword w, unsigned t) -{ - return w | t; -} - -static JS_ALWAYS_INLINE jsboxedword -JSBOXEDWORD_CLRTAG(jsboxedword w) -{ - return w & ~(jsboxedword)JSBOXEDWORD_TAGMASK; -} - -static JS_ALWAYS_INLINE JSBool -JSBOXEDWORD_IS_DOUBLE(jsboxedword w) -{ - return JSBOXEDWORD_TAG(w) == JSBOXEDWORD_TYPE_DOUBLE; -} - -static JS_ALWAYS_INLINE double * -JSBOXEDWORD_TO_DOUBLE(jsboxedword w) -{ - JS_ASSERT(JSBOXEDWORD_IS_DOUBLE(w)); - return (double *)JSBOXEDWORD_CLRTAG(w); -} - -static JS_ALWAYS_INLINE jsboxedword -DOUBLE_TO_JSBOXEDWORD(double *d) -{ - JS_ASSERT(((JSUword)d & JSBOXEDWORD_TAGMASK) == 0); - return (jsboxedword)((JSUword)d | JSBOXEDWORD_TYPE_DOUBLE); -} - -static JS_ALWAYS_INLINE JSBool -JSBOXEDWORD_IS_STRING(jsboxedword w) -{ - return JSBOXEDWORD_TAG(w) == JSBOXEDWORD_TYPE_STRING; -} - -static JS_ALWAYS_INLINE JSString * -JSBOXEDWORD_TO_STRING(jsboxedword w) -{ - JS_ASSERT(JSBOXEDWORD_IS_STRING(w)); - return (JSString *)JSBOXEDWORD_CLRTAG(w); -} - -static JS_ALWAYS_INLINE JSBool -JSBOXEDWORD_IS_SPECIAL(jsboxedword w) -{ - return JSBOXEDWORD_TAG(w) == JSBOXEDWORD_TYPE_SPECIAL; -} - -static JS_ALWAYS_INLINE jsint -JSBOXEDWORD_TO_SPECIAL(jsboxedword w) -{ - JS_ASSERT(JSBOXEDWORD_IS_SPECIAL(w)); - return jsint(w >> JSBOXEDWORD_TAGBITS); -} - -static JS_ALWAYS_INLINE jsboxedword -SPECIAL_TO_JSBOXEDWORD(jsint i) -{ - return (i << JSBOXEDWORD_TAGBITS) | JSBOXEDWORD_TYPE_SPECIAL; -} - -static JS_ALWAYS_INLINE JSBool -JSBOXEDWORD_IS_BOOLEAN(jsboxedword w) -{ - return (w & ~((jsboxedword)1 << JSBOXEDWORD_TAGBITS)) == JSBOXEDWORD_TYPE_SPECIAL; -} - -static JS_ALWAYS_INLINE JSBool -JSBOXEDWORD_TO_BOOLEAN(jsboxedword w) -{ - JS_ASSERT(w == JSBOXEDWORD_TRUE || w == JSBOXEDWORD_FALSE); - return JSBOXEDWORD_TO_SPECIAL(w); -} - -static JS_ALWAYS_INLINE jsboxedword -BOOLEAN_TO_JSBOXEDWORD(JSBool b) -{ - JS_ASSERT(b == JS_TRUE || b == JS_FALSE); - return SPECIAL_TO_JSBOXEDWORD(b); -} - -static JS_ALWAYS_INLINE jsboxedword -STRING_TO_JSBOXEDWORD(JSString *str) -{ - JS_ASSERT(((JSUword)str & JSBOXEDWORD_TAGMASK) == 0); - return (jsboxedword)str | JSBOXEDWORD_TYPE_STRING; -} - -static JS_ALWAYS_INLINE JSBool -JSBOXEDWORD_IS_GCTHING(jsboxedword w) -{ - return !(w & JSBOXEDWORD_TYPE_INT) && - JSBOXEDWORD_TAG(w) != JSBOXEDWORD_TYPE_SPECIAL; -} - -static JS_ALWAYS_INLINE void * -JSBOXEDWORD_TO_GCTHING(jsboxedword w) -{ - JS_ASSERT(JSBOXEDWORD_IS_GCTHING(w)); - return (void *)JSBOXEDWORD_CLRTAG(w); -} - -static JS_ALWAYS_INLINE uint32 -JSBOXEDWORD_TRACE_KIND(jsboxedword w) -{ -#ifdef DEBUG - unsigned tag = JSBOXEDWORD_TAG(w); - JS_ASSERT(tag == 0x0 || tag == 0x2 || tag == 0x4); -#endif - - /* - * We need to map: - * XXXXXXXXXXXXXXXXXXXXXXXXXXXXX000 -> 00 (object) - * XXXXXXXXXXXXXXXXXXXXXXXXXXXXX010 -> 10 (double) - * XXXXXXXXXXXXXXXXXXXXXXXXXXXXX100 -> 01 (string) - */ - return (w | ((w & 0x4) >> 2)) & 0x3; -} - -static JS_ALWAYS_INLINE JSBool -JSBOXEDWORD_IS_OBJECT(jsboxedword w) -{ - return JSBOXEDWORD_TAG(w) == JSBOXEDWORD_TYPE_OBJECT; -} - -static JS_ALWAYS_INLINE JSObject * -JSBOXEDWORD_TO_OBJECT(jsboxedword w) -{ - JS_ASSERT(JSBOXEDWORD_IS_OBJECT(w)); - return (JSObject *)JSBOXEDWORD_TO_GCTHING(w); -} - -static JS_ALWAYS_INLINE jsboxedword -OBJECT_TO_JSBOXEDWORD(JSObject *obj) -{ - JS_ASSERT(((JSUword)obj & JSBOXEDWORD_TAGMASK) == 0); - return (jsboxedword)obj | JSBOXEDWORD_TYPE_OBJECT; -} - -static JS_ALWAYS_INLINE JSBool -JSBOXEDWORD_IS_PRIMITIVE(jsboxedword w) -{ - return !JSBOXEDWORD_IS_OBJECT(w) || JSBOXEDWORD_IS_NULL(w); -} - -/* Domain limits for the jsboxedword int type. */ -#define JSBOXEDWORD_INT_BITS 31 -#define JSBOXEDWORD_INT_POW2(n) ((jsboxedword)1 << (n)) -#define JSBOXEDWORD_INT_MIN (-JSBOXEDWORD_INT_POW2(30)) -#define JSBOXEDWORD_INT_MAX (JSBOXEDWORD_INT_POW2(30) - 1) - -static JS_ALWAYS_INLINE JSBool -INT32_FITS_IN_JSBOXEDWORD(jsint i) -{ - return ((jsuint)(i) - (jsuint)JSBOXEDWORD_INT_MIN <= - (jsuint)(JSBOXEDWORD_INT_MAX - JSBOXEDWORD_INT_MIN)); -} - -static JS_ALWAYS_INLINE JSBool -JSBOXEDWORD_IS_INT(jsboxedword w) -{ - return w & JSBOXEDWORD_TYPE_INT; -} - -static JS_ALWAYS_INLINE jsint -JSBOXEDWORD_TO_INT(jsboxedword v) -{ - JS_ASSERT(JSBOXEDWORD_IS_INT(v)); - return (jsint)(v >> 1); -} - -static JS_ALWAYS_INLINE jsboxedword -INT_TO_JSBOXEDWORD(jsint i) -{ - JS_ASSERT(INT32_FITS_IN_JSBOXEDWORD(i)); - return (i << 1) | JSBOXEDWORD_TYPE_INT; -} - -/* - * Identifier (jsid) macros. - */ - -typedef jsboxedword jsid; -struct JSAtom; - -static JS_ALWAYS_INLINE JSBool -JSID_IS_ATOM(jsid id) -{ - return JSBOXEDWORD_IS_STRING((jsboxedword)id); -} - -static JS_ALWAYS_INLINE JSAtom * -JSID_TO_ATOM(jsid id) -{ - JS_ASSERT(JSID_IS_ATOM(id)); - return (JSAtom *)id; -} - -static JS_ALWAYS_INLINE JSString * -JSID_TO_STRING(jsid id) -{ - JS_ASSERT(JSID_IS_ATOM(id)); - return JSBOXEDWORD_TO_STRING(id); -} - -static JS_ALWAYS_INLINE jsid -ATOM_TO_JSID(JSAtom *atom) -{ - JS_ASSERT(JSBOXEDWORD_IS_STRING((jsboxedword)atom)); - return (jsid)atom; -} - -static JS_ALWAYS_INLINE JSBool -INT32_FITS_IN_JSID(int32 i) -{ - return INT32_FITS_IN_JSBOXEDWORD(i); -} - -static JS_ALWAYS_INLINE JSBool -JSID_IS_INT(jsid id) -{ - return JSBOXEDWORD_IS_INT((jsboxedword)id); -} - -static JS_ALWAYS_INLINE int32 -JSID_TO_INT(jsid id) -{ - return JSBOXEDWORD_TO_INT((jsboxedword)id); -} - -static JS_ALWAYS_INLINE jsid -INT_TO_JSID(int32 i) -{ - return (jsid)INT_TO_JSBOXEDWORD(i); -} - -static JS_ALWAYS_INLINE JSBool -JSID_IS_OBJECT(jsid id) -{ - return JSBOXEDWORD_IS_OBJECT((jsboxedword)id); -} - -static JS_ALWAYS_INLINE JSObject * -JSID_TO_OBJECT(jsid id) -{ - return JSBOXEDWORD_TO_OBJECT((jsboxedword)id); -} - -static JS_ALWAYS_INLINE jsid -OBJECT_TO_JSID(JSObject *obj) -{ - return (jsid)OBJECT_TO_JSBOXEDWORD(obj); -} - -/* TODO: get JSID/JSBOXEDWORD story together. */ -/* Objects and strings (no doubles in jsids). */ -#define JSID_IS_GCTHING(id) JSBOXEDWORD_IS_GCTHING(id) -#define JSID_TO_GCTHING(id) (JS_ASSERT(JSID_IS_GCTHING((id))), \ - JSBOXEDWORD_TO_GCTHING((jsboxedword)(id))) -#define JSID_TRACE_KIND(id) (JS_ASSERT(JSID_IS_GCTHING((id))), \ - JSBOXEDWORD_TRACE_KIND((jsboxedword)(id))) - -JS_PUBLIC_API(jsval) -JSID_TO_JSVAL(jsid id); - /* JSClass (and JSObjectOps where appropriate) function pointer typedefs. */ /* @@ -936,7 +620,7 @@ JSID_TO_JSVAL(jsid id); * obj[id] can't be deleted (because it's permanent). */ typedef JSBool -(* JSPropertyOp)(JSContext *cx, JSObject *obj, jsid id, jsval *vp); +(* JSPropertyOp)(JSContext *cx, JSObject *obj, jsval id, jsval *vp); /* * This function type is used for callbacks that enumerate the properties of @@ -967,7 +651,7 @@ typedef JSBool */ typedef JSBool (* JSNewEnumerateOp)(JSContext *cx, JSObject *obj, JSIterateOp enum_op, - jsval *statep, jsid *idp); + jsval *statep, jsval *idp); /* * The old-style JSClass.enumerate op should define all lazy properties not @@ -989,7 +673,7 @@ typedef JSBool * NB: JSNewResolveOp provides a cheaper way to resolve lazy properties. */ typedef JSBool -(* JSResolveOp)(JSContext *cx, JSObject *obj, jsid id); +(* JSResolveOp)(JSContext *cx, JSObject *obj, jsval id); /* * Like JSResolveOp, but flags provide contextual information as follows: @@ -1021,7 +705,7 @@ typedef JSBool * *objp without a new JSClass flag. */ typedef JSBool -(* JSNewResolveOp)(JSContext *cx, JSObject *obj, jsid id, uintN flags, +(* JSNewResolveOp)(JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp); /* @@ -1088,7 +772,7 @@ typedef JSObjectOps * * specialize access checks. */ typedef JSBool -(* JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, +(* JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsval id, JSAccessMode mode, jsval *vp); /* @@ -1194,7 +878,7 @@ typedef uint32 * */ typedef JSBool -(* JSEqualityOp)(JSContext *cx, JSObject *obj, const jsval *vp, JSBool *bp); +(* JSEqualityOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp); /* * A generic type for functions mapping an object to another object, or null @@ -1377,16 +1061,16 @@ typedef JSBool typedef JSBool (* FastNative)(JSContext *cx, uintN argc, Value *vp); typedef JSBool -(* PropertyOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp); +(* PropertyOp)(JSContext *cx, JSObject *obj, jsval id, Value *vp); typedef JSBool (* ConvertOp)(JSContext *cx, JSObject *obj, JSType type, Value *vp); typedef JSBool (* NewEnumerateOp)(JSContext *cx, JSObject *obj, JSIterateOp enum_op, - Value *statep, jsid *idp); + Value *statep, jsval *idp); typedef JSBool (* HasInstanceOp)(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp); typedef JSBool -(* CheckAccessOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, +(* CheckAccessOp)(JSContext *cx, JSObject *obj, jsval id, JSAccessMode mode, Value *vp); typedef JSObjectOps * (* GetObjectOps)(JSContext *cx, Class *clasp); diff --git a/js/src/jsregexp.cpp b/js/src/jsregexp.cpp index 3662e2e2c50..cb86ae452b5 100644 --- a/js/src/jsregexp.cpp +++ b/js/src/jsregexp.cpp @@ -5028,9 +5028,9 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp, if (test) continue; if (parsub->index == -1) { - Value undef = undefinedValue(); - ok = js_DefineProperty(cx, obj, INT_TO_JSID(num + 1), &undef, - NULL, NULL, JSPROP_ENUMERATE); + Value tmp = UndefinedTag(); + ok = js_DefineProperty(cx, obj, INT_TO_JSID(num + 1), + &tmp, NULL, NULL, JSPROP_ENUMERATE); } else { parstr = js_NewDependentString(cx, str, gData.cpbegin + parsub->index - @@ -5041,8 +5041,8 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp, goto out; } Value tmp = StringTag(parstr); - ok = js_DefineProperty(cx, obj, INT_TO_JSID(num + 1), &tmp, - NULL, NULL, JSPROP_ENUMERATE); + ok = js_DefineProperty(cx, obj, INT_TO_JSID(num + 1), + &tmp, NULL, NULL, JSPROP_ENUMERATE); } if (!ok) goto out; diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index cc7cbb86dfc..03071d052d2 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -339,15 +339,8 @@ JSScope::finishRuntimeState(JSContext *cx) } 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 +JS_STATIC_ASSERT(sizeof(jsid) == 8); +#define HASH_ID(id) ((JSHashNumber)(id) ^ (JSHashNumber)((id) >> 32)) /* * Double hashing needs the second hash code to be relatively prime to table @@ -368,7 +361,7 @@ JSScope::searchTable(jsid id, bool adding) uint32 sizeMask; JS_ASSERT(table); - JS_ASSERT(!JSBOXEDWORD_IS_NULL(id)); + JS_ASSERT(!JSVAL_IS_NULL(id)); /* Compute the primary hash address. */ METER(hashes); @@ -502,7 +495,7 @@ JSScopeProperty * JSScope::getChildProperty(JSContext *cx, JSScopeProperty *parent, JSScopeProperty &child) { - JS_ASSERT(!JSBOXEDWORD_IS_NULL(child.id)); + JS_ASSERT(!JSVAL_IS_NULL(child.id)); JS_ASSERT(!child.inDictionary()); /* @@ -740,7 +733,7 @@ JSScope::addProperty(JSContext *cx, jsid id, JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, this)); CHECK_ANCESTOR_LINE(this, true); - JS_ASSERT(!JSBOXEDWORD_IS_NULL(id)); + JS_ASSERT(!JSVAL_IS_NULL(id)); JS_ASSERT_IF(!cx->runtime->gcRegenShapes, hasRegenFlag(cx->runtime->gcRegenShapesScopeFlag)); @@ -873,7 +866,7 @@ JSScope::putProperty(JSContext *cx, jsid id, JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, this)); CHECK_ANCESTOR_LINE(this, true); - JS_ASSERT(!JSBOXEDWORD_IS_NULL(id)); + JS_ASSERT(!JSVAL_IS_NULL(id)); JS_ASSERT_IF(!cx->runtime->gcRegenShapes, hasRegenFlag(cx->runtime->gcRegenShapesScopeFlag)); @@ -981,7 +974,7 @@ JSScope::changeProperty(JSContext *cx, JSScopeProperty *sprop, JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, this)); CHECK_ANCESTOR_LINE(this, true); - JS_ASSERT(!JSBOXEDWORD_IS_NULL(sprop->id)); + JS_ASSERT(!JSVAL_IS_NULL(sprop->id)); JS_ASSERT(hasProperty(sprop)); attrs |= sprop->attrs & mask; @@ -1160,14 +1153,14 @@ JSScope::clear(JSContext *cx) void JSScope::deletingShapeChange(JSContext *cx, JSScopeProperty *sprop) { - JS_ASSERT(!JSBOXEDWORD_IS_NULL(sprop->id)); + JS_ASSERT(!JSVAL_IS_NULL(sprop->id)); generateOwnShape(cx); } bool JSScope::methodShapeChange(JSContext *cx, JSScopeProperty *sprop) { - JS_ASSERT(!JSBOXEDWORD_IS_NULL(sprop->id)); + JS_ASSERT(!JSVAL_IS_NULL(sprop->id)); if (sprop->isMethod()) { #ifdef DEBUG const Value &prev = object->lockedGetSlot(sprop->slot); @@ -1202,7 +1195,7 @@ JSScope::methodShapeChange(JSContext *cx, uint32 slot) generateOwnShape(cx); } else { for (JSScopeProperty *sprop = lastProp; sprop; sprop = sprop->parent) { - JS_ASSERT(!JSBOXEDWORD_IS_NULL(sprop->id)); + JS_ASSERT(!JSVAL_IS_NULL(sprop->id)); if (sprop->slot == slot) return methodShapeChange(cx, sprop); } @@ -1219,7 +1212,7 @@ JSScope::protoShapeChange(JSContext *cx) void JSScope::shadowingShapeChange(JSContext *cx, JSScopeProperty *sprop) { - JS_ASSERT(!JSBOXEDWORD_IS_NULL(sprop->id)); + JS_ASSERT(!JSVAL_IS_NULL(sprop->id)); generateOwnShape(cx); } @@ -1242,7 +1235,7 @@ PrintPropertyGetterOrSetter(JSTracer *trc, char *buf, size_t bufsize) JS_ASSERT(trc->debugPrinter == PrintPropertyGetterOrSetter); sprop = (JSScopeProperty *)trc->debugPrintArg; id = sprop->id; - JS_ASSERT(!JSBOXEDWORD_IS_NULL(id)); + JS_ASSERT(!JSVAL_IS_NULL(id)); name = trc->debugPrintIndex ? js_setter_str : js_getter_str; if (JSID_IS_ATOM(id)) { @@ -1267,7 +1260,7 @@ PrintPropertyMethod(JSTracer *trc, char *buf, size_t bufsize) JS_ASSERT(trc->debugPrinter == PrintPropertyMethod); sprop = (JSScopeProperty *)trc->debugPrintArg; id = sprop->id; - JS_ASSERT(!JSBOXEDWORD_IS_NULL(id)); + JS_ASSERT(!JSVAL_IS_NULL(id)); JS_ASSERT(JSID_IS_ATOM(id)); n = js_PutEscapedString(buf, bufsize - 1, JSID_TO_STRING(id), 0); @@ -1281,7 +1274,7 @@ JSScopeProperty::trace(JSTracer *trc) { if (IS_GC_MARKING_TRACER(trc)) mark(); - MarkBoxedWord(trc, id, "id"); + MarkId(trc, id, "id"); if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) { if ((attrs & JSPROP_GETTER) && rawGetter) { diff --git a/js/src/jsscope.h b/js/src/jsscope.h index 0ce48d99ca8..b68cd587e07 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -602,7 +602,7 @@ struct JSScopeProperty { }; void insertFree(JSScopeProperty *&list) { - id = JSBOXEDWORD_NULL; + id = JSVAL_NULL; next = list; prevp = &list; if (list) @@ -611,7 +611,7 @@ struct JSScopeProperty { } void removeFree() { - JS_ASSERT(JSBOXEDWORD_IS_NULL(id)); + JS_ASSERT(JSVAL_IS_NULL(id)); *prevp = next; if (next) next->prevp = prevp; @@ -798,7 +798,7 @@ JSScope::hasProperty(JSScopeProperty *sprop) inline JSScopeProperty * JSScope::lastProperty() const { - JS_ASSERT_IF(lastProp, !JSBOXEDWORD_IS_NULL(lastProp->id)); + JS_ASSERT_IF(lastProp, !JSVAL_IS_NULL(lastProp->id)); return lastProp; } @@ -809,8 +809,8 @@ JSScope::lastProperty() const inline void JSScope::setLastProperty(JSScopeProperty *sprop) { - JS_ASSERT(!JSBOXEDWORD_IS_NULL(sprop->id)); - JS_ASSERT_IF(lastProp, !JSBOXEDWORD_IS_NULL(lastProp->id)); + JS_ASSERT(!JSVAL_IS_NULL(sprop->id)); + JS_ASSERT_IF(lastProp, !JSVAL_IS_NULL(lastProp->id)); lastProp = sprop; } @@ -819,7 +819,7 @@ inline void JSScope::removeLastProperty() { JS_ASSERT(!inDictionaryMode()); - JS_ASSERT_IF(lastProp->parent, !JSBOXEDWORD_IS_NULL(lastProp->parent->id)); + JS_ASSERT_IF(lastProp->parent, !JSVAL_IS_NULL(lastProp->parent->id)); lastProp = lastProp->parent; --entryCount; @@ -831,12 +831,12 @@ JSScope::removeDictionaryProperty(JSScopeProperty *sprop) JS_ASSERT(inDictionaryMode()); JS_ASSERT(sprop->inDictionary()); JS_ASSERT(sprop->childp); - JS_ASSERT(!JSBOXEDWORD_IS_NULL(sprop->id)); + JS_ASSERT(!JSVAL_IS_NULL(sprop->id)); JS_ASSERT(lastProp->inDictionary()); JS_ASSERT(lastProp->childp == &lastProp); - JS_ASSERT_IF(lastProp != sprop, !JSBOXEDWORD_IS_NULL(lastProp->id)); - JS_ASSERT_IF(lastProp->parent, !JSBOXEDWORD_IS_NULL(lastProp->parent->id)); + JS_ASSERT_IF(lastProp != sprop, !JSVAL_IS_NULL(lastProp->id)); + JS_ASSERT_IF(lastProp->parent, !JSVAL_IS_NULL(lastProp->parent->id)); if (sprop->parent) sprop->parent->childp = sprop->childp; @@ -854,12 +854,12 @@ JSScope::insertDictionaryProperty(JSScopeProperty *sprop, JSScopeProperty **chil */ JS_ASSERT(sprop->inDictionary()); JS_ASSERT(!sprop->childp); - JS_ASSERT(!JSBOXEDWORD_IS_NULL(sprop->id)); + JS_ASSERT(!JSVAL_IS_NULL(sprop->id)); JS_ASSERT_IF(*childp, (*childp)->inDictionary()); JS_ASSERT_IF(lastProp, lastProp->inDictionary()); JS_ASSERT_IF(lastProp, lastProp->childp == &lastProp); - JS_ASSERT_IF(lastProp, !JSBOXEDWORD_IS_NULL(lastProp->id)); + JS_ASSERT_IF(lastProp, !JSVAL_IS_NULL(lastProp->id)); sprop->parent = *childp; *childp = sprop; @@ -958,7 +958,7 @@ JSScope::canProvideEmptyScope(JSObjectOps *ops, js::Class *clasp) inline bool JSScopeProperty::get(JSContext* cx, JSObject *obj, JSObject *pobj, js::Value* vp) { - JS_ASSERT(!JSBOXEDWORD_IS_NULL(this->id)); + JS_ASSERT(!JSVAL_IS_NULL(this->id)); JS_ASSERT(!hasDefaultGetter()); if (hasGetterValue()) { diff --git a/js/src/jsscopeinlines.h b/js/src/jsscopeinlines.h index 5802730e4c4..4b73ab02025 100644 --- a/js/src/jsscopeinlines.h +++ b/js/src/jsscopeinlines.h @@ -237,8 +237,8 @@ JSScopeProperty::hash() const inline bool JSScopeProperty::matches(const JSScopeProperty *p) const { - JS_ASSERT(!JSBOXEDWORD_IS_NULL(id)); - JS_ASSERT(!JSBOXEDWORD_IS_NULL(p->id)); + JS_ASSERT(!JSVAL_IS_NULL(id)); + JS_ASSERT(!JSVAL_IS_NULL(p->id)); return id == p->id && matchesParamsAfterId(p->rawGetter, p->rawSetter, p->slot, p->attrs, p->flags, p->shortid); @@ -248,7 +248,7 @@ inline bool JSScopeProperty::matchesParamsAfterId(js::PropertyOp agetter, js::PropertyOp asetter, uint32 aslot, uintN aattrs, uintN aflags, intN ashortid) const { - JS_ASSERT(!JSBOXEDWORD_IS_NULL(id)); + JS_ASSERT(!JSVAL_IS_NULL(id)); return rawGetter == agetter && rawSetter == asetter && slot == aslot && diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 3f8b7d7674b..2fff276440b 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -75,7 +75,7 @@ static const jsbytecode emptyScriptCode[] = {JSOP_STOP, SRC_NULL}; /* static */ const JSScript JSScript::emptyScriptConst = { const_cast(emptyScriptCode), - 1, JSVERSION_DEFAULT, 0, 0, 0, 0, 0, true, false, false, false, + 1, JSVERSION_DEFAULT, 0, 0, 0, 0, 0, 0, true, false, false, false, const_cast(emptyScriptCode), {0, NULL}, NULL, 0, 0, 0, NULL }; @@ -91,7 +91,7 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, bool needMutableScript, JSBool ok; jsbytecode *code; uint32 length, lineno, nslots, magic; - uint32 natoms, nsrcnotes, ntrynotes, nobjects, nupvars, nregexps, i; + uint32 natoms, nsrcnotes, ntrynotes, nobjects, nupvars, nregexps, nconsts, i; uint32 prologLength, version; JSPrincipals *principals; uint32 encodeable; @@ -101,7 +101,7 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, bool needMutableScript, cx = xdr->cx; script = *scriptp; - nsrcnotes = ntrynotes = natoms = nobjects = nupvars = nregexps = 0; + nsrcnotes = ntrynotes = natoms = nobjects = nupvars = nregexps = nconsts = 0; filenameWasSaved = JS_FALSE; notes = NULL; @@ -146,7 +146,7 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, bool needMutableScript, * the shorthand (0 length word) for us. Make a new mutable empty * script here and return it immediately. */ - script = js_NewScript(cx, 1, 1, 0, 0, 0, 0, 0); + script = js_NewScript(cx, 1, 1, 0, 0, 0, 0, 0, 0); if (!script) return JS_FALSE; @@ -186,6 +186,8 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, bool needMutableScript, nregexps = script->regexps()->length; if (script->trynotesOffset != 0) ntrynotes = script->trynotes()->length; + if (script->constOffset != 0) + nconsts = script->consts()->length; } if (!JS_XDRUint32(xdr, &prologLength)) @@ -209,12 +211,14 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, bool needMutableScript, return JS_FALSE; if (!JS_XDRUint32(xdr, &nregexps)) return JS_FALSE; + if (!JS_XDRUint32(xdr, &nconsts)) + return JS_FALSE; AutoScriptRooter tvr(cx, NULL); if (xdr->mode == JSXDR_DECODE) { script = js_NewScript(cx, length, nsrcnotes, natoms, nobjects, nupvars, - nregexps, ntrynotes); + nregexps, ntrynotes, nconsts); if (!script) return JS_FALSE; @@ -367,6 +371,11 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, bool needMutableScript, } while (tn != tnfirst); } + for (i = 0; i != nconsts; ++i) { + if (!JS_XDRValue(xdr, Jsvalify(&script->consts()->vector[i]))) + goto error; + } + xdr->script = oldscript; return JS_TRUE; @@ -806,7 +815,7 @@ JS_STATIC_ASSERT(sizeof(JSScript) + 2 * sizeof(JSObjectArray) + JSScript * js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natoms, uint32 nobjects, uint32 nupvars, uint32 nregexps, - uint32 ntrynotes) + uint32 ntrynotes, uint32 nconsts) { size_t size, vectorSize; JSScript *script; @@ -824,6 +833,8 @@ js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natoms, size += sizeof(JSObjectArray) + nregexps * sizeof(JSObject *); if (ntrynotes != 0) size += sizeof(JSTryNoteArray) + ntrynotes * sizeof(JSTryNote); + if (nconsts != 0) + size += sizeof(JSConstArray) + nconsts * sizeof(Value); script = (JSScript *) cx->malloc(size); if (!script) @@ -849,6 +860,10 @@ js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natoms, script->trynotesOffset = (uint8)(cursor - (uint8 *)script); cursor += sizeof(JSTryNoteArray); } + if (nconsts != 0) { + script->constOffset = (uint8)(cursor - (uint8 *)script); + cursor += sizeof(JSConstArray); + } if (natoms != 0) { script->atomMap.length = natoms; @@ -889,6 +904,14 @@ js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natoms, cursor += vectorSize; } + if (nconsts != 0) { + script->consts()->length = nconsts; + script->consts()->vector = (Value *)cursor; + vectorSize = nconsts * sizeof(script->consts()->vector[0]); + memset(cursor, 0, vectorSize); + cursor += vectorSize; + } + /* * NB: We allocate the vector of uint32 upvar cookies after all vectors of * pointers, to avoid misalignment on 64-bit platforms. See bug 514645. @@ -988,7 +1011,7 @@ js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg) script = js_NewScript(cx, prologLength + mainLength, nsrcnotes, cg->atomList.count, cg->objectList.length, cg->upvarList.count, cg->regexpList.length, - cg->ntrynotes); + cg->ntrynotes, cg->constList.length()); if (!script) return NULL; @@ -1028,6 +1051,8 @@ js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg) cg->objectList.finish(script->objects()); if (cg->regexpList.length != 0) cg->regexpList.finish(script->regexps()); + if (cg->constList.length() != 0) + cg->constList.finish(script->consts()); if (cg->flags & TCF_NO_SCRIPT_RVAL) script->noScriptRval = true; if (cg->hasSharps()) @@ -1174,9 +1199,7 @@ void js_TraceScript(JSTracer *trc, JSScript *script) { JSAtomMap *map = &script->atomMap; - uintN length = map->length; - jsboxedword *vector = (jsboxedword *)map->vector; - MarkBoxedWordRange(trc, length, vector, "atomMap"); + MarkAtomRange(trc, map->length, map->vector, "atomMap"); if (script->objectsOffset != 0) { JSObjectArray *objarray = script->objects(); @@ -1202,6 +1225,11 @@ js_TraceScript(JSTracer *trc, JSScript *script) } while (i != 0); } + if (script->constOffset != 0) { + JSConstArray *constarray = script->consts(); + MarkValueRange(trc, constarray->length, constarray->vector, "consts"); + } + if (script->u.object) { JS_SET_TRACING_NAME(trc, "object"); MarkRaw(trc, script->u.object, JSTRACE_OBJECT); diff --git a/js/src/jsscript.h b/js/src/jsscript.h index e01674c9157..70b6add9ce5 100644 --- a/js/src/jsscript.h +++ b/js/src/jsscript.h @@ -86,6 +86,11 @@ typedef struct JSUpvarArray { uint32 length; /* count of indexed upvar cookies */ } JSUpvarArray; +typedef struct JSConstArray { + js::Value *vector; /* array of indexed constant values */ + uint32 length; +} JSConstArray; + #define CALLEE_UPVAR_SLOT 0xffff #define FREE_STATIC_LEVEL 0x3fff #define FREE_UPVAR_COOKIE 0xffffffff @@ -115,6 +120,8 @@ struct JSScript { regexps or 0 if none. */ uint8 trynotesOffset; /* offset to the array of try notes or 0 if none */ + uint8 constOffset; /* offset to the array of constants or + 0 if none */ bool noScriptRval:1; /* no need for result value of last expression statement */ bool savedCallerFun:1; /* object 0 is caller function */ @@ -159,6 +166,11 @@ struct JSScript { return (JSTryNoteArray *) ((uint8 *) this + trynotesOffset); } + JSConstArray *consts() { + JS_ASSERT(constOffset != 0); + return (JSConstArray *) ((uint8 *) this + constOffset); + } + JSAtom *getAtom(size_t index) { JS_ASSERT(index < atomMap.length); return atomMap.vector[index]; @@ -174,6 +186,12 @@ struct JSScript { inline JSObject *getRegExp(size_t index); + js::Value getConst(size_t index) { + JSConstArray *arr = consts(); + JS_ASSERT(index < arr->length); + return arr->vector[index]; + } + /* * The isEmpty method tells whether this script has code that computes any * result (not return value, result AKA normal completion value) other than @@ -286,7 +304,7 @@ js_SweepScriptFilenames(JSRuntime *rt); extern JSScript * js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natoms, uint32 nobjects, uint32 nupvars, uint32 nregexps, - uint32 ntrynotes); + uint32 ntrynotes, uint32 nconsts); extern JSScript * js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg); diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index 20debacedcd..13325643b57 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -547,7 +547,7 @@ str_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp) { JSString *str; - if (id == ATOM_KEY(cx->runtime->atomState.lengthAtom)) { + if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) { if (obj->getClass() == &js_StringClass) { /* Follow ECMA-262 by fetching intrinsic length of our string. */ str = obj->getPrimitiveThis().asString(); diff --git a/js/src/jsstr.h b/js/src/jsstr.h index 1fa4ed4838f..8e436570fda 100644 --- a/js/src/jsstr.h +++ b/js/src/jsstr.h @@ -311,6 +311,8 @@ struct JSString { static JSString *intString(jsint i); }; +JS_STATIC_ASSERT(sizeof(JSString) % JS_GCTHING_ALIGN == 0); + extern const jschar * js_GetStringChars(JSContext *cx, JSString *str); diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 36cd0ca3d93..ff0deca3856 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -9007,7 +9007,7 @@ DumpShape(JSObject* obj, const char* prefix) fprintf(shapefp, "\n%s: shape %u flags %x\n", prefix, scope->shape, scope->flags); for (JSScopeProperty* sprop = scope->lastProperty(); sprop; sprop = sprop->parent) { if (JSID_IS_ATOM(sprop->id)) { - fprintf(shapefp, " %s", JS_GetStringBytes(JSVAL_TO_STRING(ID_TO_VALUE(sprop->id)))); + fprintf(shapefp, " %s", JS_GetStringBytes(JSID_TO_STRING(sprop->id))); } else { JS_ASSERT(!JSID_IS_OBJECT(sprop->id)); fprintf(shapefp, " %d", JSID_TO_INT(sprop->id)); diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index d1e0144bc6a..86dfeb56fd5 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -267,7 +267,7 @@ TypedArray::obj_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JS_ASSERT(tarray); if (tarray->isArrayIndex(cx, id)) { - *propp = (JSProperty *) id; + *propp = (JSProperty *) 1; /* non-null to indicate found */ *objp = obj; return true; } @@ -614,14 +614,14 @@ class TypedArrayTemplate } static JSBool - obj_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *vp, + obj_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v, PropertyOp getter, PropertyOp setter, uintN attrs) { if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) return true; - Value v = *vp; - return obj_setProperty(cx, obj, id, &v); + Value tmp = *v; + return obj_setProperty(cx, obj, id, &tmp); } static JSBool diff --git a/js/src/jsxdrapi.cpp b/js/src/jsxdrapi.cpp index 77357fa7646..ce4782c040c 100644 --- a/js/src/jsxdrapi.cpp +++ b/js/src/jsxdrapi.cpp @@ -623,35 +623,20 @@ JS_XDRValue(JSXDRState *xdr, jsval *vp) JSBool js_XDRAtom(JSXDRState *xdr, JSAtom **atomp) { - jsval v; - uint32 type; + JSString *str; - if (xdr->mode == JSXDR_ENCODE) { - v = Jsvalify(BoxedWordToValue(ATOM_KEY(*atomp))); - return JS_XDRValue(xdr, &v); - } + if (xdr->mode == JSXDR_ENCODE) + str = ATOM_TO_STRING(*atomp); - /* - * Inline JS_XDRValue when decoding to avoid ceation of GC things when - * then corresponding atom already exists. See bug 321985. - */ - if (!JS_XDRUint32(xdr, &type)) + if (!JS_XDRString(xdr, &str)) return JS_FALSE; - if (type == JSVAL_STRING) - return js_XDRStringAtom(xdr, atomp); - if (type == JSVAL_DOUBLE) { - jsdouble d = 0; - if (!XDRDoubleValue(xdr, &d)) - return JS_FALSE; - *atomp = js_AtomizeDouble(xdr->cx, d); + if (xdr->mode == JSXDR_DECODE) { + *atomp = js_AtomizeString(xdr->cx, str, 0); return *atomp != NULL; } - jsboxedword w; - return XDRValueBody(xdr, type, &v) && - ValueToBoxedWord(xdr->cx, Valueify(v), &w) && - js_AtomizePrimitiveValue(xdr->cx, w, atomp); + return JS_TRUE; } extern JSBool @@ -665,7 +650,6 @@ js_XDRStringAtom(JSXDRState *xdr, JSAtom **atomp) jschar stackChars[256]; if (xdr->mode == JSXDR_ENCODE) { - JS_ASSERT(ATOM_IS_STRING(*atomp)); str = ATOM_TO_STRING(*atomp); return JS_XDRString(xdr, &str); } diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index 44f4f52b25f..062b2c7de4b 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -252,12 +252,12 @@ namespace_finalize(JSContext *cx, JSObject *obj) } static JSBool -namespace_equality(JSContext *cx, JSObject *obj, const jsval *vp, JSBool *bp) +namespace_equality(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp) { JSObject *obj2; - JS_ASSERT(JSVAL_IS_OBJECT(*vp)); - obj2 = JSVAL_TO_OBJECT(*vp); + JS_ASSERT(JSVAL_IS_OBJECT(*v)); + obj2 = JSVAL_TO_OBJECT(*v); *bp = (!obj2 || obj2->getClass() != &js_NamespaceClass.base) ? JS_FALSE : js_EqualStrings(GetURI(obj), GetURI(obj2)); @@ -2969,7 +2969,7 @@ ToXMLName(JSContext *cx, jsval v, jsid *funidp) * If the idea is to reject uint32 property names, then the check needs to * be stricter, to exclude hexadecimal and floating point literals. */ - if (js_IdIsIndex(STRING_TO_JSBOXEDWORD(name), &index)) + if (js_IdIsIndex(STRING_TO_JSVAL(name), &index)) goto bad; if (*name->chars() == '@') { @@ -3583,18 +3583,17 @@ Insert(JSContext *cx, JSXML *xml, uint32 i, jsval v) } static JSBool -IndexToBoxedWord(JSContext *cx, uint32 index, jsboxedword *wp) +IndexToIdVal(JSContext *cx, uint32 index, jsval *idvp) { JSString *str; - if (index <= JSBOXEDWORD_INT_MAX) { - *wp = INT_TO_JSBOXEDWORD(index); + if (index <= JSVAL_INT_MAX) { + *idvp = INT_TO_JSVAL(index); } else { str = js_NumberToString(cx, (jsdouble) index); if (!str) return JS_FALSE; - - *wp = STRING_TO_JSBOXEDWORD(str); + *idvp = STRING_TO_JSVAL(str); } return JS_TRUE; } @@ -3850,7 +3849,7 @@ GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) /* * ECMA-357 9.2.1.1/9.1.1.1 qname case. */ - nameqn = ToXMLName(cx, Jsvalify(IdToValue(id)), &funid); + nameqn = ToXMLName(cx, ID_TO_JSVAL(id), &funid); if (!nameqn) return false; if (funid) @@ -3955,14 +3954,14 @@ PutProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) MUST_FLOW_THROUGH("out"); jsval roots[3]; roots[OBJ_ROOT] = OBJECT_TO_JSVAL(obj); - roots[ID_ROOT] = Jsvalify(IdToValue(id)); + roots[ID_ROOT] = ID_TO_JSVAL(id); roots[VAL_ROOT] = *vp; AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(roots), Valueify(roots)); if (js_IdIsIndex(id, &index)) { if (xml->xml_class != JSXML_CLASS_LIST) { /* See NOTE in spec: this variation is reserved for future use. */ - ReportBadXMLName(cx, IdToValue(id)); + ReportBadXMLName(cx, ID_TO_VALUE(id)); goto bad; } @@ -4247,7 +4246,7 @@ PutProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) kidobj = js_GetXMLObject(cx, kid); if (!kidobj) goto bad; - id = ATOM_KEY(cx->runtime->atomState.starAtom); + id = ATOM_TO_JSID(cx->runtime->atomState.starAtom); ok = PutProperty(cx, kidobj, id, vp); if (!ok) goto out; @@ -4256,7 +4255,7 @@ PutProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) /* * ECMA-357 9.2.1.2/9.1.1.2 qname case. */ - nameqn = ToXMLName(cx, Jsvalify(IdToValue(id)), &funid); + nameqn = ToXMLName(cx, ID_TO_JSVAL(id), &funid); if (!nameqn) goto bad; if (funid) { @@ -4436,7 +4435,7 @@ PutProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) } /* 10-11. */ - id = JSBOXEDWORD_VOID; + id = JSVAL_VOID; primitiveAssign = !vxml && !IS_STAR(GetLocalName(nameqn)); /* 12. */ @@ -4550,7 +4549,7 @@ out: type_error: JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_XMLLIST_PUT, - js_ValueToPrintableString(cx, IdToValue(id))); + js_ValueToPrintableString(cx, ID_TO_VALUE(id))); bad: ok = JS_FALSE; goto out; @@ -4719,7 +4718,7 @@ HasProperty(JSContext *cx, JSObject *obj, jsid id, JSBool *found) if (js_IdIsIndex(id, &i)) { *found = HasIndexedProperty(xml, i); } else { - qn = ToXMLName(cx, Jsvalify(IdToValue(id)), &funid); + qn = ToXMLName(cx, ID_TO_JSVAL(id), &funid); if (!qn) return JS_FALSE; if (funid) { @@ -4796,7 +4795,7 @@ xml_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, if (js_IdIsIndex(id, &i)) { found = HasIndexedProperty(xml, i); } else { - qn = ToXMLName(cx, Jsvalify(IdToValue(id)), &funid); + qn = ToXMLName(cx, ID_TO_JSVAL(id), &funid); if (!qn) return JS_FALSE; if (funid) @@ -4822,16 +4821,16 @@ xml_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, } static JSBool -xml_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *vp, +xml_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v, PropertyOp getter, PropertyOp setter, uintN attrs) { - if (vp->isFunObj() || getter || setter || + if (v->isFunObj() || getter || setter || (attrs & JSPROP_ENUMERATE) == 0 || (attrs & (JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED))) { - return js_DefineProperty(cx, obj, id, vp, getter, setter, attrs); + return js_DefineProperty(cx, obj, id, v, getter, setter, attrs); } - jsval tmp = Jsvalify(*vp); + jsval tmp = Jsvalify(*v); return PutProperty(cx, obj, id, &tmp); } @@ -4899,12 +4898,12 @@ xml_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval) JSObject *nameqn; jsid funid; - idval = Jsvalify(IdToValue(id)); + idval = ID_TO_JSVAL(id); xml = (JSXML *) obj->getPrivate(); if (js_IdIsIndex(id, &index)) { if (xml->xml_class != JSXML_CLASS_LIST) { /* See NOTE in spec: this variation is reserved for future use. */ - ReportBadXMLName(cx, IdToValue(id)); + ReportBadXMLName(cx, ID_TO_VALUE(id)); return JS_FALSE; } @@ -5012,7 +5011,7 @@ xml_typeOf(JSContext *cx, JSObject *obj) } static JSBool -xml_hasInstance(JSContext *cx, JSObject *obj, const Value *vp, JSBool *bp) +xml_hasInstance(JSContext *cx, JSObject *obj, const Value *, JSBool *bp) { return JS_TRUE; } @@ -5341,16 +5340,11 @@ xml_appendChild(JSContext *cx, uintN argc, jsval *vp) vxml = (JSXML *) vobj->getPrivate(); JS_ASSERT(vxml->xml_class == JSXML_CLASS_LIST); - jsboxedword w; - if (!IndexToBoxedWord(cx, vxml->xml_kids.length, &w)) + if (!IndexToIdVal(cx, vxml->xml_kids.length, &name)) return JS_FALSE; *vp = (argc != 0) ? vp[2] : JSVAL_VOID; - /* - * N.B. w is not actually a jsid: w may contain an non-interned string. - * Apparently, PutProperty is cool with this. - */ - if (!PutProperty(cx, JSVAL_TO_OBJECT(v), w, vp)) + if (!PutProperty(cx, JSVAL_TO_OBJECT(v), v, vp)) return JS_FALSE; *vp = OBJECT_TO_JSVAL(obj); @@ -5415,14 +5409,10 @@ xml_child_helper(JSContext *cx, JSObject *obj, JSXML *xml, jsval name, JSXML *kid; JSObject *kidobj; - jsid idw; - if (!ValueToBoxedWord(cx, Valueify(name), &idw)) - return JS_FALSE; - /* ECMA-357 13.4.4.6 */ JS_ASSERT(xml->xml_class != JSXML_CLASS_LIST); - if (js_IdIsIndex(idw, &index)) { + if (js_IdIsIndex(name, &index)) { if (index >= JSXML_LENGTH(xml)) { *rval = JSVAL_VOID; } else { @@ -5443,7 +5433,7 @@ xml_child_helper(JSContext *cx, JSObject *obj, JSXML *xml, jsval name, * N.B. name is not actually a jsid: name may contain an non-interned * string. Apparently, PutProperty is cool with this. */ - return GetProperty(cx, obj, idw, rval); + return GetProperty(cx, obj, name, rval); } /* XML and XMLList */ @@ -5745,12 +5735,7 @@ xml_hasOwnProperty(JSContext *cx, uintN argc, jsval *vp) return JS_FALSE; name = argc != 0 ? vp[2] : JSVAL_VOID; - - jsid idw; - if (!ValueToBoxedWord(cx, Valueify(name), &idw)) - return JS_FALSE; - - if (!HasProperty(cx, obj, idw, &found)) + if (!HasProperty(cx, obj, name, &found)) return JS_FALSE; if (found) { *vp = JSVAL_TRUE; @@ -6312,18 +6297,13 @@ xml_propertyIsEnumerable(JSContext *cx, uintN argc, jsval *vp) XML_METHOD_PROLOG; *vp = JSVAL_FALSE; - if (argc != 0) { - jsboxedword idw; - if (!ValueToBoxedWord(cx, Valueify(vp[2]), &idw)) - return JS_FALSE; - if (js_IdIsIndex(idw, &index)) { - if (xml->xml_class == JSXML_CLASS_LIST) { - /* 13.5.4.18. */ - *vp = BOOLEAN_TO_JSVAL(index < xml->xml_kids.length); - } else { - /* 13.4.4.30. */ - *vp = BOOLEAN_TO_JSVAL(index == 0); - } + if (argc != 0 && js_IdIsIndex(vp[2], &index)) { + if (xml->xml_class == JSXML_CLASS_LIST) { + /* 13.5.4.18. */ + *vp = BOOLEAN_TO_JSVAL(index < xml->xml_kids.length); + } else { + /* 13.4.4.30. */ + *vp = BOOLEAN_TO_JSVAL(index == 0); } } return JS_TRUE; @@ -6441,11 +6421,7 @@ xml_replace(JSContext *cx, uintN argc, jsval *vp) if (!xml) return JS_FALSE; - jsid idw; - if (!ValueToBoxedWord(cx, Valueify(vp[2]), &idw)) - return JS_FALSE; - - if (argc == 0 || !js_IdIsIndex(idw, &index)) { + if (argc == 0 || !js_IdIsIndex(vp[2], &index)) { /* * Call function QName per spec, not ToXMLName, to avoid attribute * names. @@ -6490,7 +6466,7 @@ xml_setChildren(JSContext *cx, uintN argc, jsval *vp) return JS_FALSE; *vp = argc != 0 ? vp[2] : JSVAL_VOID; /* local root */ - if (!PutProperty(cx, obj, ATOM_KEY(cx->runtime->atomState.starAtom), vp)) + if (!PutProperty(cx, obj, ATOM_TO_JSVAL(cx->runtime->atomState.starAtom), vp)) return JS_FALSE; *vp = OBJECT_TO_JSVAL(obj); @@ -7115,9 +7091,9 @@ js_TraceXML(JSTracer *trc, JSXML *xml) if (xml->xml_targetprop) JS_CALL_OBJECT_TRACER(trc, xml->xml_targetprop, "targetprop"); } else { - MarkObjectVector(trc, xml->xml_namespaces.length, - (JSObject **) xml->xml_namespaces.vector, - "xml_namespaces"); + MarkObjectRange(trc, xml->xml_namespaces.length, + (JSObject **) xml->xml_namespaces.vector, + "xml_namespaces"); XMLArrayCursorTrace(trc, xml->xml_namespaces.cursors); if (IS_GC_MARKING_TRACER(trc)) XMLArrayTrim(&xml->xml_namespaces); diff --git a/js/src/jsxml.h b/js/src/jsxml.h index 12788e5f766..71f39a7de15 100644 --- a/js/src/jsxml.h +++ b/js/src/jsxml.h @@ -168,7 +168,7 @@ struct JSXML { } u; }; -JS_STATIC_ASSERT(sizeof(JSXML) % JSBOXEDWORD_ALIGN == 0); +JS_STATIC_ASSERT(sizeof(JSXML) % JS_GCTHING_ALIGN == 0); /* union member shorthands */ #define xml_kids u.list.kids diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index ce9f9c494fb..cdf1e52e998 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -216,19 +216,6 @@ JS_END_EXTERN_C class ToString { public: - ToString(JSContext *aCx, jsid id, JSBool aThrow = JS_FALSE) - : cx(aCx) - , mThrow(aThrow) - { - jsval v; - JS_IdToValue(cx, id, &v); - mStr = JS_ValueToString(cx, v); - if (!aThrow && !mStr && JS_IsExceptionPending(cx)) { - if (!JS_ReportPendingException(cx)) - JS_ClearPendingException(cx); - } - JS_AddNamedStringRoot(cx, &mStr, "Value ToString helper"); - } ToString(JSContext *aCx, jsval v, JSBool aThrow = JS_FALSE) : cx(aCx) , mThrow(aThrow) @@ -1671,7 +1658,6 @@ SrcNotes(JSContext *cx, JSScript *script) case SRC_CONT2LABEL: index = js_GetSrcNoteOffset(sn, 0); JS_GET_SCRIPT_ATOM(script, NULL, index, atom); - JS_ASSERT(ATOM_IS_STRING(atom)); str = ATOM_TO_STRING(atom); fprintf(gOutFile, " atom %u (", index); js_FileEscapedString(gOutFile, str, 0); @@ -2683,7 +2669,7 @@ split_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, if (!JS_NextProperty(cx, iterator, idp)) return JS_FALSE; - if (!JSBOXEDWORD_IS_VOID(*idp)) + if (!JSVAL_IS_VOID(*idp)) break; /* Fall through. */ @@ -2795,7 +2781,7 @@ split_getObjectOps(JSContext *cx, JSClass *clasp) } static JSBool -split_equality(JSContext *cx, JSObject *obj, const jsval *vp, JSBool *bp); +split_equality(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp); static JSObject * split_innerObject(JSContext *cx, JSObject *obj) @@ -2826,13 +2812,13 @@ static JSExtendedClass split_global_class = { }; static JSBool -split_equality(JSContext *cx, JSObject *obj, const jsval *vp, JSBool *bp) +split_equality(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp) { *bp = JS_FALSE; - if (JSVAL_IS_PRIMITIVE(*vp)) + if (JSVAL_IS_PRIMITIVE(*v)) return JS_TRUE; - JSObject *obj2 = JSVAL_TO_OBJECT(*vp); + JSObject *obj2 = JSVAL_TO_OBJECT(*v); if (JS_GET_CLASS(cx, obj2) != &split_global_class.base) return JS_TRUE; @@ -4399,7 +4385,7 @@ its_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, if (!JS_NextProperty(cx, iterator, idp)) return JS_FALSE; - if (!JSBOXEDWORD_IS_VOID(*idp)) + if (!JSVAL_IS_VOID(*idp)) break; /* Fall through. */