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; }
JSAtomListElement * JSAtomList::add(JSCompiler *jsc, JSAtom *atom, AddHow how) { JS_ASSERT(!set); JSAtomListElement *ale, *ale2, *next; JSHashEntry **hep; ale = rawLookup(atom, hep); if (!ale || how != UNIQUE) { if (count < ATOM_LIST_HASH_THRESHOLD && !table) { /* Few enough for linear search and no hash table yet needed. */ ale = (JSAtomListElement *)js_alloc_temp_entry(jsc, atom); if (!ale) return NULL; ALE_SET_ATOM(ale, atom); if (how == HOIST) { ale->entry.next = NULL; hep = (JSHashEntry **) &list; while (*hep) hep = &(*hep)->next; *hep = &ale->entry; } else { ale->entry.next = list; list = &ale->entry; } } else { /* * We should hash, or else we already are hashing, but count was * reduced by JSAtomList::rawRemove below ATOM_LIST_HASH_THRESHOLD. * Check whether we should create the table. */ if (!table) { /* No hash table yet, so hep had better be null! */ JS_ASSERT(!hep); table = JS_NewHashTable(count + 1, js_hash_atom_ptr, JS_CompareValues, JS_CompareValues, &temp_alloc_ops, jsc); if (!table) return NULL; /* * Set ht->nentries explicitly, because we are moving entries * from list to ht, not calling JS_HashTable(Raw|)Add. */ table->nentries = count; /* * Insert each ale on list into the new hash table. Append to * the hash chain rather than inserting at the bucket head, to * preserve order among entries with the same key. */ for (ale2 = (JSAtomListElement *)list; ale2; ale2 = next) { next = ALE_NEXT(ale2); ale2->entry.keyHash = ATOM_HASH(ALE_ATOM(ale2)); hep = JS_HashTableRawLookup(table, ale2->entry.keyHash, ale2->entry.key); while (*hep) hep = &(*hep)->next; *hep = &ale2->entry; ale2->entry.next = NULL; } list = NULL; /* Set hep for insertion of atom's ale, immediately below. */ hep = JS_HashTableRawLookup(table, ATOM_HASH(atom), atom); } /* Finally, add an entry for atom into the hash bucket at hep. */ ale = (JSAtomListElement *) JS_HashTableRawAdd(table, hep, ATOM_HASH(atom), atom, NULL); if (!ale) return NULL; /* * If hoisting, move ale to the end of its chain after we called * JS_HashTableRawAdd, since RawAdd may have grown the table and * then recomputed hep to refer to the pointer to the first entry * with the given key. */ if (how == HOIST && ale->entry.next) { JS_ASSERT(*hep == &ale->entry); *hep = ale->entry.next; ale->entry.next = NULL; do { hep = &(*hep)->next; } while (*hep); *hep = &ale->entry; } } ALE_SET_INDEX(ale, count++); } return ale; }