📄 jsatom.c
字号:
voidjs_UnpinPinnedAtoms(JSAtomState *state){ if (state->table) JS_HashTableEnumerateEntries(state->table, js_atom_unpinner, NULL);}static JSAtom *js_AtomizeHashedKey(JSContext *cx, jsval key, JSHashNumber keyHash, uintN flags){ JSAtomState *state; JSHashTable *table; JSHashEntry *he, **hep; JSAtom *atom; state = &cx->runtime->atomState; JS_LOCK(&state->lock, cx); table = state->table; hep = JS_HashTableRawLookup(table, keyHash, (void *)key); if ((he = *hep) == NULL) { he = JS_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL); if (!he) { JS_ReportOutOfMemory(cx); atom = NULL; goto out; } } atom = (JSAtom *)he; atom->flags |= flags; cx->weakRoots.lastAtom = atom;out: JS_UNLOCK(&state->lock,cx); return atom;}JSAtom *js_AtomizeObject(JSContext *cx, JSObject *obj, uintN flags){ jsval key; JSHashNumber keyHash; /* XXX must be set in the following order or MSVC1.52 will crash */ keyHash = HASH_OBJECT(obj); key = OBJECT_TO_JSVAL(obj); return js_AtomizeHashedKey(cx, key, keyHash, flags);}JSAtom *js_AtomizeBoolean(JSContext *cx, JSBool b, uintN flags){ jsval key; JSHashNumber keyHash; key = BOOLEAN_TO_JSVAL(b); keyHash = HASH_BOOLEAN(b); return js_AtomizeHashedKey(cx, key, keyHash, flags);}JSAtom *js_AtomizeInt(JSContext *cx, jsint i, uintN flags){ jsval key; JSHashNumber keyHash; key = INT_TO_JSVAL(i); keyHash = HASH_INT(i); return js_AtomizeHashedKey(cx, key, keyHash, flags);}/* Worst-case alignment grain and aligning macro for 2x-sized buffer. */#define ALIGNMENT(t) JS_MAX(JSVAL_ALIGN, sizeof(t))#define ALIGN(b,t) ((t*) &(b)[ALIGNMENT(t) - (jsuword)(b) % ALIGNMENT(t)])JSAtom *js_AtomizeDouble(JSContext *cx, jsdouble d, uintN flags){ jsdouble *dp; JSHashNumber keyHash; jsval key; JSAtomState *state; JSHashTable *table; JSHashEntry *he, **hep; JSAtom *atom; char buf[2 * ALIGNMENT(double)]; dp = ALIGN(buf, double); *dp = d; keyHash = HASH_DOUBLE(dp); key = DOUBLE_TO_JSVAL(dp); 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;#endif JS_UNLOCK(&state->lock,cx); if (!js_NewDoubleValue(cx, d, &key)) return NULL; JS_LOCK(&state->lock, cx);#ifdef JS_THREADSAFE if (state->tablegen != gen) { hep = JS_HashTableRawLookup(table, keyHash, (void *)key); if ((he = *hep) != NULL) { atom = (JSAtom *)he; 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; cx->weakRoots.lastAtom = atom;out: JS_UNLOCK(&state->lock,cx); return atom;}/* * To put an atom into the hidden subspace. XOR its keyHash with this value, * which is (sqrt(2)-1) in 32-bit fixed point. */#define HIDDEN_ATOM_SUBSPACE_KEYHASH 0x6A09E667JSAtom *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); if (flags & ATOM_HIDDEN) keyHash ^= HIDDEN_ATOM_SUBSPACE_KEYHASH; 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 | ATOM_HIDDEN); cx->weakRoots.lastAtom = atom;out: JS_UNLOCK(&state->lock,cx); return atom;}JS_FRIEND_API(JSAtom *)js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags){ jschar *chars; JSString *str; JSAtom *atom; char buf[2 * ALIGNMENT(JSString)]; /* * Avoiding the malloc in js_InflateString on shorter strings saves us * over 20,000 malloc calls on mozilla browser startup. This compares to * only 131 calls where the string is longer than a 31 char (net) buffer. * The vast majority of atomized strings are already in the hashtable. So * js_AtomizeString rarely has to copy the temp string we make. */#define ATOMIZE_BUF_MAX 32 jschar inflated[ATOMIZE_BUF_MAX]; size_t inflatedLength = ATOMIZE_BUF_MAX - 1; if (length < ATOMIZE_BUF_MAX) { js_InflateStringToBuffer(cx, bytes, length, inflated, &inflatedLength); inflated[inflatedLength] = 0; chars = inflated; } else { inflatedLength = length; chars = js_InflateString(cx, bytes, &inflatedLength); if (!chars) return NULL; flags |= ATOM_NOCOPY; } str = ALIGN(buf, JSString); str->chars = chars; str->length = inflatedLength; atom = js_AtomizeString(cx, str, ATOM_TMPSTR | flags); if (chars != inflated && (!atom || ATOM_TO_STRING(atom)->chars != chars)) JS_free(cx, chars); return atom;}JS_FRIEND_API(JSAtom *)js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags){ JSString *str; char buf[2 * ALIGNMENT(JSString)]; str = ALIGN(buf, JSString); str->chars = (jschar *)chars; str->length = length; return js_AtomizeString(cx, str, ATOM_TMPSTR | flags);}JSAtom *js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length){ JSString *str; char buf[2 * ALIGNMENT(JSString)]; JSHashNumber keyHash; jsval key; JSAtomState *state; JSHashTable *table; JSHashEntry **hep; str = ALIGN(buf, JSString); str->chars = (jschar *)chars; str->length = length; 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); JS_UNLOCK(&state->lock, cx); return (hep) ? (JSAtom *)*hep : NULL;}JSAtom *js_AtomizeValue(JSContext *cx, jsval value, uintN flags){ if (JSVAL_IS_STRING(value)) return js_AtomizeString(cx, JSVAL_TO_STRING(value), flags); if (JSVAL_IS_INT(value)) return js_AtomizeInt(cx, JSVAL_TO_INT(value), flags); if (JSVAL_IS_DOUBLE(value)) return js_AtomizeDouble(cx, *JSVAL_TO_DOUBLE(value), flags); if (JSVAL_IS_OBJECT(value)) return js_AtomizeObject(cx, JSVAL_TO_OBJECT(value), flags); if (JSVAL_IS_BOOLEAN(value)) return js_AtomizeBoolean(cx, JSVAL_TO_BOOLEAN(value), flags); return js_AtomizeHashedKey(cx, value, (JSHashNumber)value, flags);}JSAtom *js_ValueToStringAtom(JSContext *cx, jsval v){ JSString *str; str = js_ValueToString(cx, v); if (!str) return NULL; return js_AtomizeString(cx, str, 0);}JS_STATIC_DLL_CALLBACK(JSHashNumber)js_hash_atom_ptr(const void *key){ const JSAtom *atom = key; return atom->number;}JS_STATIC_DLL_CALLBACK(void *)js_alloc_temp_space(void *priv, size_t size){ JSContext *cx = priv; void *space; JS_ARENA_ALLOCATE(space, &cx->tempPool, size); if (!space) JS_ReportOutOfMemory(cx); return space;}JS_STATIC_DLL_CALLBACK(void)js_free_temp_space(void *priv, void *item){}JS_STATIC_DLL_CALLBACK(JSHashEntry *)js_alloc_temp_entry(void *priv, const void *key){ JSContext *cx = priv; JSAtomListElement *ale; JS_ARENA_ALLOCATE_TYPE(ale, JSAtomListElement, &cx->tempPool); if (!ale) { JS_ReportOutOfMemory(cx); return NULL; } return &ale->entry;}JS_STATIC_DLL_CALLBACK(void)js_free_temp_entry(void *priv, JSHashEntry *he, uintN flag){}static JSHashAllocOps temp_alloc_ops = { js_alloc_temp_space, js_free_temp_space, js_alloc_temp_entry, js_free_temp_entry};JSAtomListElement *js_IndexAtom(JSContext *cx, JSAtom *atom, JSAtomList *al){ JSAtomListElement *ale, *ale2, *next; JSHashEntry **hep; ATOM_LIST_LOOKUP(ale, hep, al, atom); if (!ale) { if (al->count < 10) { /* Few enough for linear search, no hash table needed. */ JS_ASSERT(!al->table); ale = (JSAtomListElement *)js_alloc_temp_entry(cx, atom); if (!ale) return NULL; ALE_SET_ATOM(ale, atom); ALE_SET_NEXT(ale, al->list); al->list = ale; } else { /* We want to hash. Have we already made a hash table? */ if (!al->table) { /* No hash table yet, so hep had better be null! */ JS_ASSERT(!hep); al->table = JS_NewHashTable(al->count + 1, js_hash_atom_ptr, JS_CompareValues, JS_CompareValues, &temp_alloc_ops, cx); if (!al->table) return NULL; /* * Set ht->nentries explicitly, because we are moving entries * from al to ht, not calling JS_HashTable(Raw|)Add. */ al->table->nentries = al->count; /* Insert each ale on al->list into the new hash table. */ for (ale2 = al->list; ale2; ale2 = next) { next = ALE_NEXT(ale2); ale2->entry.keyHash = ALE_ATOM(ale2)->number; hep = JS_HashTableRawLookup(al->table, ale2->entry.keyHash, ale2->entry.key); ALE_SET_NEXT(ale2, *hep); *hep = &ale2->entry; } al->list = NULL; /* Set hep for insertion of atom's ale, immediately below. */ hep = JS_HashTableRawLookup(al->table, atom->number, atom); } /* Finally, add an entry for atom into the hash bucket at hep. */ ale = (JSAtomListElement *) JS_HashTableRawAdd(al->table, hep, atom->number, atom, NULL); if (!ale) return NULL; } ALE_SET_INDEX(ale, al->count++); } return ale;}JS_FRIEND_API(JSAtom *)js_GetAtom(JSContext *cx, JSAtomMap *map, jsatomid i){ JSAtom *atom; static JSAtom dummy; JS_ASSERT(map->vector && i < map->length); if (!map->vector || i >= map->length) { char numBuf[12]; JS_snprintf(numBuf, sizeof numBuf, "%lu", (unsigned long)i); JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ATOMIC_NUMBER, numBuf); return &dummy; } atom = map->vector[i]; JS_ASSERT(atom); return atom;}JS_STATIC_DLL_CALLBACK(intN)js_map_atom(JSHashEntry *he, intN i, void *arg){ JSAtomListElement *ale = (JSAtomListElement *)he; JSAtom **vector = arg; vector[ALE_INDEX(ale)] = ALE_ATOM(ale); return HT_ENUMERATE_NEXT;}#ifdef DEBUGstatic jsrefcount js_atom_map_count;static jsrefcount js_atom_map_hash_table_count;#endifJS_FRIEND_API(JSBool)js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al){ JSAtom **vector; JSAtomListElement *ale; uint32 count;#ifdef DEBUG JS_ATOMIC_INCREMENT(&js_atom_map_count);#endif ale = al->list; if (!ale && !al->table) { map->vector = NULL; map->length = 0; return JS_TRUE; } count = al->count; if (count >= ATOM_INDEX_LIMIT) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TOO_MANY_LITERALS); return JS_FALSE; } vector = (JSAtom **) JS_malloc(cx, (size_t) count * sizeof *vector); if (!vector) return JS_FALSE; if (al->table) {#ifdef DEBUG JS_ATOMIC_INCREMENT(&js_atom_map_hash_table_count);#endif JS_HashTableEnumerateEntries(al->table, js_map_atom, vector); } else { do { vector[ALE_INDEX(ale)] = ALE_ATOM(ale); } while ((ale = ALE_NEXT(ale)) != NULL); } ATOM_LIST_INIT(al); map->vector = vector; map->length = (jsatomid)count; return JS_TRUE;}JS_FRIEND_API(void)js_FreeAtomMap(JSContext *cx, JSAtomMap *map){ if (map->vector) { JS_free(cx, map->vector); map->vector = NULL; } map->length = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -