diff --git a/mozilla/js/src/js.c b/mozilla/js/src/js.c index a859de1a911..fe2d46c6565 100644 --- a/mozilla/js/src/js.c +++ b/mozilla/js/src/js.c @@ -1694,7 +1694,7 @@ DumpHeap(JSContext *cx, uintN argc, jsval *vp) static JSBool DoExport(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { - jsid id; + JSAtom *atom; JSObject *obj2; JSProperty *prop; JSBool ok; @@ -1707,18 +1707,19 @@ DoExport(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) if (!JS_ValueToObject(cx, argv[0], &obj)) return JS_FALSE; argv[0] = OBJECT_TO_JSVAL(obj); - if (!js_ValueToStringId(cx, argv[1], &id)) + atom = js_ValueToStringAtom(cx, argv[1]); + if (!atom) return JS_FALSE; - if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop)) + if (!OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &obj2, &prop)) return JS_FALSE; if (!prop) { ok = OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID, NULL, NULL, JSPROP_EXPORTED, NULL); } else { - ok = OBJ_GET_ATTRIBUTES(cx, obj, id, prop, &attrs); + ok = OBJ_GET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, &attrs); if (ok) { attrs |= JSPROP_EXPORTED; - ok = OBJ_SET_ATTRIBUTES(cx, obj, id, prop, &attrs); + ok = OBJ_SET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, &attrs); } OBJ_DROP_PROPERTY(cx, obj2, prop); } diff --git a/mozilla/js/src/jsapi.c b/mozilla/js/src/jsapi.c index d187321f1e8..deccf636687 100644 --- a/mozilla/js/src/jsapi.c +++ b/mozilla/js/src/jsapi.c @@ -2565,15 +2565,23 @@ JS_DestroyIdArray(JSContext *cx, JSIdArray *ida) JS_PUBLIC_API(JSBool) JS_ValueToId(JSContext *cx, jsval v, jsid *idp) { + JSAtom *atom; + CHECK_REQUEST(cx); - if (JSVAL_IS_INT(v)) + if (JSVAL_IS_INT(v)) { *idp = INT_JSVAL_TO_JSID(v); + } else { #if JS_HAS_XML_SUPPORT - else if (!JSVAL_IS_PRIMITIVE(v)) - *idp = OBJECT_JSVAL_TO_JSID(v); + if (JSVAL_IS_OBJECT(v)) { + *idp = OBJECT_JSVAL_TO_JSID(v); + return JS_TRUE; + } #endif - else - return js_ValueToStringId(cx, v, idp); + atom = js_ValueToStringAtom(cx, v); + if (!atom) + return JS_FALSE; + *idp = ATOM_TO_JSID(atom); + } return JS_TRUE; } @@ -5232,7 +5240,7 @@ JS_GetStringChars(JSString *str) } } else { JSSTRING_CLEAR_MUTABLE(str); - s = JSFLATSTR_CHARS(str); + s = str->u.chars; } return s; } diff --git a/mozilla/js/src/jsatom.c b/mozilla/js/src/jsatom.c index 4c317639248..e278365b1b4 100644 --- a/mozilla/js/src/jsatom.c +++ b/mozilla/js/src/jsatom.c @@ -621,16 +621,16 @@ js_AtomizeDouble(JSContext *cx, jsdouble d) JSAtom * js_AtomizeString(JSContext *cx, JSString *str, uintN flags) { - jsval v; JSAtomState *state; JSDHashTable *table; JSAtomHashEntry *entry; JSString *key; uint32 gen; + jsval v; - JS_ASSERT(!(flags & ~(ATOM_PINNED|ATOM_INTERNED|ATOM_TMPSTR|ATOM_NOCOPY))); - JS_ASSERT_IF(flags & ATOM_NOCOPY, flags & ATOM_TMPSTR); - + JS_ASSERT((flags & + ~(ATOM_PINNED | ATOM_INTERNED | ATOM_TMPSTR | ATOM_NOCOPY)) + == 0); state = &cx->runtime->atomState; table = &state->stringAtoms; @@ -638,67 +638,49 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags) entry = TO_ATOM_ENTRY(JS_DHashTableOperate(table, str, JS_DHASH_ADD)); if (!entry) goto failed_hash_add; - if (entry->keyAndFlags != 0) { - key = (JSString *)ATOM_ENTRY_KEY(entry); - } else { - /* - * We created a new hashtable entry. Unless str is already allocated - * from the GC heap and flat, we have to release state->lock as - * string construction is a complex operation. For example, it can - * trigger GC which may rehash the table and make the entry invalid. - */ + if (entry->keyAndFlags == 0) { ++state->tablegen; + gen = state->tablegen; + JS_UNLOCK(&state->lock, cx); - if (!(flags & ATOM_TMPSTR) && !JSSTRING_IS_DEPENDENT(str)) { - JSSTRING_CLEAR_MUTABLE(str); - key = str; - } else { - gen = state->tablegen; - JS_UNLOCK(&state->lock, cx); - - if (flags & ATOM_TMPSTR) { - if (flags & ATOM_NOCOPY) { - key = js_NewString(cx, JSFLATSTR_CHARS(str), - JSFLATSTR_LENGTH(str)); - if (!key) - return NULL; - - /* Finish handing off chars to the GC'ed key string. */ - str->u.chars = NULL; - } else { - key = js_NewStringCopyN(cx, JSFLATSTR_CHARS(str), - JSFLATSTR_LENGTH(str)); - if (!key) - return NULL; - } - } else { - JS_ASSERT(JSSTRING_IS_DEPENDENT(str)); - if (!js_UndependString(cx, str)) + if (flags & ATOM_TMPSTR) { + if (flags & ATOM_NOCOPY) { + key = js_NewString(cx, str->u.chars, str->length); + if (!key) return NULL; - key = str; - } - JS_LOCK(&state->lock, cx); - if (state->tablegen == gen) { - JS_ASSERT(entry->keyAndFlags == 0); + /* Transfer ownership of str->chars to GC-controlled string. */ + str->u.chars = NULL; } else { - entry = TO_ATOM_ENTRY(JS_DHashTableOperate(table, key, - JS_DHASH_ADD)); - if (!entry) - goto failed_hash_add; - if (entry->keyAndFlags != 0) - goto finish; - ++state->tablegen; + key = js_NewStringCopyN(cx, str->u.chars, str->length); + if (!key) + return NULL; } + } else { + JS_ASSERT((flags & ATOM_NOCOPY) == 0); + if (!JS_MakeStringImmutable(cx, str)) + return NULL; + key = str; + } + + JS_LOCK(&state->lock, cx); + if (state->tablegen == 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; + ++state->tablegen; } INIT_ATOM_ENTRY(entry, key); - JSSTRING_SET_ATOMIZED(key); } finish: ADD_ATOM_ENTRY_FLAGS(entry, flags & (ATOM_PINNED | ATOM_INTERNED)); - JS_ASSERT(JSSTRING_IS_ATOMIZED(key)); - v = STRING_TO_JSVAL(key); + v = STRING_TO_JSVAL((JSString *)ATOM_ENTRY_KEY(entry)); cx->weakRoots.lastAtom = v; JS_UNLOCK(&state->lock, cx); return (JSAtom *)v; @@ -797,36 +779,15 @@ js_AtomizePrimitiveValue(JSContext *cx, jsval v, JSAtom **atomp) return JS_TRUE; } -JSBool -js_ValueToStringId(JSContext *cx, jsval v, jsid *idp) +JSAtom * +js_ValueToStringAtom(JSContext *cx, jsval v) { JSString *str; - JSAtom *atom; - /* - * Optimize for the common case where v is an already-atomized string. The - * comment in jsstr.h before the JSSTRING_SET_ATOMIZED macro's definition - * explains why this is thread-safe. The extra rooting via lastAtom (which - * would otherwise be done in js_js_AtomizeString) ensures the caller that - * the resulting id at least weakly rooted. - */ - if (JSVAL_IS_STRING(v)) { - str = JSVAL_TO_STRING(v); - if (JSSTRING_IS_ATOMIZED(str)) { - cx->weakRoots.lastAtom = v; - *idp = ATOM_TO_JSID((JSAtom *) v); - return JS_TRUE; - } - } else { - str = js_ValueToString(cx, v); - if (!str) - return JS_FALSE; - } - atom = js_AtomizeString(cx, str, 0); - if (!atom) - return JS_FALSE; - *idp = ATOM_TO_JSID(atom); - return JS_TRUE; + str = js_ValueToString(cx, v); + if (!str) + return NULL; + return js_AtomizeString(cx, str, 0); } #ifdef DEBUG diff --git a/mozilla/js/src/jsatom.h b/mozilla/js/src/jsatom.h index 4e24b5c95a5..6cc4cc8aaa5 100644 --- a/mozilla/js/src/jsatom.h +++ b/mozilla/js/src/jsatom.h @@ -416,10 +416,10 @@ JSBool js_AtomizePrimitiveValue(JSContext *cx, jsval v, JSAtom **atomp); /* - * Convert v to an atomized string and wrap it as an id. + * Convert v to an atomized string. */ -extern JSBool -js_ValueToStringId(JSContext *cx, jsval v, jsid *idp); +extern JSAtom * +js_ValueToStringAtom(JSContext *cx, jsval v); #ifdef DEBUG diff --git a/mozilla/js/src/jsdbgapi.c b/mozilla/js/src/jsdbgapi.c index b2826b79e94..9b5730fc650 100644 --- a/mozilla/js/src/jsdbgapi.c +++ b/mozilla/js/src/jsdbgapi.c @@ -675,9 +675,9 @@ js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter) if (JSID_IS_ATOM(id)) { atom = JSID_TO_ATOM(id); } else if (JSID_IS_INT(id)) { - if (!js_ValueToStringId(cx, INT_JSID_TO_JSVAL(id), &id)) + atom = js_ValueToStringAtom(cx, INT_JSID_TO_JSVAL(id)); + if (!atom) return NULL; - atom = JSID_TO_ATOM(id); } else { atom = NULL; } @@ -690,9 +690,10 @@ js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter) } JS_PUBLIC_API(JSBool) -JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval, +JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id, JSWatchPointHandler handler, void *closure) { + JSAtom *atom; jsid propid; JSObject *pobj; JSProperty *prop; @@ -708,10 +709,15 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval, return JS_FALSE; } - if (JSVAL_IS_INT(idval)) - propid = INT_JSVAL_TO_JSID(idval); - else if (!js_ValueToStringId(cx, idval, &propid)) - return JS_FALSE; + if (JSVAL_IS_INT(id)) { + propid = INT_JSVAL_TO_JSID(id); + atom = NULL; + } else { + atom = js_ValueToStringAtom(cx, id); + if (!atom) + return JS_FALSE; + propid = ATOM_TO_JSID(atom); + } if (!js_LookupProperty(cx, obj, propid, &pobj, &prop)) return JS_FALSE; @@ -746,8 +752,8 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval, flags = sprop->flags; shortid = sprop->shortid; } else { - if (!OBJ_GET_PROPERTY(cx, pobj, propid, &value) || - !OBJ_GET_ATTRIBUTES(cx, pobj, propid, prop, &attrs)) { + if (!OBJ_GET_PROPERTY(cx, pobj, id, &value) || + !OBJ_GET_ATTRIBUTES(cx, pobj, id, prop, &attrs)) { OBJ_DROP_PROPERTY(cx, pobj, prop); return JS_FALSE; } @@ -1516,8 +1522,7 @@ GetAtomTotalSize(JSContext *cx, JSAtom *atom) nbytes = sizeof(JSAtom *) + sizeof(JSDHashEntryStub); if (ATOM_IS_STRING(atom)) { nbytes += sizeof(JSString); - nbytes += (JSFLATSTR_LENGTH(ATOM_TO_STRING(atom)) + 1) - * sizeof(jschar); + nbytes += (ATOM_TO_STRING(atom)->length + 1) * sizeof(jschar); } else if (ATOM_IS_DOUBLE(atom)) { nbytes += sizeof(jsdouble); } diff --git a/mozilla/js/src/jsfun.c b/mozilla/js/src/jsfun.c index ef0ec5d1080..b654780155d 100644 --- a/mozilla/js/src/jsfun.c +++ b/mozilla/js/src/jsfun.c @@ -807,11 +807,12 @@ call_enumerate(JSContext *cx, JSObject *obj) } static JSBool -call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags, +call_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp) { JSStackFrame *fp; - jsid id; + JSString *str; + JSAtom *atom; JSLocalKind localKind; JSPropertyOp getter, setter; uintN slot, attrs; @@ -823,13 +824,15 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags, JS_ASSERT(fp->fun); JS_ASSERT(GET_FUNCTION_PRIVATE(cx, fp->callee) == fp->fun); - if (!JSVAL_IS_STRING(idval)) + if (!JSVAL_IS_STRING(id)) return JS_TRUE; - if (!js_ValueToStringId(cx, idval, &id)) + str = JSVAL_TO_STRING(id); + atom = js_AtomizeString(cx, str, 0); + if (!atom) return JS_FALSE; - localKind = js_LookupLocal(cx, fp->fun, JSID_TO_ATOM(id), &slot); + localKind = js_LookupLocal(cx, fp->fun, atom, &slot); if (localKind != JSLOCAL_NONE) { if (localKind == JSLOCAL_ARG) { JS_ASSERT(slot < fp->fun->nargs); @@ -847,9 +850,9 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags, ? JSPROP_PERMANENT | JSPROP_READONLY : JSPROP_PERMANENT; } - if (!js_DefineNativeProperty(cx, obj, id, vp[slot], getter, setter, - attrs, SPROP_HAS_SHORTID, (int) slot, - NULL)) { + if (!js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom), vp[slot], + getter, setter, attrs, + SPROP_HAS_SHORTID, (int) slot, NULL)) { return JS_FALSE; } *objp = obj; @@ -860,8 +863,10 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags, * Resolve arguments so that we never store a particular Call object's * arguments object reference in a Call prototype's |arguments| slot. */ - if (id == ATOM_TO_JSID(cx->runtime->atomState.argumentsAtom)) { - if (!js_DefineNativeProperty(cx, obj, id, JSVAL_VOID, + atom = cx->runtime->atomState.argumentsAtom; + if (id == ATOM_KEY(atom)) { + if (!js_DefineNativeProperty(cx, obj, + ATOM_TO_JSID(atom), JSVAL_VOID, NULL, NULL, JSPROP_PERMANENT, SPROP_HAS_SHORTID, CALL_ARGUMENTS, NULL)) { diff --git a/mozilla/js/src/jsinterp.c b/mozilla/js/src/jsinterp.c index 3cb14a1f5f7..1dabda97270 100644 --- a/mozilla/js/src/jsinterp.c +++ b/mozilla/js/src/jsinterp.c @@ -1632,6 +1632,8 @@ js_InvokeConstructor(JSContext *cx, jsval *vp, uintN argc) static JSBool InternNonIntElementId(JSContext *cx, JSObject *obj, jsval idval, jsid *idp) { + JSAtom *atom; + JS_ASSERT(!JSVAL_IS_INT(idval)); #if JS_HAS_XML_SUPPORT @@ -1647,7 +1649,11 @@ InternNonIntElementId(JSContext *cx, JSObject *obj, jsval idval, jsid *idp) } #endif - return js_ValueToStringId(cx, idval, idp); + atom = js_ValueToStringAtom(cx, idval); + if (!atom) + return JS_FALSE; + *idp = ATOM_TO_JSID(atom); + return JS_TRUE; } /* diff --git a/mozilla/js/src/jsobj.c b/mozilla/js/src/jsobj.c index 99730368ca3..09962c5bad9 100644 --- a/mozilla/js/src/jsobj.c +++ b/mozilla/js/src/jsobj.c @@ -2937,11 +2937,11 @@ js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot) if (JSID_IS_ATOM(id)) { \ JSAtom *atom_ = JSID_TO_ATOM(id); \ JSString *str_ = ATOM_TO_STRING(atom_); \ - const jschar *cp_ = JSFLATSTR_CHARS(str_); \ + const jschar *cp_ = str_->u.chars; \ JSBool negative_ = (*cp_ == '-'); \ if (negative_) cp_++; \ if (JS7_ISDEC(*cp_)) { \ - size_t n_ = JSFLATSTR_LENGTH(str_) - negative_; \ + size_t n_ = str_->length - negative_; \ if (n_ <= sizeof(JSVAL_INT_MAX_STRING) - 1) \ id = CheckForStringIndex(id, cp_, cp_ + n_, negative_); \ } \ diff --git a/mozilla/js/src/jsparse.c b/mozilla/js/src/jsparse.c index c3862f5fe38..ffbc7c0149c 100644 --- a/mozilla/js/src/jsparse.c +++ b/mozilla/js/src/jsparse.c @@ -6406,7 +6406,7 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc) /* XXX fold only if all operands convert to string */ if (pn2->pn_type != TOK_STRING) return JS_TRUE; - length += JSFLATSTR_LENGTH(ATOM_TO_STRING(pn2->pn_atom)); + length += ATOM_TO_STRING(pn2->pn_atom)->length; } /* Allocate a new buffer and string descriptor for the result. */ @@ -6422,8 +6422,8 @@ js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc) /* Fill the buffer, advancing chars and recycling kids as we go. */ for (pn2 = pn1; pn2; pn2 = RecycleTree(pn2, tc)) { str2 = ATOM_TO_STRING(pn2->pn_atom); - length2 = JSFLATSTR_LENGTH(str2); - js_strncpy(chars, JSFLATSTR_CHARS(str2), length2); + length2 = str2->length; + js_strncpy(chars, str2->u.chars, length2); chars += length2; } *chars = 0; diff --git a/mozilla/js/src/jsstr.c b/mozilla/js/src/jsstr.c index 40ca1a5a306..9b39be257e5 100644 --- a/mozilla/js/src/jsstr.c +++ b/mozilla/js/src/jsstr.c @@ -110,8 +110,8 @@ js_GetDependentStringChars(JSString *str) start = js_MinimizeDependentStrings(str, 0, &base); JS_ASSERT(!JSSTRING_IS_DEPENDENT(base)); - JS_ASSERT(start < JSFLATSTR_LENGTH(base)); - return JSFLATSTR_CHARS(base) + start; + JS_ASSERT(start < (base->length & ~JSSTRFLAG_MUTABLE)); + return base->u.chars + start; } const jschar * @@ -120,7 +120,7 @@ js_GetStringChars(JSContext *cx, JSString *str) if (!js_MakeStringImmutable(cx, str)) return NULL; JS_ASSERT(!JSSTRING_IS_DEPENDENT(str)); - return JSFLATSTR_CHARS(str); + return str->u.chars; } JSString * @@ -225,7 +225,7 @@ js_UndependString(JSContext *cx, JSString *str) #endif } - return JSFLATSTR_CHARS(str); + return str->u.chars; } JSBool @@ -2645,7 +2645,6 @@ js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop, void js_FinalizeStringRT(JSRuntime *rt, JSString *str, intN type, JSContext *cx) { - jschar *chars; JSBool valid; JSStringFinalizeOp finalizer; @@ -2658,15 +2657,14 @@ js_FinalizeStringRT(JSRuntime *rt, JSString *str, intN type, JSContext *cx) valid = JS_TRUE; } else { /* A stillborn string has null chars, so is not valid. */ - chars = JSFLATSTR_CHARS(str); - valid = (chars != NULL); + valid = (str->u.chars != NULL); if (valid) { - if (IN_UNIT_STRING_SPACE_RT(rt, chars)) { - JS_ASSERT(rt->unitStrings[*chars] == str); + if (IN_UNIT_STRING_SPACE_RT(rt, str->u.chars)) { + JS_ASSERT(rt->unitStrings[*str->u.chars] == str); JS_ASSERT(type < 0); - rt->unitStrings[*chars] = NULL; + rt->unitStrings[*str->u.chars] = NULL; } else if (type < 0) { - free(chars); + free(str->u.chars); } else { JS_ASSERT((uintN) type < JS_ARRAY_LENGTH(str_finalizers)); finalizer = str_finalizers[type]; diff --git a/mozilla/js/src/jsstr.h b/mozilla/js/src/jsstr.h index f5ec6db12be..9179c1a3d3a 100644 --- a/mozilla/js/src/jsstr.h +++ b/mozilla/js/src/jsstr.h @@ -70,10 +70,6 @@ JS_BEGIN_EXTERN_C * such string but extreme care must be taken to ensure that no other code * relies on the original length of the string. * - * A flat string with JSSTRFLAG_ATOMIZED set means that the string is hashed - * as an atom. This flag is used to avoid re-hashing of the already-atomized - * string. - * * When JSSTRFLAG_DEPENDENT is set, the string depends on characters of * another string strongly referenced by the u.base field. The base member may * point to another dependent string if JSSTRING_CHARS has not been called @@ -103,102 +99,59 @@ struct JSString { * Definitions for flags stored in the high order bits of JSString.length. * JSSTRFLAG_PREFIX and JSSTRFLAG_MUTABLE are two aliases for the same value. * JSSTRFLAG_PREFIX should be used only if JSSTRFLAG_DEPENDENT is set and - * JSSTRFLAG_MUTABLE should be used only if the string is flat and - * JSSTRFLAG_DEPENDENT is unset. JSSTRFLAG_ATOMIZED is used only with the - * flat immutable strings. + * JSSTRFLAG_MUTABLE should be used only if JSSTRFLAG_DEPENDENT is unset. */ -#define JSSTRFLAG_DEPENDENT JSSTRING_BIT(JS_BITS_PER_WORD - 1) -#define JSSTRFLAG_PREFIX JSSTRING_BIT(JS_BITS_PER_WORD - 2) -#define JSSTRFLAG_MUTABLE JSSTRFLAG_PREFIX -#define JSSTRFLAG_ATOMIZED JSSTRING_BIT(JS_BITS_PER_WORD - 3) - -#define JSSTRING_LENGTH_BITS (JS_BITS_PER_WORD - 3) -#define JSSTRING_LENGTH_MASK JSSTRING_BITMASK(JSSTRING_LENGTH_BITS) +#define JSSTRFLAG_BITS 2 +#define JSSTRFLAG_SHIFT(flg) ((size_t)(flg) << JSSTRING_LENGTH_BITS) +#define JSSTRFLAG_MASK JSSTRFLAG_SHIFT(JS_BITMASK(JSSTRFLAG_BITS)) +#define JSSTRFLAG_DEPENDENT JSSTRFLAG_SHIFT(1) +#define JSSTRFLAG_PREFIX JSSTRFLAG_SHIFT(2) +#define JSSTRFLAG_MUTABLE JSSTRFLAG_SHIFT(2) /* Universal JSString type inquiry and accessor macros. */ #define JSSTRING_BIT(n) ((size_t)1 << (n)) #define JSSTRING_BITMASK(n) (JSSTRING_BIT(n) - 1) #define JSSTRING_HAS_FLAG(str,flg) ((str)->length & (flg)) #define JSSTRING_IS_DEPENDENT(str) JSSTRING_HAS_FLAG(str, JSSTRFLAG_DEPENDENT) -#define JSSTRING_IS_MUTABLE(str) (((str)->length & (JSSTRFLAG_DEPENDENT | \ - JSSTRFLAG_MUTABLE)) == \ +#define JSSTRING_IS_MUTABLE(str) (((str)->length & JSSTRFLAG_MASK) == \ JSSTRFLAG_MUTABLE) -#define JSSTRING_IS_ATOMIZED(str) (((str)->length & (JSSTRFLAG_DEPENDENT | \ - JSSTRFLAG_ATOMIZED)) ==\ - JSSTRFLAG_ATOMIZED) #define JSSTRING_CHARS(str) (JSSTRING_IS_DEPENDENT(str) \ ? JSSTRDEP_CHARS(str) \ - : JSFLATSTR_CHARS(str)) + : (str)->u.chars) #define JSSTRING_LENGTH(str) (JSSTRING_IS_DEPENDENT(str) \ ? JSSTRDEP_LENGTH(str) \ - : JSFLATSTR_LENGTH(str)) + : ((str)->length & ~JSSTRFLAG_MUTABLE)) #define JSSTRING_CHARS_AND_LENGTH(str, chars_, length_) \ ((void)(JSSTRING_IS_DEPENDENT(str) \ ? ((length_) = JSSTRDEP_LENGTH(str), \ (chars_) = JSSTRDEP_CHARS(str)) \ - : ((length_) = JSFLATSTR_LENGTH(str), \ - (chars_) = JSFLATSTR_CHARS(str)))) + : ((length_) = (str)->length & ~JSSTRFLAG_MUTABLE, \ + (chars_) = (str)->u.chars))) #define JSSTRING_CHARS_AND_END(str, chars_, end) \ ((void)((end) = JSSTRING_IS_DEPENDENT(str) \ ? JSSTRDEP_LENGTH(str) + ((chars_) = JSSTRDEP_CHARS(str)) \ - : JSFLATSTR_LENGTH(str) + ((chars_) = JSFLATSTR_CHARS(str)))) + : ((str)->length & ~JSSTRFLAG_MUTABLE) + \ + ((chars_) = (str)->u.chars))) + +#define JSSTRING_LENGTH_BITS (sizeof(size_t) * JS_BITS_PER_BYTE \ + - JSSTRFLAG_BITS) +#define JSSTRING_LENGTH_MASK JSSTRING_BITMASK(JSSTRING_LENGTH_BITS) #define JSSTRING_INIT(str, chars_, length_) \ - ((void)(JS_ASSERT(((length_) & ~JSSTRING_LENGTH_MASK) == 0), \ + ((void)(JS_ASSERT(((length_) & JSSTRFLAG_MASK) == 0), \ (str)->length = (length_), (str)->u.chars = (chars_))) -/* - * Specific macro to get the length and characters of a flat string. - */ -#define JSFLATSTR_LENGTH(str) \ - (JS_ASSERT(!JSSTRING_IS_DEPENDENT(str)), \ - (str)->length & JSSTRING_LENGTH_MASK) - -#define JSFLATSTR_CHARS(str) \ - (JS_ASSERT(!JSSTRING_IS_DEPENDENT(str)), (str)->u.chars) - -/* - * Specific macros to manipulate atomized and mutable flags. It is safe to use - * these without extra locking due to the following properties: - * - * * We do not have a macro like JSSTRING_CLEAR_ATOMIZED as a string remains - * atomized until the GC collects it. - * - * * A thread may call JSSTRING_SET_MUTABLE only when it is the only thread - * accessing the string until a later call to JSSTRING_CLEAR_MUTABLE. - * - * * Multiple threads can call JSSTRING_CLEAR_MUTABLE but the macro actually - * clears the mutable flag only when the flag is set -- in which case only - * one thread can access the string (see previous property). - * - * Thus, when multiple threads access the string, JSSTRING_SET_ATOMIZED is - * the only macro that can update the length field of the string by changing - * the mutable bit from 0 to 1. We call the macro only after the string has - * been hashed. When some threads in js_ValueToStringId see that the flag is - * set, it knows that the string was atomized. - * - * On the other hand, if the thread sees that the flag is unset, it could be - * seeing a stale value when another thread has just atomized the string and - * set the flag. But this can lead only to an extra call to js_AtomizeString. - * This function would find that the string was already hashed and return it - * with the atomized bit set. - */ -#define JSSTRING_SET_ATOMIZED(str) \ - ((void)(JS_ASSERT(!JSSTRING_IS_DEPENDENT(str)), \ - JS_ASSERT(!JSSTRING_IS_MUTABLE(str)), \ - (str)->length |= JSSTRFLAG_ATOMIZED)) - +/* Specific mutable string manipulation macros. */ #define JSSTRING_SET_MUTABLE(str) \ ((void)(JS_ASSERT(!JSSTRING_IS_DEPENDENT(str)), \ (str)->length |= JSSTRFLAG_MUTABLE)) #define JSSTRING_CLEAR_MUTABLE(str) \ ((void)(JS_ASSERT(!JSSTRING_IS_DEPENDENT(str)), \ - JSSTRING_HAS_FLAG(str, JSSTRFLAG_MUTABLE) && \ - ((str)->length &= ~JSSTRFLAG_MUTABLE))) + (str)->length &= ~JSSTRFLAG_MUTABLE)) /* Specific dependent string shift/mask accessor and mutator macros. */ #define JSSTRDEP_START_BITS (JSSTRING_LENGTH_BITS-JSSTRDEP_LENGTH_BITS) @@ -235,7 +188,7 @@ struct JSString { #define JSSTRDEP_CHARS(str) \ (JSSTRING_IS_DEPENDENT(JSSTRDEP_BASE(str)) \ ? js_GetDependentStringChars(str) \ - : JSFLATSTR_CHARS(JSSTRDEP_BASE(str)) + JSSTRDEP_START(str)) + : JSSTRDEP_BASE(str)->u.chars + JSSTRDEP_START(str)) extern size_t js_MinimizeDependentStrings(JSString *str, int level, JSString **basep); diff --git a/mozilla/js/src/jsxml.c b/mozilla/js/src/jsxml.c index e3d71742f80..e7bc328ce21 100644 --- a/mozilla/js/src/jsxml.c +++ b/mozilla/js/src/jsxml.c @@ -7896,7 +7896,7 @@ js_AddAttributePart(JSContext *cx, JSBool isName, JSString *str, JSString *str2) str = js_NewStringCopyN(cx, chars, len); if (!str) return NULL; - chars = JSFLATSTR_CHARS(str); + chars = str->u.chars; } else { /* * Reallocating str (because we know it has no other references)