зеркало из https://github.com/mozilla/pjs.git
[JAEGER] Merge from fatval branch.
This commit is contained in:
Коммит
01c5a3c27c
|
@ -1017,9 +1017,9 @@ ifdef MOZ_PROFILE_GENERATE
|
|||
endif
|
||||
else # !WINNT || GNU_CC
|
||||
ifeq ($(CPP_PROG_LINK),1)
|
||||
$(CCC) -o $@ $(CXXFLAGS) $(WRAP_MALLOC_CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(SOLARIS_JEMALLOC_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(WRAP_MALLOC_LIB) $(EXE_DEF_FILE)
|
||||
$(CCC) -o $@ $(CXXFLAGS) $(WRAP_MALLOC_CFLAGS) $(PROGOBJS) $(RESFILE) $(DARWIN_EXE_LDFLAGS) $(WIN32_EXE_LDFLAGS) $(SOLARIS_JEMALLOC_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(WRAP_MALLOC_LIB) $(EXE_DEF_FILE)
|
||||
else # ! CPP_PROG_LINK
|
||||
$(CC) -o $@ $(CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(SOLARIS_JEMALLOC_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE)
|
||||
$(CC) -o $@ $(CFLAGS) $(PROGOBJS) $(RESFILE) $(DARWIN_EXE_LDFLAGS) $(WIN32_EXE_LDFLAGS) $(SOLARIS_JEMALLOC_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE)
|
||||
endif # CPP_PROG_LINK
|
||||
endif # WINNT && !GNU_CC
|
||||
endif # WINCE
|
||||
|
|
|
@ -539,7 +539,7 @@ JSRuntime::init(uint32 maxbytes)
|
|||
if (!js_InitGC(this, maxbytes) || !js_InitAtomState(this))
|
||||
return false;
|
||||
|
||||
#ifdef _M_X64
|
||||
#ifdef JS_64BIT
|
||||
if (!JSString::initStringTables())
|
||||
return false;
|
||||
#endif
|
||||
|
@ -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));
|
||||
|
|
|
@ -780,7 +780,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)
|
||||
|
@ -979,7 +979,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);
|
||||
|
@ -3319,6 +3319,10 @@ class Value
|
|||
return JSVAL_TO_PRIVATE_IMPL(data);
|
||||
}
|
||||
|
||||
void *asPrivateVoidPtrUnchecked() const {
|
||||
return JSVAL_TO_PRIVATE_IMPL(data);
|
||||
}
|
||||
|
||||
void setPrivateUint32(uint32 u) {
|
||||
setInt32((int32)u);
|
||||
}
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 *,
|
||||
|
|
|
@ -1380,7 +1380,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)
|
||||
|
|
|
@ -1238,7 +1238,6 @@ struct JSRuntime {
|
|||
JSGCArena *gcEmptyArenaList;
|
||||
#endif
|
||||
JSGCArenaList gcArenaList[FINALIZE_LIMIT];
|
||||
JSGCDoubleArenaList gcDoubleArenaList;
|
||||
js::RootedValueMap gcRootsHash;
|
||||
JSDHashTable gcLocksHash;
|
||||
jsrefcount gcKeepAtoms;
|
||||
|
@ -2231,8 +2230,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:
|
||||
|
@ -3058,48 +3056,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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -103,6 +103,7 @@ JSCodeGenerator::JSCodeGenerator(Parser *parser,
|
|||
arrayCompDepth(0),
|
||||
emitLevel(0),
|
||||
constMap(parser->context),
|
||||
constList(parser->context),
|
||||
globalUses(ContextAllocPolicy(parser->context))
|
||||
{
|
||||
flags = TCF_COMPILING;
|
||||
|
@ -1548,37 +1549,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;
|
||||
|
@ -1622,43 +1599,13 @@ js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp, JSStmtInfo *stmt
|
|||
return stmt;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
JSStmtInfo *stmt;
|
||||
JSObject *obj;
|
||||
|
@ -1668,7 +1615,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. */
|
||||
|
@ -1677,7 +1624,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;
|
||||
}
|
||||
|
@ -1708,11 +1655,7 @@ LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
|
|||
*/
|
||||
if (!sprop->writable() && !sprop->configurable() &&
|
||||
sprop->hasDefaultGetter() && SPROP_HAS_VALID_SLOT(sprop, scope)) {
|
||||
Value v = obj->lockedGetSlot(sprop->slot);
|
||||
if (!ValueToCompilerConstant(cx, v, constp)) {
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
return JS_FALSE;
|
||||
}
|
||||
*constp = obj->lockedGetSlot(sprop->slot);
|
||||
}
|
||||
}
|
||||
JS_UNLOCK_SCOPE(cx, scope);
|
||||
|
@ -3008,7 +2951,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;
|
||||
|
@ -3057,8 +2999,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)
|
||||
|
@ -3087,14 +3027,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
|
||||
|
@ -3107,9 +3059,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;
|
||||
|
@ -3223,30 +3173,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.
|
||||
|
@ -3254,7 +3196,6 @@ EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
|
|||
switchOp = JSOP_CONDSWITCH;
|
||||
continue;
|
||||
}
|
||||
pn3->pn_val = ATOM_KEY(atom);
|
||||
constPropagated = JS_TRUE;
|
||||
break;
|
||||
}
|
||||
|
@ -3262,15 +3203,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 */
|
||||
|
@ -3278,16 +3219,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;
|
||||
|
@ -3350,7 +3298,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;
|
||||
}
|
||||
}
|
||||
|
@ -3482,7 +3430,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;
|
||||
|
@ -3625,12 +3573,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;
|
||||
|
@ -7533,3 +7478,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;
|
||||
}
|
||||
|
|
|
@ -445,6 +445,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 */
|
||||
|
@ -484,9 +494,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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -394,6 +394,9 @@ WrapEscapingClosure(JSContext *cx, JSStackFrame *fp, JSObject *funobj, JSFunctio
|
|||
(script->trynotesOffset != 0)
|
||||
? script->trynotes()->length
|
||||
: 0,
|
||||
(script->constOffset != 0)
|
||||
? script->consts()->length
|
||||
: 0,
|
||||
(script->globalsOffset != 0)
|
||||
? script->globals()->length
|
||||
: 0);
|
||||
|
@ -516,11 +519,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)) {
|
||||
/*
|
||||
|
@ -569,8 +572,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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -596,10 +599,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;
|
||||
}
|
||||
|
@ -609,8 +612,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;
|
||||
}
|
||||
|
@ -1388,7 +1391,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;
|
||||
}
|
||||
|
@ -1467,7 +1470,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));
|
||||
|
||||
/*
|
||||
|
@ -1503,7 +1506,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,
|
||||
|
@ -2644,12 +2647,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
|
||||
|
@ -2703,7 +2700,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) {
|
||||
|
|
|
@ -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
|
||||
|
|
284
js/src/jsgc.cpp
284
js/src/jsgc.cpp
|
@ -825,8 +825,6 @@ InitGCArenaLists(JSRuntime *rt)
|
|||
arenaList->thingKind = i;
|
||||
arenaList->thingSize = GetFinalizableThingSize(i);
|
||||
}
|
||||
rt->gcDoubleArenaList.head = NULL;
|
||||
rt->gcDoubleArenaList.cursor = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -836,8 +834,6 @@ FinishGCArenaLists(JSRuntime *rt)
|
|||
rt->gcArenaList[i].head = NULL;
|
||||
rt->gcArenaList[i].cursor = NULL;
|
||||
}
|
||||
rt->gcDoubleArenaList.head = NULL;
|
||||
rt->gcDoubleArenaList.cursor = NULL;
|
||||
|
||||
rt->gcBytes = 0;
|
||||
|
||||
|
@ -983,7 +979,6 @@ JS_FRIEND_API(void)
|
|||
js_DumpGCStats(JSRuntime *rt, FILE *fp)
|
||||
{
|
||||
static const char *const GC_ARENA_NAMES[] = {
|
||||
"double",
|
||||
"object",
|
||||
"function",
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
|
@ -999,7 +994,7 @@ js_DumpGCStats(JSRuntime *rt, FILE *fp)
|
|||
"external_string_6",
|
||||
"external_string_7",
|
||||
};
|
||||
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(GC_ARENA_NAMES) == FINALIZE_LIMIT + 1);
|
||||
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(GC_ARENA_NAMES) == FINALIZE_LIMIT);
|
||||
|
||||
fprintf(fp, "\nGC allocation statistics:\n\n");
|
||||
|
||||
|
@ -1019,23 +1014,17 @@ js_DumpGCStats(JSRuntime *rt, FILE *fp)
|
|||
size_t sumLocalAlloc = 0;
|
||||
size_t sumFail = 0;
|
||||
size_t sumRetry = 0;
|
||||
for (int i = -1; i < (int) FINALIZE_LIMIT; i++) {
|
||||
for (int i = 0; i < (int) FINALIZE_LIMIT; i++) {
|
||||
size_t thingSize, thingsPerArena;
|
||||
JSGCArenaStats *st;
|
||||
if (i == -1) {
|
||||
thingSize = sizeof(jsdouble);
|
||||
thingsPerArena = DOUBLES_PER_ARENA;
|
||||
st = &rt->gcStats.doubleArenaStats;
|
||||
} else {
|
||||
thingSize = rt->gcArenaList[i].thingSize;
|
||||
thingsPerArena = ThingsPerArena(thingSize);
|
||||
st = &rt->gcStats.arenaStats[i];
|
||||
}
|
||||
thingSize = rt->gcArenaList[i].thingSize;
|
||||
thingsPerArena = ThingsPerArena(thingSize);
|
||||
st = &rt->gcStats.arenaStats[i];
|
||||
if (st->maxarenas == 0)
|
||||
continue;
|
||||
fprintf(fp,
|
||||
"%s arenas (thing size %lu, %lu things per arena):",
|
||||
GC_ARENA_NAMES[i + 1], UL(thingSize), UL(thingsPerArena));
|
||||
GC_ARENA_NAMES[i], UL(thingSize), UL(thingsPerArena));
|
||||
putc('\n', fp);
|
||||
fprintf(fp, " arenas before GC: %lu\n", UL(st->narenas));
|
||||
fprintf(fp, " new arenas before GC: %lu (%.1f%%)\n",
|
||||
|
@ -1068,23 +1057,17 @@ js_DumpGCStats(JSRuntime *rt, FILE *fp)
|
|||
}
|
||||
|
||||
fputs("Never used arenas:\n", fp);
|
||||
for (int i = -1; i < (int) FINALIZE_LIMIT; i++) {
|
||||
for (int i = 0; i < (int) FINALIZE_LIMIT; i++) {
|
||||
size_t thingSize, thingsPerArena;
|
||||
JSGCArenaStats *st;
|
||||
if (i == -1) {
|
||||
thingSize = sizeof(jsdouble);
|
||||
thingsPerArena = DOUBLES_PER_ARENA;
|
||||
st = &rt->gcStats.doubleArenaStats;
|
||||
} else {
|
||||
thingSize = rt->gcArenaList[i].thingSize;
|
||||
thingsPerArena = ThingsPerArena(thingSize);
|
||||
st = &rt->gcStats.arenaStats[i];
|
||||
}
|
||||
thingSize = rt->gcArenaList[i].thingSize;
|
||||
thingsPerArena = ThingsPerArena(thingSize);
|
||||
st = &rt->gcStats.arenaStats[i];
|
||||
if (st->maxarenas != 0)
|
||||
continue;
|
||||
fprintf(fp,
|
||||
"%s (thing size %lu, %lu things per arena)\n",
|
||||
GC_ARENA_NAMES[i + 1], UL(thingSize), UL(thingsPerArena));
|
||||
GC_ARENA_NAMES[i], UL(thingSize), UL(thingsPerArena));
|
||||
}
|
||||
fprintf(fp, "\nTOTAL STATS:\n");
|
||||
fprintf(fp, " bytes allocated: %lu\n", UL(rt->gcBytes));
|
||||
|
@ -1331,14 +1314,12 @@ JSGCFreeLists::purge()
|
|||
*p = NULL;
|
||||
}
|
||||
}
|
||||
doubles = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
JSGCFreeLists::moveTo(JSGCFreeLists *another)
|
||||
{
|
||||
*another = *this;
|
||||
doubles = NULL;
|
||||
PodArrayZero(finalizables);
|
||||
JS_ASSERT(isEmpty());
|
||||
}
|
||||
|
@ -1557,179 +1538,6 @@ js_NewFinalizableGCThing(JSContext *cx, unsigned thingKind)
|
|||
return thing;
|
||||
}
|
||||
|
||||
static JSGCThing *
|
||||
TurnUsedArenaIntoDoubleList(JSGCArena *a)
|
||||
{
|
||||
JSGCThing *head;
|
||||
JSGCThing **tailp = &head;
|
||||
jsuword thing = a->toPageStart();
|
||||
jsbitmap *markBitmap = a->getMarkBitmap();
|
||||
jsbitmap *lastMarkWord = markBitmap + GC_MARK_BITMAP_WORDS - 1;
|
||||
|
||||
for (jsbitmap *m = markBitmap; m <= lastMarkWord; ++m) {
|
||||
JS_ASSERT(thing < a->toPageStart() + GC_ARENA_SIZE);
|
||||
JS_ASSERT((thing - a->toPageStart()) %
|
||||
(JS_BITS_PER_WORD * sizeof(jsdouble)) == 0);
|
||||
|
||||
jsbitmap bits = *m;
|
||||
if (bits == jsbitmap(-1)) {
|
||||
thing += JS_BITS_PER_WORD * sizeof(jsdouble);
|
||||
} else {
|
||||
/*
|
||||
* We have some zero bits. Turn corresponding cells into a list
|
||||
* unrolling the loop for better performance.
|
||||
*/
|
||||
const unsigned unroll = 4;
|
||||
const jsbitmap unrollMask = (jsbitmap(1) << unroll) - 1;
|
||||
JS_STATIC_ASSERT((JS_BITS_PER_WORD & unrollMask) == 0);
|
||||
|
||||
for (unsigned n = 0; n != JS_BITS_PER_WORD; n += unroll) {
|
||||
jsbitmap bitsChunk = bits & unrollMask;
|
||||
bits >>= unroll;
|
||||
if (bitsChunk == unrollMask) {
|
||||
thing += unroll * sizeof(jsdouble);
|
||||
} else {
|
||||
#define DO_BIT(bit) \
|
||||
if (!(bitsChunk & (jsbitmap(1) << (bit)))) { \
|
||||
JS_ASSERT(thing - a->toPageStart() <= \
|
||||
(DOUBLES_PER_ARENA - 1) * sizeof(jsdouble));\
|
||||
JSGCThing *t = reinterpret_cast<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.
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -35,14 +35,14 @@
|
|||
#include "jstypes.h"
|
||||
#include "jsstdint.h"
|
||||
#include "jsgcchunk.h"
|
||||
#ifdef JS_64BIT
|
||||
# include "jsstr.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef XP_WIN
|
||||
# include <windows.h>
|
||||
|
||||
#ifdef _M_X64
|
||||
# include "jsstr.h"
|
||||
#endif
|
||||
|
||||
# ifdef _MSC_VER
|
||||
# pragma warning( disable: 4267 4996 4146 )
|
||||
# endif
|
||||
|
@ -183,27 +183,6 @@ UnmapPages(void *addr, size_t size)
|
|||
NtFreeVirtualMemory(INVALID_HANDLE_VALUE, &addr, &size, MEM_RELEASE);
|
||||
}
|
||||
|
||||
bool
|
||||
JSString::initStringTables()
|
||||
{
|
||||
char *p = (char *) MapPages(NULL, unitStringTableSize + intStringTableSize);
|
||||
if (!p)
|
||||
return false;
|
||||
unitStringTable = (JSString*) memcpy(p, staticUnitStringTable, unitStringTableSize);
|
||||
intStringTable = (JSString*) memcpy(p + unitStringTableSize,
|
||||
staticIntStringTable, intStringTableSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
JSString::freeStringTables()
|
||||
{
|
||||
UnmapPages(unitStringTable, unitStringTableSize + intStringTableSize);
|
||||
unitStringTable = NULL;
|
||||
intStringTable = NULL;
|
||||
}
|
||||
|
||||
# else /* _M_X64 */
|
||||
|
||||
static void *
|
||||
|
@ -281,6 +260,53 @@ MapAlignedPages(size_t size, size_t alignment)
|
|||
|
||||
# else /* JS_GC_HAS_MAP_ALIGN */
|
||||
|
||||
# if defined(__MACH__) && defined(__APPLE__) && defined(__x86_64__)
|
||||
|
||||
// Make sure the result is in the 32-bit address region.
|
||||
static void *
|
||||
MapPages(void *addr, size_t size)
|
||||
{
|
||||
void * const start = (void *) 0x10000;
|
||||
void * const end = (void *) 0x100000000;
|
||||
|
||||
// If an addr is given, try once there.
|
||||
if (addr) {
|
||||
JS_ASSERT(addr < end);
|
||||
void *p = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
if (p == MAP_FAILED)
|
||||
return NULL;
|
||||
if (p != addr) {
|
||||
JS_ALWAYS_TRUE(munmap(p, size) == 0);
|
||||
return NULL;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
// FIXME: this depends on implementation details of OSX mmap, namely
|
||||
// that it searches for free memory starting from the hint,
|
||||
// so that it will find free memory addresses in 32-bit space
|
||||
// if it exists.
|
||||
static void *base = start;
|
||||
while (true) {
|
||||
void *p = mmap(base, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
if (p == MAP_FAILED)
|
||||
return NULL;
|
||||
// Got a region in range, so return it.
|
||||
if (start <= p && p < end) {
|
||||
base = (void *) (uintptr_t(p) + size);
|
||||
return p;
|
||||
}
|
||||
// Out of range. If we started past 'start', then we can try
|
||||
// again from there.
|
||||
munmap(p, size);
|
||||
if (base != start)
|
||||
return NULL;
|
||||
base = start;
|
||||
}
|
||||
}
|
||||
|
||||
# else /* DARWIN && __x86_64__ */
|
||||
|
||||
static void *
|
||||
MapPages(void *addr, size_t size)
|
||||
{
|
||||
|
@ -301,6 +327,8 @@ MapPages(void *addr, size_t size)
|
|||
return p;
|
||||
}
|
||||
|
||||
# endif /* DARWIN && __x86_64__ */
|
||||
|
||||
# endif /* !JS_GC_HAS_MAP_ALIGN */
|
||||
|
||||
static void
|
||||
|
@ -311,6 +339,29 @@ UnmapPages(void *addr, size_t size)
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef JS_64BIT
|
||||
bool
|
||||
JSString::initStringTables()
|
||||
{
|
||||
char *p = (char *) MapPages(NULL, unitStringTableSize + intStringTableSize);
|
||||
if (!p)
|
||||
return false;
|
||||
unitStringTable = (JSString*) memcpy(p, staticUnitStringTable, unitStringTableSize);
|
||||
intStringTable = (JSString*) memcpy(p + unitStringTableSize,
|
||||
staticIntStringTable, intStringTableSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
JSString::freeStringTables()
|
||||
{
|
||||
UnmapPages(unitStringTable, unitStringTableSize + intStringTableSize);
|
||||
unitStringTable = NULL;
|
||||
intStringTable = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace js {
|
||||
|
||||
inline void *
|
||||
|
|
|
@ -343,7 +343,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);
|
||||
|
@ -983,7 +983,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,
|
||||
|
@ -1158,65 +1158,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;
|
||||
}
|
||||
|
@ -2060,21 +2006,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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2247,6 +2186,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
|
||||
|
|
|
@ -401,15 +401,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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -3946,8 +3946,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);
|
||||
|
@ -4792,7 +4792,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;
|
||||
}
|
||||
|
@ -4870,7 +4870,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);
|
||||
}
|
||||
|
||||
|
@ -5581,11 +5581,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;
|
||||
|
@ -6280,8 +6280,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));
|
||||
}
|
||||
|
||||
|
@ -6347,7 +6345,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);
|
||||
}
|
||||
|
||||
|
|
|
@ -405,7 +405,7 @@ struct JSObject {
|
|||
|
||||
void *getPrivate() const {
|
||||
JS_ASSERT(getClass()->flags & JSCLASS_HAS_PRIVATE);
|
||||
void *priv = fslots[JSSLOT_PRIVATE].asPrivateVoidPtr();
|
||||
void *priv = fslots[JSSLOT_PRIVATE].asPrivateVoidPtrUnchecked();
|
||||
return priv;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
@ -454,12 +444,12 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc,
|
|||
pc2 += UINT16_LEN;
|
||||
fprintf(fp, " offset %d npairs %u", (intN) off, (uintN) npairs);
|
||||
while (npairs) {
|
||||
JS_GET_SCRIPT_ATOM(script, pc, GET_INDEX(pc2), atom);
|
||||
uint16 constIndex = GET_INDEX(pc2);
|
||||
pc2 += INDEX_LEN;
|
||||
off = GetJumpOffset(pc, pc2);
|
||||
pc2 += jmplen;
|
||||
|
||||
bytes = ToDisassemblySource(cx, ExtAtomToJsval(atom));
|
||||
bytes = ToDisassemblySource(cx, Jsvalify(script->getConst(constIndex)));
|
||||
if (!bytes)
|
||||
return 0;
|
||||
fprintf(fp, "\n\t%s: %d", bytes, (intN) off);
|
||||
|
@ -483,7 +473,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);
|
||||
|
@ -1580,8 +1570,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;
|
||||
|
||||
|
@ -3899,7 +3888,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;
|
||||
|
@ -4064,11 +4052,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);
|
||||
|
@ -4347,11 +4337,11 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
} else {
|
||||
table[k].label = NULL;
|
||||
}
|
||||
JS_GET_SCRIPT_ATOM(jp->script, pc, GET_INDEX(pc2), atom);
|
||||
uint16 constIndex = GET_INDEX(pc2);
|
||||
pc2 += INDEX_LEN;
|
||||
off2 = GetJumpOffset(pc, pc2);
|
||||
pc2 += jmplen;
|
||||
table[k].key = ExtAtomToJsval(atom);
|
||||
table[k].key = Jsvalify(jp->script->getConst(constIndex));
|
||||
table[k].offset = off2;
|
||||
}
|
||||
|
||||
|
|
|
@ -337,12 +337,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) \
|
||||
|
|
|
@ -441,9 +441,9 @@ END_CASE(JSOP_ANDX)
|
|||
#define FETCH_ELEMENT_ID(obj, n, id) \
|
||||
JS_BEGIN_MACRO \
|
||||
const Value &idval_ = regs.sp[n]; \
|
||||
int32_t i; \
|
||||
if (ValueFitsInInt32(idval_, &i) && INT32_FITS_IN_JSID(i)) { \
|
||||
id = INT_TO_JSID(i); \
|
||||
int32_t i_; \
|
||||
if (ValueFitsInInt32(idval_, &i_)) { \
|
||||
id = INT_TO_JSID(i_); \
|
||||
} else { \
|
||||
if (!js_InternNonIntElementId(cx, obj, idval_, &id, ®s.sp[n])) \
|
||||
goto error; \
|
||||
|
@ -458,10 +458,10 @@ END_CASE(JSOP_ANDX)
|
|||
regs.sp -= spdec; \
|
||||
if (cond == (diff_ != 0)) { \
|
||||
++regs.pc; \
|
||||
len = GET_JUMP_OFFSET(regs.pc); \
|
||||
len = GET_JUMP_OFFSET(regs.pc); \
|
||||
BRANCH(len); \
|
||||
} \
|
||||
len = 1 + JSOP_IFEQ_LENGTH; \
|
||||
len = 1 + JSOP_IFEQ_LENGTH; \
|
||||
DO_NEXT_OP(len); \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
@ -826,7 +826,7 @@ END_CASE(JSOP_BITAND)
|
|||
#define EXTENDED_EQUALITY_OP(OP) \
|
||||
if (((clasp = l->getClass())->flags & JSCLASS_IS_EXTENDED) && \
|
||||
((ExtendedClass *)clasp)->equality) { \
|
||||
if (!((ExtendedClass *)clasp)->equality(cx, l, &lval, &cond)) \
|
||||
if (!((ExtendedClass *)clasp)->equality(cx, l, &rval, &cond)) \
|
||||
goto error; \
|
||||
cond = cond OP JS_TRUE; \
|
||||
} else
|
||||
|
@ -1049,7 +1049,6 @@ BEGIN_CASE(JSOP_ADD)
|
|||
#if JS_HAS_XML_SUPPORT
|
||||
if (lval.isNonFunObj() && lval.asObject().isXML() &&
|
||||
rval.isNonFunObj() && rval.asObject().isXML()) {
|
||||
Value rval;
|
||||
if (!js_ConcatenateXML(cx, &lval.asObject(), &rval.asObject(), &rval))
|
||||
goto error;
|
||||
regs.sp--;
|
||||
|
@ -2091,13 +2090,8 @@ BEGIN_CASE(JSOP_GETELEM)
|
|||
copyFrom = ®s.sp[-1];
|
||||
}
|
||||
}
|
||||
int32_t i32 = rref.asInt32();
|
||||
if (INT32_FITS_IN_JSID(i32))
|
||||
id = INT_TO_JSID(i32);
|
||||
else
|
||||
goto intern_big_int;
|
||||
id = INT_TO_JSID(rref.asInt32());
|
||||
} else {
|
||||
intern_big_int:
|
||||
if (!js_InternNonIntElementId(cx, obj, rref, &id))
|
||||
goto error;
|
||||
}
|
||||
|
@ -2534,10 +2528,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)
|
||||
|
||||
|
@ -2711,9 +2705,7 @@ 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); \
|
||||
Value rval = script->getConst(GET_INDEX(pc2)); \
|
||||
MATCH_CODE \
|
||||
pc2 += INDEX_LEN; \
|
||||
if (match) \
|
||||
|
@ -2729,25 +2721,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
|
||||
|
@ -4076,7 +4061,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)
|
||||
|
||||
|
@ -4162,7 +4147,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)
|
||||
|
||||
|
|
|
@ -90,6 +90,8 @@
|
|||
#include "jsdhash.h"
|
||||
#endif
|
||||
|
||||
#include "jsatominlines.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
/*
|
||||
|
@ -4212,7 +4214,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;
|
||||
|
||||
|
@ -8122,8 +8124,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 */
|
||||
|
@ -8151,8 +8156,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 */
|
||||
|
@ -8236,19 +8244,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) {
|
||||
|
|
|
@ -335,7 +335,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 */
|
||||
|
@ -387,7 +387,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
|
||||
|
|
|
@ -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;
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
340
js/src/jspubtd.h
340
js/src/jspubtd.h
|
@ -238,6 +238,7 @@ JSValueMask32;
|
|||
#endif
|
||||
|
||||
typedef VALUE_ALIGNMENT uint64 jsval;
|
||||
typedef VALUE_ALIGNMENT uint64 jsid;
|
||||
|
||||
#define BUILD_JSVAL(mask32, payload) ((jsval)((((uint64)(uint32)(mask32)) << 32) | (uint32)(payload)))
|
||||
|
||||
|
@ -249,7 +250,8 @@ typedef enum JSWhyMagic
|
|||
* to js_Enumerate, which really means the object can be
|
||||
* enumerated like a native object. */
|
||||
JS_NO_ITER_VALUE, /* there is not a pending iterator value */
|
||||
JS_GENERATOR_CLOSING /* exception value thrown when closing a generator */
|
||||
JS_GENERATOR_CLOSING, /* exception value thrown when closing a generator */
|
||||
JS_NO_CONSTANT /* compiler sentinel value */
|
||||
} JSWhyMagic;
|
||||
|
||||
#if !defined(IS_LITTLE_ENDIAN)
|
||||
|
@ -608,324 +610,6 @@ JSVAL_TRACE_KIND_IMPL(jsval_layout l)
|
|||
return (uint32)(l.s.mask32 == JSVAL_MASK32_STRING);
|
||||
}
|
||||
|
||||
/*
|
||||
* Boxed word macros (private engine detail)
|
||||
*
|
||||
* N.B. jsboxedword and the JSBOXEDWORD macros are engine-private. Callers
|
||||
* should use only JSID macros (below) instead.
|
||||
*
|
||||
* The jsboxedword type is used by atoms and jsids. Eventually, the ability to
|
||||
* atomize any primitive will be removed and atoms will simply be unboxed,
|
||||
* interned JSString*s. However, jsids will always need boxing. Using a
|
||||
* one-word boxing scheme instead of the normal jsval 16-byte unboxed scheme
|
||||
* allows jsids to be passed by value without penalty, since jsids never are
|
||||
* doubles nor are jsids used to build typemaps for entering/leaving trace.
|
||||
*/
|
||||
|
||||
typedef jsword jsboxedword;
|
||||
|
||||
#define JSBOXEDWORD_TYPE_OBJECT 0x0
|
||||
#define JSBOXEDWORD_TYPE_INT 0x1
|
||||
#define JSBOXEDWORD_TYPE_DOUBLE 0x2
|
||||
#define JSBOXEDWORD_TYPE_STRING 0x4
|
||||
#define JSBOXEDWORD_TYPE_SPECIAL 0x6
|
||||
|
||||
/* Type tag bitfield length and derived macros. */
|
||||
#define JSBOXEDWORD_TAGBITS 3
|
||||
#define JSBOXEDWORD_TAGMASK ((jsboxedword) JS_BITMASK(JSBOXEDWORD_TAGBITS))
|
||||
#define JSBOXEDWORD_ALIGN JS_BIT(JSBOXEDWORD_TAGBITS)
|
||||
|
||||
static const jsboxedword JSBOXEDWORD_NULL = (jsboxedword)0x0;
|
||||
static const jsboxedword JSBOXEDWORD_FALSE = (jsboxedword)0x6;
|
||||
static const jsboxedword JSBOXEDWORD_TRUE = (jsboxedword)0xe;
|
||||
static const jsboxedword JSBOXEDWORD_VOID = (jsboxedword)0x16;
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_NULL(jsboxedword w)
|
||||
{
|
||||
return w == JSBOXEDWORD_NULL;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_VOID(jsboxedword w)
|
||||
{
|
||||
return w == JSBOXEDWORD_VOID;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE unsigned
|
||||
JSBOXEDWORD_TAG(jsboxedword w)
|
||||
{
|
||||
return (unsigned)(w & JSBOXEDWORD_TAGMASK);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsboxedword
|
||||
JSBOXEDWORD_SETTAG(jsboxedword w, unsigned t)
|
||||
{
|
||||
return w | t;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsboxedword
|
||||
JSBOXEDWORD_CLRTAG(jsboxedword w)
|
||||
{
|
||||
return w & ~(jsboxedword)JSBOXEDWORD_TAGMASK;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_DOUBLE(jsboxedword w)
|
||||
{
|
||||
return JSBOXEDWORD_TAG(w) == JSBOXEDWORD_TYPE_DOUBLE;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE double *
|
||||
JSBOXEDWORD_TO_DOUBLE(jsboxedword w)
|
||||
{
|
||||
JS_ASSERT(JSBOXEDWORD_IS_DOUBLE(w));
|
||||
return (double *)JSBOXEDWORD_CLRTAG(w);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsboxedword
|
||||
DOUBLE_TO_JSBOXEDWORD(double *d)
|
||||
{
|
||||
JS_ASSERT(((JSUword)d & JSBOXEDWORD_TAGMASK) == 0);
|
||||
return (jsboxedword)((JSUword)d | JSBOXEDWORD_TYPE_DOUBLE);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_STRING(jsboxedword w)
|
||||
{
|
||||
return JSBOXEDWORD_TAG(w) == JSBOXEDWORD_TYPE_STRING;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSString *
|
||||
JSBOXEDWORD_TO_STRING(jsboxedword w)
|
||||
{
|
||||
JS_ASSERT(JSBOXEDWORD_IS_STRING(w));
|
||||
return (JSString *)JSBOXEDWORD_CLRTAG(w);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_SPECIAL(jsboxedword w)
|
||||
{
|
||||
return JSBOXEDWORD_TAG(w) == JSBOXEDWORD_TYPE_SPECIAL;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsint
|
||||
JSBOXEDWORD_TO_SPECIAL(jsboxedword w)
|
||||
{
|
||||
JS_ASSERT(JSBOXEDWORD_IS_SPECIAL(w));
|
||||
return jsint(w >> JSBOXEDWORD_TAGBITS);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsboxedword
|
||||
SPECIAL_TO_JSBOXEDWORD(jsint i)
|
||||
{
|
||||
return (i << JSBOXEDWORD_TAGBITS) | JSBOXEDWORD_TYPE_SPECIAL;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_BOOLEAN(jsboxedword w)
|
||||
{
|
||||
return (w & ~((jsboxedword)1 << JSBOXEDWORD_TAGBITS)) == JSBOXEDWORD_TYPE_SPECIAL;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_TO_BOOLEAN(jsboxedword w)
|
||||
{
|
||||
JS_ASSERT(w == JSBOXEDWORD_TRUE || w == JSBOXEDWORD_FALSE);
|
||||
return JSBOXEDWORD_TO_SPECIAL(w);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsboxedword
|
||||
BOOLEAN_TO_JSBOXEDWORD(JSBool b)
|
||||
{
|
||||
JS_ASSERT(b == JS_TRUE || b == JS_FALSE);
|
||||
return SPECIAL_TO_JSBOXEDWORD(b);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsboxedword
|
||||
STRING_TO_JSBOXEDWORD(JSString *str)
|
||||
{
|
||||
JS_ASSERT(((JSUword)str & JSBOXEDWORD_TAGMASK) == 0);
|
||||
return (jsboxedword)str | JSBOXEDWORD_TYPE_STRING;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_GCTHING(jsboxedword w)
|
||||
{
|
||||
return !(w & JSBOXEDWORD_TYPE_INT) &&
|
||||
JSBOXEDWORD_TAG(w) != JSBOXEDWORD_TYPE_SPECIAL;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void *
|
||||
JSBOXEDWORD_TO_GCTHING(jsboxedword w)
|
||||
{
|
||||
JS_ASSERT(JSBOXEDWORD_IS_GCTHING(w));
|
||||
return (void *)JSBOXEDWORD_CLRTAG(w);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE uint32
|
||||
JSBOXEDWORD_TRACE_KIND(jsboxedword w)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
unsigned tag = JSBOXEDWORD_TAG(w);
|
||||
JS_ASSERT(tag == 0x0 || tag == 0x2 || tag == 0x4);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We need to map:
|
||||
* XXXXXXXXXXXXXXXXXXXXXXXXXXXXX000 -> 00 (object)
|
||||
* XXXXXXXXXXXXXXXXXXXXXXXXXXXXX010 -> 10 (double)
|
||||
* XXXXXXXXXXXXXXXXXXXXXXXXXXXXX100 -> 01 (string)
|
||||
*/
|
||||
return (w | ((w & 0x4) >> 2)) & 0x3;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_OBJECT(jsboxedword w)
|
||||
{
|
||||
return JSBOXEDWORD_TAG(w) == JSBOXEDWORD_TYPE_OBJECT;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSObject *
|
||||
JSBOXEDWORD_TO_OBJECT(jsboxedword w)
|
||||
{
|
||||
JS_ASSERT(JSBOXEDWORD_IS_OBJECT(w));
|
||||
return (JSObject *)JSBOXEDWORD_TO_GCTHING(w);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsboxedword
|
||||
OBJECT_TO_JSBOXEDWORD(JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(((JSUword)obj & JSBOXEDWORD_TAGMASK) == 0);
|
||||
return (jsboxedword)obj | JSBOXEDWORD_TYPE_OBJECT;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_PRIMITIVE(jsboxedword w)
|
||||
{
|
||||
return !JSBOXEDWORD_IS_OBJECT(w) || JSBOXEDWORD_IS_NULL(w);
|
||||
}
|
||||
|
||||
/* Domain limits for the jsboxedword int type. */
|
||||
#define JSBOXEDWORD_INT_BITS 31
|
||||
#define JSBOXEDWORD_INT_POW2(n) ((jsboxedword)1 << (n))
|
||||
#define JSBOXEDWORD_INT_MIN (-JSBOXEDWORD_INT_POW2(30))
|
||||
#define JSBOXEDWORD_INT_MAX (JSBOXEDWORD_INT_POW2(30) - 1)
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
INT32_FITS_IN_JSBOXEDWORD(jsint i)
|
||||
{
|
||||
return ((jsuint)(i) - (jsuint)JSBOXEDWORD_INT_MIN <=
|
||||
(jsuint)(JSBOXEDWORD_INT_MAX - JSBOXEDWORD_INT_MIN));
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSBOXEDWORD_IS_INT(jsboxedword w)
|
||||
{
|
||||
return w & JSBOXEDWORD_TYPE_INT;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsint
|
||||
JSBOXEDWORD_TO_INT(jsboxedword v)
|
||||
{
|
||||
JS_ASSERT(JSBOXEDWORD_IS_INT(v));
|
||||
return (jsint)(v >> 1);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsboxedword
|
||||
INT_TO_JSBOXEDWORD(jsint i)
|
||||
{
|
||||
JS_ASSERT(INT32_FITS_IN_JSBOXEDWORD(i));
|
||||
return (i << 1) | JSBOXEDWORD_TYPE_INT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Identifier (jsid) macros.
|
||||
*/
|
||||
|
||||
typedef jsboxedword jsid;
|
||||
struct JSAtom;
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSID_IS_ATOM(jsid id)
|
||||
{
|
||||
return JSBOXEDWORD_IS_STRING((jsboxedword)id);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSAtom *
|
||||
JSID_TO_ATOM(jsid id)
|
||||
{
|
||||
JS_ASSERT(JSID_IS_ATOM(id));
|
||||
return (JSAtom *)id;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSString *
|
||||
JSID_TO_STRING(jsid id)
|
||||
{
|
||||
JS_ASSERT(JSID_IS_ATOM(id));
|
||||
return JSBOXEDWORD_TO_STRING(id);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsid
|
||||
ATOM_TO_JSID(JSAtom *atom)
|
||||
{
|
||||
JS_ASSERT(JSBOXEDWORD_IS_STRING((jsboxedword)atom));
|
||||
return (jsid)atom;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
INT32_FITS_IN_JSID(int32 i)
|
||||
{
|
||||
return INT32_FITS_IN_JSBOXEDWORD(i);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSID_IS_INT(jsid id)
|
||||
{
|
||||
return JSBOXEDWORD_IS_INT((jsboxedword)id);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE int32
|
||||
JSID_TO_INT(jsid id)
|
||||
{
|
||||
return JSBOXEDWORD_TO_INT((jsboxedword)id);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsid
|
||||
INT_TO_JSID(int32 i)
|
||||
{
|
||||
return (jsid)INT_TO_JSBOXEDWORD(i);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSID_IS_OBJECT(jsid id)
|
||||
{
|
||||
return JSBOXEDWORD_IS_OBJECT((jsboxedword)id);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSObject *
|
||||
JSID_TO_OBJECT(jsid id)
|
||||
{
|
||||
return JSBOXEDWORD_TO_OBJECT((jsboxedword)id);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsid
|
||||
OBJECT_TO_JSID(JSObject *obj)
|
||||
{
|
||||
return (jsid)OBJECT_TO_JSBOXEDWORD(obj);
|
||||
}
|
||||
|
||||
/* TODO: get JSID/JSBOXEDWORD story together. */
|
||||
/* Objects and strings (no doubles in jsids). */
|
||||
#define JSID_IS_GCTHING(id) JSBOXEDWORD_IS_GCTHING(id)
|
||||
#define JSID_TO_GCTHING(id) (JS_ASSERT(JSID_IS_GCTHING((id))), \
|
||||
JSBOXEDWORD_TO_GCTHING((jsboxedword)(id)))
|
||||
#define JSID_TRACE_KIND(id) (JS_ASSERT(JSID_IS_GCTHING((id))), \
|
||||
JSBOXEDWORD_TRACE_KIND((jsboxedword)(id)))
|
||||
|
||||
JS_PUBLIC_API(jsval)
|
||||
JSID_TO_JSVAL(jsid id);
|
||||
|
||||
/* JSClass (and JSObjectOps where appropriate) function pointer typedefs. */
|
||||
|
||||
/*
|
||||
|
@ -936,7 +620,7 @@ JSID_TO_JSVAL(jsid id);
|
|||
* obj[id] can't be deleted (because it's permanent).
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSPropertyOp)(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
(* JSPropertyOp)(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
/*
|
||||
* This function type is used for callbacks that enumerate the properties of
|
||||
|
@ -967,7 +651,7 @@ typedef JSBool
|
|||
*/
|
||||
typedef JSBool
|
||||
(* JSNewEnumerateOp)(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
jsval *statep, jsid *idp);
|
||||
jsval *statep, jsval *idp);
|
||||
|
||||
/*
|
||||
* The old-style JSClass.enumerate op should define all lazy properties not
|
||||
|
@ -989,7 +673,7 @@ typedef JSBool
|
|||
* NB: JSNewResolveOp provides a cheaper way to resolve lazy properties.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSResolveOp)(JSContext *cx, JSObject *obj, jsid id);
|
||||
(* JSResolveOp)(JSContext *cx, JSObject *obj, jsval id);
|
||||
|
||||
/*
|
||||
* Like JSResolveOp, but flags provide contextual information as follows:
|
||||
|
@ -1021,7 +705,7 @@ typedef JSBool
|
|||
* *objp without a new JSClass flag.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSNewResolveOp)(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
(* JSNewResolveOp)(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
||||
JSObject **objp);
|
||||
|
||||
/*
|
||||
|
@ -1088,7 +772,7 @@ typedef JSObjectOps *
|
|||
* specialize access checks.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
|
||||
(* JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsval id, JSAccessMode mode,
|
||||
jsval *vp);
|
||||
|
||||
/*
|
||||
|
@ -1194,7 +878,7 @@ typedef uint32
|
|||
*
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSEqualityOp)(JSContext *cx, JSObject *obj, const jsval *vp, JSBool *bp);
|
||||
(* JSEqualityOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
|
||||
|
||||
/*
|
||||
* A generic type for functions mapping an object to another object, or null
|
||||
|
@ -1377,16 +1061,16 @@ typedef JSBool
|
|||
typedef JSBool
|
||||
(* FastNative)(JSContext *cx, uintN argc, Value *vp);
|
||||
typedef JSBool
|
||||
(* PropertyOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp);
|
||||
(* PropertyOp)(JSContext *cx, JSObject *obj, jsval id, Value *vp);
|
||||
typedef JSBool
|
||||
(* ConvertOp)(JSContext *cx, JSObject *obj, JSType type, Value *vp);
|
||||
typedef JSBool
|
||||
(* NewEnumerateOp)(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
Value *statep, jsid *idp);
|
||||
Value *statep, jsval *idp);
|
||||
typedef JSBool
|
||||
(* HasInstanceOp)(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp);
|
||||
typedef JSBool
|
||||
(* CheckAccessOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
|
||||
(* CheckAccessOp)(JSContext *cx, JSObject *obj, jsval id, JSAccessMode mode,
|
||||
Value *vp);
|
||||
typedef JSObjectOps *
|
||||
(* GetObjectOps)(JSContext *cx, Class *clasp);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -76,7 +76,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, 0, true, false, false, false,
|
||||
1, JSVERSION_DEFAULT, 0, 0, 0, 0, 0, 0, 0, true, false, false, false,
|
||||
const_cast<jsbytecode*>(emptyScriptCode),
|
||||
{0, NULL}, NULL, 0, 0, 0, NULL
|
||||
};
|
||||
|
@ -92,7 +92,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;
|
||||
|
@ -102,7 +102,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;
|
||||
|
||||
|
@ -150,7 +150,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, 0);
|
||||
script = js_NewScript(cx, 1, 1, 0, 0, 0, 0, 0, 0, 0);
|
||||
if (!script)
|
||||
return JS_FALSE;
|
||||
|
||||
|
@ -190,6 +190,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))
|
||||
|
@ -213,12 +215,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, 0);
|
||||
nregexps, ntrynotes, nconsts, 0);
|
||||
if (!script)
|
||||
return JS_FALSE;
|
||||
|
||||
|
@ -371,6 +375,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;
|
||||
|
||||
|
@ -810,16 +819,16 @@ 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 nglobals)
|
||||
uint32 ntrynotes, uint32 nconsts, uint32 nglobals)
|
||||
{
|
||||
size_t size, vectorSize;
|
||||
JSScript *script;
|
||||
uint8 *cursor;
|
||||
unsigned constPadding = 0;
|
||||
|
||||
size = sizeof(JSScript) +
|
||||
sizeof(JSAtom *) * natoms +
|
||||
length * sizeof(jsbytecode) +
|
||||
nsrcnotes * sizeof(jssrcnote);
|
||||
sizeof(JSAtom *) * natoms;
|
||||
|
||||
if (nobjects != 0)
|
||||
size += sizeof(JSObjectArray) + nobjects * sizeof(JSObject *);
|
||||
if (nupvars != 0)
|
||||
|
@ -831,6 +840,19 @@ js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natoms,
|
|||
if (nglobals != 0)
|
||||
size += sizeof(GlobalSlotArray) + nglobals * sizeof(GlobalSlotArray::Entry);
|
||||
|
||||
if (nconsts != 0) {
|
||||
size += sizeof(JSConstArray);
|
||||
/*
|
||||
* Calculate padding assuming that consts go after the other arrays,
|
||||
* but before the bytecode and source notes.
|
||||
*/
|
||||
constPadding = (8 - (size % 8)) % 8;
|
||||
size += constPadding + nconsts * sizeof(Value);
|
||||
}
|
||||
|
||||
size += length * sizeof(jsbytecode) +
|
||||
nsrcnotes * sizeof(jssrcnote);
|
||||
|
||||
script = (JSScript *) cx->malloc(size);
|
||||
if (!script)
|
||||
return NULL;
|
||||
|
@ -860,6 +882,10 @@ js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natoms,
|
|||
script->globalsOffset = (uint8)(cursor - (uint8 *)script);
|
||||
cursor += sizeof(GlobalSlotArray);
|
||||
}
|
||||
if (nconsts != 0) {
|
||||
script->constOffset = (uint8)(cursor - (uint8 *)script);
|
||||
cursor += sizeof(JSConstArray);
|
||||
}
|
||||
|
||||
if (natoms != 0) {
|
||||
script->atomMap.length = natoms;
|
||||
|
@ -919,6 +945,17 @@ js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natoms,
|
|||
cursor += vectorSize;
|
||||
}
|
||||
|
||||
/* Must go after other arrays; see constPadding definition. */
|
||||
if (nconsts != 0) {
|
||||
cursor += constPadding;
|
||||
script->consts()->length = nconsts;
|
||||
script->consts()->vector = (Value *)cursor;
|
||||
JS_ASSERT((size_t)cursor % sizeof(double) == 0);
|
||||
vectorSize = nconsts * sizeof(script->consts()->vector[0]);
|
||||
memset(cursor, 0, vectorSize);
|
||||
cursor += vectorSize;
|
||||
}
|
||||
|
||||
script->code = script->main = (jsbytecode *)cursor;
|
||||
JS_ASSERT(cursor +
|
||||
length * sizeof(jsbytecode) +
|
||||
|
@ -1006,7 +1043,8 @@ 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->globalUses.length());
|
||||
cg->ntrynotes, cg->constList.length(),
|
||||
cg->globalUses.length());
|
||||
if (!script)
|
||||
return NULL;
|
||||
|
||||
|
@ -1046,6 +1084,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())
|
||||
|
@ -1201,9 +1241,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();
|
||||
|
@ -1229,6 +1267,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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
namespace js {
|
||||
|
||||
struct GlobalSlotArray {
|
||||
|
@ -141,6 +146,8 @@ struct JSScript {
|
|||
0 if none */
|
||||
uint8 globalsOffset; /* offset to the array of global slots 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 */
|
||||
|
@ -212,6 +219,11 @@ struct JSScript {
|
|||
return (js::GlobalSlotArray *) ((uint8 *)this + globalsOffset);
|
||||
}
|
||||
|
||||
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];
|
||||
|
@ -239,6 +251,12 @@ struct JSScript {
|
|||
|
||||
inline JSObject *getRegExp(size_t index);
|
||||
|
||||
const 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
|
||||
|
@ -362,7 +380,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 nglobals);
|
||||
uint32 ntrynotes, uint32 nconsts, uint32 nglobals);
|
||||
|
||||
extern JSScript *
|
||||
js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg);
|
||||
|
|
|
@ -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();
|
||||
|
@ -2640,7 +2640,7 @@ static const jschar UnitStringData[] = {
|
|||
#pragma pack(push, 8)
|
||||
#endif
|
||||
|
||||
#ifndef _M_X64
|
||||
#ifndef JS_64BIT
|
||||
JSString JSString::unitStringTable[]
|
||||
#else
|
||||
JSString JSString::staticUnitStringTable[]
|
||||
|
@ -2683,7 +2683,7 @@ __attribute__ ((aligned (8)))
|
|||
U(0xf8), U(0xf9), U(0xfa), U(0xfb), U(0xfc), U(0xfd), U(0xfe), U(0xff)
|
||||
};
|
||||
|
||||
#ifdef _M_X64
|
||||
#ifdef JS_64BIT
|
||||
JSString *JSString::unitStringTable = staticUnitStringTable;
|
||||
size_t JSString::unitStringTableSize = sizeof(staticUnitStringTable);
|
||||
#endif
|
||||
|
@ -2758,7 +2758,7 @@ static const jschar Hundreds[] = {
|
|||
#pragma pack(push, 8)
|
||||
#endif
|
||||
|
||||
#ifndef _M_X64
|
||||
#ifndef JS_64BIT
|
||||
JSString JSString::intStringTable[]
|
||||
#else
|
||||
JSString JSString::staticIntStringTable[]
|
||||
|
@ -2801,7 +2801,7 @@ __attribute__ ((aligned (8)))
|
|||
L3(0xf8), L3(0xf9), L3(0xfa), L3(0xfb), L3(0xfc), L3(0xfd), L3(0xfe), L3(0xff)
|
||||
};
|
||||
|
||||
#ifdef _M_X64
|
||||
#ifdef JS_64BIT
|
||||
JSString *JSString::intStringTable = staticIntStringTable;
|
||||
size_t JSString::intStringTableSize = sizeof(staticIntStringTable);
|
||||
#endif
|
||||
|
|
|
@ -289,7 +289,7 @@ struct JSString {
|
|||
#pragma align 8 (__1cIJSStringPunitStringTable_, __1cIJSStringOintStringTable_)
|
||||
#endif
|
||||
|
||||
#ifndef _M_X64
|
||||
#ifndef JS_64BIT
|
||||
static JSString unitStringTable[];
|
||||
static JSString intStringTable[];
|
||||
#else
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -303,6 +303,21 @@
|
|||
# include "jsautocfg.h" /* Use auto-detected configuration */
|
||||
#endif
|
||||
|
||||
// Define JS_64BIT iff we are building in an environment with 64-bit
|
||||
// addresses.
|
||||
#ifdef _MSC_VER
|
||||
# if defined(_M_X64) || defined(_M_AMD64)
|
||||
# define JS_64BIT
|
||||
# endif
|
||||
#elif defined(__GNUC__)
|
||||
# ifdef __x86_64__
|
||||
# define JS_64BIT
|
||||
# endif
|
||||
#else
|
||||
# error "Implement me"
|
||||
#endif
|
||||
|
||||
|
||||
#include "jsinttypes.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
106
js/src/jsxml.cpp
106
js/src/jsxml.cpp
|
@ -252,12 +252,12 @@ namespace_finalize(JSContext *cx, JSObject *obj)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
namespace_equality(JSContext *cx, JSObject *obj, const jsval *vp, JSBool *bp)
|
||||
namespace_equality(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp)
|
||||
{
|
||||
JSObject *obj2;
|
||||
|
||||
JS_ASSERT(JSVAL_IS_OBJECT(*vp));
|
||||
obj2 = JSVAL_TO_OBJECT(*vp);
|
||||
JS_ASSERT(JSVAL_IS_OBJECT(*v));
|
||||
obj2 = JSVAL_TO_OBJECT(*v);
|
||||
*bp = (!obj2 || obj2->getClass() != &js_NamespaceClass.base)
|
||||
? JS_FALSE
|
||||
: js_EqualStrings(GetURI(obj), GetURI(obj2));
|
||||
|
@ -2969,7 +2969,7 @@ ToXMLName(JSContext *cx, jsval v, jsid *funidp)
|
|||
* If the idea is to reject uint32 property names, then the check needs to
|
||||
* be stricter, to exclude hexadecimal and floating point literals.
|
||||
*/
|
||||
if (js_IdIsIndex(STRING_TO_JSBOXEDWORD(name), &index))
|
||||
if (js_IdIsIndex(STRING_TO_JSVAL(name), &index))
|
||||
goto bad;
|
||||
|
||||
if (*name->chars() == '@') {
|
||||
|
@ -3583,18 +3583,17 @@ Insert(JSContext *cx, JSXML *xml, uint32 i, jsval v)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
IndexToBoxedWord(JSContext *cx, uint32 index, jsboxedword *wp)
|
||||
IndexToIdVal(JSContext *cx, uint32 index, jsval *idvp)
|
||||
{
|
||||
JSString *str;
|
||||
|
||||
if (index <= JSBOXEDWORD_INT_MAX) {
|
||||
*wp = INT_TO_JSBOXEDWORD(index);
|
||||
if (index <= JSVAL_INT_MAX) {
|
||||
*idvp = INT_TO_JSVAL(index);
|
||||
} else {
|
||||
str = js_NumberToString(cx, (jsdouble) index);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
|
||||
*wp = STRING_TO_JSBOXEDWORD(str);
|
||||
*idvp = STRING_TO_JSVAL(str);
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -3850,7 +3849,7 @@ GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
|||
/*
|
||||
* ECMA-357 9.2.1.1/9.1.1.1 qname case.
|
||||
*/
|
||||
nameqn = ToXMLName(cx, Jsvalify(IdToValue(id)), &funid);
|
||||
nameqn = ToXMLName(cx, ID_TO_JSVAL(id), &funid);
|
||||
if (!nameqn)
|
||||
return false;
|
||||
if (funid)
|
||||
|
@ -3955,14 +3954,14 @@ PutProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
|||
MUST_FLOW_THROUGH("out");
|
||||
jsval roots[3];
|
||||
roots[OBJ_ROOT] = OBJECT_TO_JSVAL(obj);
|
||||
roots[ID_ROOT] = Jsvalify(IdToValue(id));
|
||||
roots[ID_ROOT] = ID_TO_JSVAL(id);
|
||||
roots[VAL_ROOT] = *vp;
|
||||
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(roots), Valueify(roots));
|
||||
|
||||
if (js_IdIsIndex(id, &index)) {
|
||||
if (xml->xml_class != JSXML_CLASS_LIST) {
|
||||
/* See NOTE in spec: this variation is reserved for future use. */
|
||||
ReportBadXMLName(cx, IdToValue(id));
|
||||
ReportBadXMLName(cx, ID_TO_VALUE(id));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
|
@ -4247,7 +4246,7 @@ PutProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
|||
kidobj = js_GetXMLObject(cx, kid);
|
||||
if (!kidobj)
|
||||
goto bad;
|
||||
id = ATOM_KEY(cx->runtime->atomState.starAtom);
|
||||
id = ATOM_TO_JSID(cx->runtime->atomState.starAtom);
|
||||
ok = PutProperty(cx, kidobj, id, vp);
|
||||
if (!ok)
|
||||
goto out;
|
||||
|
@ -4256,7 +4255,7 @@ PutProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
|||
/*
|
||||
* ECMA-357 9.2.1.2/9.1.1.2 qname case.
|
||||
*/
|
||||
nameqn = ToXMLName(cx, Jsvalify(IdToValue(id)), &funid);
|
||||
nameqn = ToXMLName(cx, ID_TO_JSVAL(id), &funid);
|
||||
if (!nameqn)
|
||||
goto bad;
|
||||
if (funid) {
|
||||
|
@ -4436,7 +4435,7 @@ PutProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
|
|||
}
|
||||
|
||||
/* 10-11. */
|
||||
id = JSBOXEDWORD_VOID;
|
||||
id = JSVAL_VOID;
|
||||
primitiveAssign = !vxml && !IS_STAR(GetLocalName(nameqn));
|
||||
|
||||
/* 12. */
|
||||
|
@ -4550,7 +4549,7 @@ out:
|
|||
type_error:
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_BAD_XMLLIST_PUT,
|
||||
js_ValueToPrintableString(cx, IdToValue(id)));
|
||||
js_ValueToPrintableString(cx, ID_TO_VALUE(id)));
|
||||
bad:
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
|
@ -4719,7 +4718,7 @@ HasProperty(JSContext *cx, JSObject *obj, jsid id, JSBool *found)
|
|||
if (js_IdIsIndex(id, &i)) {
|
||||
*found = HasIndexedProperty(xml, i);
|
||||
} else {
|
||||
qn = ToXMLName(cx, Jsvalify(IdToValue(id)), &funid);
|
||||
qn = ToXMLName(cx, ID_TO_JSVAL(id), &funid);
|
||||
if (!qn)
|
||||
return JS_FALSE;
|
||||
if (funid) {
|
||||
|
@ -4796,7 +4795,7 @@ xml_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
|
|||
if (js_IdIsIndex(id, &i)) {
|
||||
found = HasIndexedProperty(xml, i);
|
||||
} else {
|
||||
qn = ToXMLName(cx, Jsvalify(IdToValue(id)), &funid);
|
||||
qn = ToXMLName(cx, ID_TO_JSVAL(id), &funid);
|
||||
if (!qn)
|
||||
return JS_FALSE;
|
||||
if (funid)
|
||||
|
@ -4822,16 +4821,16 @@ xml_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
|
|||
}
|
||||
|
||||
static JSBool
|
||||
xml_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *vp,
|
||||
xml_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v,
|
||||
PropertyOp getter, PropertyOp setter, uintN attrs)
|
||||
{
|
||||
if (vp->isFunObj() || getter || setter ||
|
||||
if (v->isFunObj() || getter || setter ||
|
||||
(attrs & JSPROP_ENUMERATE) == 0 ||
|
||||
(attrs & (JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED))) {
|
||||
return js_DefineProperty(cx, obj, id, vp, getter, setter, attrs);
|
||||
return js_DefineProperty(cx, obj, id, v, getter, setter, attrs);
|
||||
}
|
||||
|
||||
jsval tmp = Jsvalify(*vp);
|
||||
jsval tmp = Jsvalify(*v);
|
||||
return PutProperty(cx, obj, id, &tmp);
|
||||
}
|
||||
|
||||
|
@ -4899,12 +4898,12 @@ xml_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval)
|
|||
JSObject *nameqn;
|
||||
jsid funid;
|
||||
|
||||
idval = Jsvalify(IdToValue(id));
|
||||
idval = ID_TO_JSVAL(id);
|
||||
xml = (JSXML *) obj->getPrivate();
|
||||
if (js_IdIsIndex(id, &index)) {
|
||||
if (xml->xml_class != JSXML_CLASS_LIST) {
|
||||
/* See NOTE in spec: this variation is reserved for future use. */
|
||||
ReportBadXMLName(cx, IdToValue(id));
|
||||
ReportBadXMLName(cx, ID_TO_VALUE(id));
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
|
@ -5012,7 +5011,7 @@ xml_typeOf(JSContext *cx, JSObject *obj)
|
|||
}
|
||||
|
||||
static JSBool
|
||||
xml_hasInstance(JSContext *cx, JSObject *obj, const Value *vp, JSBool *bp)
|
||||
xml_hasInstance(JSContext *cx, JSObject *obj, const Value *, JSBool *bp)
|
||||
{
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -5341,16 +5340,11 @@ xml_appendChild(JSContext *cx, uintN argc, jsval *vp)
|
|||
vxml = (JSXML *) vobj->getPrivate();
|
||||
JS_ASSERT(vxml->xml_class == JSXML_CLASS_LIST);
|
||||
|
||||
jsboxedword w;
|
||||
if (!IndexToBoxedWord(cx, vxml->xml_kids.length, &w))
|
||||
if (!IndexToIdVal(cx, vxml->xml_kids.length, &name))
|
||||
return JS_FALSE;
|
||||
*vp = (argc != 0) ? vp[2] : JSVAL_VOID;
|
||||
|
||||
/*
|
||||
* N.B. w is not actually a jsid: w may contain an non-interned string.
|
||||
* Apparently, PutProperty is cool with this.
|
||||
*/
|
||||
if (!PutProperty(cx, JSVAL_TO_OBJECT(v), w, vp))
|
||||
if (!PutProperty(cx, JSVAL_TO_OBJECT(v), name, 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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -452,8 +452,7 @@ mjit::Compiler::generateMethod()
|
|||
BEGIN_CASE(JSOP_DOUBLE)
|
||||
{
|
||||
uint32 index = fullAtomIndex(PC);
|
||||
JSAtom *atom = script->getAtom(index);
|
||||
double d = *ATOM_TO_DOUBLE(atom);
|
||||
double d = script->getConst(index).asDouble();
|
||||
frame.push(Value(DoubleTag(d)));
|
||||
}
|
||||
END_CASE(JSOP_DOUBLE)
|
||||
|
|
|
@ -62,6 +62,12 @@ WIN32_EXE_LDFLAGS += -ENTRY:mainACRTStartup
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),Darwin)
|
||||
ifeq ($(TARGET_CPU),x86_64)
|
||||
DARWIN_EXE_LDFLAGS += -pagezero_size 10000 -image_base 100000000
|
||||
endif
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifdef MOZ_SHARK
|
||||
|
|
|
@ -217,19 +217,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)
|
||||
|
@ -1678,7 +1665,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);
|
||||
|
@ -2690,7 +2676,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. */
|
||||
|
||||
|
@ -2802,7 +2788,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)
|
||||
|
@ -2833,13 +2819,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;
|
||||
|
||||
|
@ -4406,7 +4392,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. */
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче