void js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al) { JSAtom **vector; JSAtomListElement *ale; uint32 count; /* Map length must already be initialized. */ JS_ASSERT(al->count == map->length); #ifdef DEBUG JS_ATOMIC_INCREMENT(&js_atom_map_count); #endif ale = (JSAtomListElement *)al->list; if (!ale && !al->table) { JS_ASSERT(!map->vector); return; } count = al->count; vector = map->vector; 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); } al->clear(); }
JSAtomListElement * JSAtomListIterator::operator ()() { JSAtomListElement *ale; JSHashTable *ht; if (index == uint32(-1)) return NULL; ale = next; if (!ale) { ht = list->table; if (!ht) goto done; do { if (index == JS_BIT(JS_HASH_BITS - ht->shift)) goto done; next = (JSAtomListElement *) ht->buckets[index++]; } while (!next); ale = next; } next = ALE_NEXT(ale); return ale; done: index = uint32(-1); return NULL; }
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; }
static JSHashEntry * js_alloc_temp_entry(void *priv, const void *key) { JSCompiler *jsc = (JSCompiler *) priv; JSAtomListElement *ale; ale = jsc->aleFreeList; if (ale) { jsc->aleFreeList = ALE_NEXT(ale); return &ale->entry; } JS_ARENA_ALLOCATE_TYPE(ale, JSAtomListElement, &jsc->context->tempPool); if (!ale) { js_ReportOutOfScriptQuota(jsc->context); return NULL; } return &ale->entry; }
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; }
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; }