Remove jsboxedword, change jsid to be a jsval

This commit is contained in:
Luke Wagner 2010-06-02 19:09:04 -07:00
parent 7dddedeff0
commit 8f6c06b148
47 changed files with 549 additions and 1522 deletions

View File

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

View File

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

View File

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

View File

@ -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. */

View File

@ -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("<uninitialized>", 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;
}

View File

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

View File

@ -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 *,

View File

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

View File

@ -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<jsboxedword, 8> vector;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
static JS_ALWAYS_INLINE void
MakeValueRangeGCSafe(Value *vec, uintN len)
{

View File

@ -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<AutoIdArray *>(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<AutoNamespaces *>(this)->array;
MarkObjectVector(trc, array.length, reinterpret_cast<JSObject **>(array.vector),
"JSXMLArray");
MarkObjectRange(trc, array.length, reinterpret_cast<JSObject **>(array.vector),
"JSXMLArray");
array.cursors->trace(trc);
return;
}
@ -256,7 +256,7 @@ AutoGCRooter::trace(JSTracer *trc)
return;
case ID:
MarkBoxedWord(trc, static_cast<AutoIdRooter *>(this)->idval, "js::AutoIdRooter.val");
MarkId(trc, static_cast<AutoIdRooter *>(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<jsboxedword, 8> &vector = static_cast<AutoBoxedWordVector *>(this)->vector;
MarkBoxedWordRange(trc, vector.length(), vector.begin(), "js::AutoIdVector.vector");
return;
}
}
JS_ASSERT(tag >= 0);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -430,6 +430,16 @@ struct JSCGObjectList {
void finish(JSObjectArray *array);
};
class JSGCConstList {
js::Vector<js::Value> 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<JSAtom *, JSAtom *> ConstMap;
typedef js::HashMap<JSAtom *, js::Value> 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 */

View File

@ -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;
}

View File

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

View File

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

View File

@ -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<JSGCThing *>(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<jsdouble *>(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<jsdouble *>(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.

View File

@ -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<JSString **>(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. */

View File

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

View File

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

View File

@ -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<jsid>& ht, AutoBoxedWordVector& vec)
Enumerate(JSContext *cx, JSObject *obj, jsid id,
bool enumerable, uintN flags, HashSet<jsid>& 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<jsid> &ht, AutoBoxedWordVector& props)
EnumerateNativeProperties(JSContext *cx, JSObject *obj, uintN flags,
HashSet<jsid> &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<jsid> &ht, AutoBoxedWordVector& props)
EnumerateDenseArrayProperties(JSContext *cx, JSObject *obj, uintN flags,
HashSet<jsid> &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;

View File

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

View File

@ -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, "<non-string atom>\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);
}

View File

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

View File

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

View File

@ -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;
}

View File

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

View File

@ -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, &regs.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 = &regs.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)

View File

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

View File

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

View File

@ -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;
/*

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -75,7 +75,7 @@ static const jsbytecode emptyScriptCode[] = {JSOP_STOP, SRC_NULL};
/* static */ const JSScript JSScript::emptyScriptConst = {
const_cast<jsbytecode*>(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<jsbytecode*>(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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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. */