size = JS_BIT(table->sizeLog2); if (table->entryCount + table->removedCount >= size - (size >> 2)) { if (table->removedCount >= size >> 2) { METER(table->stats.compresses++); biasedDeltaLog2 = 0 + DELTA_LOG2_BIAS; } else { METER(table->stats.grows++); biasedDeltaLog2 = 1 + DELTA_LOG2_BIAS; } }
JS_DHashTableOperate(JSDHashTable *table, const void *key, JSDHashOperator op){    int biasedDeltaLog2;    JSDHashNumber keyHash;    JSDHashEntryHdr *entry;    uint32 size;/* * Usually we don't grow or shrink the table, so optimize for test-not-zero * by biasing the deltaLog2 of -1 (shrink), 0 (compress), or 1 (grow) so that * the biased no-change value is 0. */#define DELTA_LOG2_BIAS 2    biasedDeltaLog2 = 0;    /* Avoid 0 and 1 hash codes, they indicate free and removed entries. */    keyHash = table->ops->hashKey(table, key);    ENSURE_LIVE_KEYHASH(keyHash);    keyHash *= JS_DHASH_GOLDEN_RATIO;    entry = SearchTable(table, key, keyHash);    switch (op) {      case JS_DHASH_LOOKUP:        METER(table->stats.lookups++);        break;      case JS_DHASH_ADD:        if (JS_DHASH_ENTRY_IS_FREE(entry)) {            /* Initialize the entry, indicating that it's no longer free. */            METER(table->stats.addMisses++);            if (table->ops->initEntry)                table->ops->initEntry(table, entry, key);            entry->keyHash = keyHash;            table->entryCount++;            /* If alpha is >= .75, set biasedDeltaLog2 to trigger growth. */            size = JS_BIT(table->sizeLog2);            if (table->entryCount + table->removedCount >= size - (size >> 2)) {                if (table->removedCount >= size >> 2) {                    METER(table->stats.compresses++);                    biasedDeltaLog2 = 0 + DELTA_LOG2_BIAS;                } else {                    METER(table->stats.grows++);                    biasedDeltaLog2 = 1 + DELTA_LOG2_BIAS;                }            }        }        METER(else table->stats.addHits++);        break;      case JS_DHASH_REMOVE:        if (JS_DHASH_ENTRY_IS_BUSY(entry)) {            /* Clear this entry and mark it as "removed". */            METER(table->stats.removeHits++);            JS_DHashTableRawRemove(table, entry);            /* Shrink if alpha is <= .25 and table isn't too small already. */            size = JS_BIT(table->sizeLog2);            if (size > JS_DHASH_MIN_SIZE && table->entryCount <= size >> 2) {                METER(table->stats.shrinks++);                biasedDeltaLog2 = -1 + DELTA_LOG2_BIAS;            }        }        METER(else table->stats.removeMisses++);        entry = NULL;        break;      default:        JS_ASSERT(0);    }    if (biasedDeltaLog2) {        /* Grow, compress, or shrink table, keeping entry valid if non-null. */        if (!ChangeTable(table, biasedDeltaLog2 - DELTA_LOG2_BIAS, &entry)) {            /* If we just grabbed the last free entry, undo and fail hard. */            if (op == JS_DHASH_ADD &&                table->entryCount + table->removedCount == size) {                METER(table->stats.addFailures++);                table->ops->clearEntry(table, entry);                MARK_ENTRY_FREE(entry);                table->entryCount--;                entry = NULL;            }        }    }#undef DELTA_LOG2_BIAS    return entry;}