JSAtom * js_AtomizeString(JSContext *cx, JSString *str, uintN flags) { PRHashTable *table; PRHashNumber keyHash; jsval key; PRHashEntry *he, **hep; JSAtom *atom; PR_ASSERT(JS_IS_LOCKED(cx)); table = cx->runtime->atomState.table; keyHash = js_HashString(str); key = STRING_TO_JSVAL(str); hep = PR_HashTableRawLookup(table, keyHash, (void *)key); if ((he = *hep) == NULL) { if (flags & ATOM_TMPSTR) { if (flags & ATOM_NOCOPY) str = js_NewString(cx, str->chars, str->length, 0); else str = js_NewStringCopyN(cx, str->chars, str->length, 0); if (!str) return NULL; key = STRING_TO_JSVAL(str); } he = PR_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL); if (!he) { JS_ReportOutOfMemory(cx); return NULL; } } atom = (JSAtom *)he; #ifdef DEBUG_DUPLICATE_ATOMS hep = PR_HashTableRawLookup(table, keyHash, (void *)key); he = *hep; PR_ASSERT(atom == (JSAtom *)he); #endif if (flags & ATOM_NOHOLD) return atom; return js_HoldAtom(cx, atom); }
js_hash_atom_key(const void *key) { jsval v; jsdouble *dp; /* Order JSVAL_IS_* tests by likelihood of success. */ v = (jsval)key; if (JSVAL_IS_STRING(v)) return js_HashString(JSVAL_TO_STRING(v)); if (JSVAL_IS_INT(v)) return HASH_INT(JSVAL_TO_INT(v)); if (JSVAL_IS_DOUBLE(v)) { dp = JSVAL_TO_DOUBLE(v); return HASH_DOUBLE(dp); } if (JSVAL_IS_OBJECT(v)) return HASH_OBJECT(JSVAL_TO_OBJECT(v)); if (JSVAL_IS_BOOLEAN(v)) return HASH_BOOLEAN(JSVAL_TO_BOOLEAN(v)); return (JSHashNumber)v; }
static JSDHashNumber HashString(JSDHashTable *table, const void *key) { JS_ASSERT(IS_STRING_TABLE(table)); return js_HashString((JSString *)key); }
JSAtom * js_AtomizeString(JSContext *cx, JSString *str, uintN flags) { JSHashNumber keyHash; jsval key; JSAtomState *state; JSHashTable *table; JSHashEntry *he, **hep; JSAtom *atom; keyHash = js_HashString(str); key = STRING_TO_JSVAL(str); state = &cx->runtime->atomState; JS_LOCK(&state->lock, cx); table = state->table; hep = JS_HashTableRawLookup(table, keyHash, (void *)key); if ((he = *hep) == NULL) { #ifdef JS_THREADSAFE uint32 gen = state->tablegen; JS_UNLOCK(&state->lock, cx); #endif if (flags & ATOM_TMPSTR) { str = (flags & ATOM_NOCOPY) ? js_NewString(cx, str->chars, str->length, 0) : js_NewStringCopyN(cx, str->chars, str->length, 0); if (!str) return NULL; key = STRING_TO_JSVAL(str); } else { if (!JS_MakeStringImmutable(cx, str)) return NULL; } #ifdef JS_THREADSAFE JS_LOCK(&state->lock, cx); if (state->tablegen != gen) { hep = JS_HashTableRawLookup(table, keyHash, (void *)key); if ((he = *hep) != NULL) { atom = (JSAtom *)he; if (flags & ATOM_NOCOPY) str->chars = NULL; goto out; } } #endif he = JS_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL); if (!he) { JS_ReportOutOfMemory(cx); atom = NULL; goto out; } } atom = (JSAtom *)he; atom->flags |= flags & (ATOM_PINNED | ATOM_INTERNED); out: JS_UNLOCK(&state->lock,cx); return atom; }