示例#1
0
JS_HashTableEnumerateEntries(JSHashTable *ht, JSHashEnumerator f, void *arg)
{
    JSHashEntry *he, **hep, **bucket;
    uint32 nlimit, n, nbuckets, newlog2;
    int rv;

    nlimit = ht->nentries;
    n = 0;
    for (bucket = ht->buckets; n != nlimit; ++bucket) {
        hep = bucket;
        while ((he = *hep) != NULL) {
            JS_ASSERT(n < nlimit);
            rv = f(he, n, arg);
            n++;
            if (rv & HT_ENUMERATE_REMOVE) {
                *hep = he->next;
                ht->allocOps->freeEntry(ht->allocPriv, he, HT_FREE_ENTRY);
                --ht->nentries;
            } else {
                hep = &he->next;
            }
            if (rv & HT_ENUMERATE_STOP) {
                goto out;
            }
        }
    }

out:
    /* Shrink table if removal of entries made it underloaded */
    if (ht->nentries != nlimit) {
        JS_ASSERT(ht->nentries < nlimit);
        nbuckets = NBUCKETS(ht);
        if (MINBUCKETS < nbuckets && ht->nentries < UNDERLOADED(nbuckets)) {
            newlog2 = JS_CeilingLog2(ht->nentries);
            if (newlog2 < MINBUCKETSLOG2)
                newlog2 = MINBUCKETSLOG2;

            /*  Check that we really shrink the table. */
            JS_ASSERT(JS_HASH_BITS - ht->shift > newlog2);
            Resize(ht, JS_HASH_BITS - newlog2);
        }
    }
    return (int)n;
}
示例#2
0
Int32 HashTableEnumerateEntries(HashTable *ht, HashEnumerator f)
{
    HashEntry *he = NULL, **hep = NULL;
    Uint32 i = 0, nbuckets = 0;
    int rv = 0, n = 0;
    HashEntry *todo = 0;

    nbuckets = NBUCKETS(ht);
    for (i = 0; i < nbuckets; i++)
    {
        hep = &ht->buckets[i];
        while ((he = *hep) != 0)
        {
            rv = (*f)(he, n);
            n++;
            if (rv & (HT_ENUMERATE_REMOVE | HT_ENUMERATE_UNHASH))
            {
                *hep = he->next;
                if (rv & HT_ENUMERATE_REMOVE)
                {
                    he->next = todo;
                    todo = he;
                }
            }
            else
            {
                hep = &he->next;
            }
            if (rv & HT_ENUMERATE_STOP)
            {
                goto out;
            }
        }
    }

out:
    hep = &todo;
    while ((he = *hep) != 0)
    {
        HashTableRawRemove(ht, hep, he);
    }
    return n;
}
示例#3
0
PL_HashTableDumpMeter(PLHashTable *ht, PLHashEnumerator dump, FILE *fp)
{
    double mean, variance;
    PRUint32 nchains, nbuckets;
    PRUint32 i, n, maxChain, maxChainLen;
    PLHashEntry *he;

    variance = 0;
    nchains = 0;
    maxChainLen = 0;
    nbuckets = NBUCKETS(ht);
    for (i = 0; i < nbuckets; i++) {
        he = ht->buckets[i];
        if (!he)
            continue;
        nchains++;
        for (n = 0; he; he = he->next)
            n++;
        variance += n * n;
        if (n > maxChainLen) {
            maxChainLen = n;
            maxChain = i;
        }
    }
    mean = (double)ht->nentries / nchains;
    variance = fabs(variance / nchains - mean * mean);

    fprintf(fp, "\nHash table statistics:\n");
    fprintf(fp, "     number of lookups: %u\n", ht->nlookups);
    fprintf(fp, "     number of entries: %u\n", ht->nentries);
    fprintf(fp, "       number of grows: %u\n", ht->ngrows);
    fprintf(fp, "     number of shrinks: %u\n", ht->nshrinks);
    fprintf(fp, "   mean steps per hash: %g\n", (double)ht->nsteps
                                                / ht->nlookups);
    fprintf(fp, "mean hash chain length: %g\n", mean);
    fprintf(fp, "    standard deviation: %g\n", sqrt(variance));
    fprintf(fp, " max hash chain length: %u\n", maxChainLen);
    fprintf(fp, "        max hash chain: [%u]\n", maxChain);

    for (he = ht->buckets[maxChain], i = 0; he; he = he->next, i++)
        if ((*dump)(he, i, fp) != HT_ENUMERATE_NEXT)
            break;
}
示例#4
0
JS_HashTableDumpMeter(JSHashTable *ht, JSHashEnumerator dump, FILE *fp)
{
    double sqsum, mean, sigma;
    uint32 nchains, nbuckets;
    uint32 i, n, maxChain, maxChainLen;
    JSHashEntry *he;

    sqsum = 0;
    nchains = 0;
    maxChain = maxChainLen = 0;
    nbuckets = NBUCKETS(ht);
    for (i = 0; i < nbuckets; i++) {
        he = ht->buckets[i];
        if (!he)
            continue;
        nchains++;
        for (n = 0; he; he = he->next)
            n++;
        sqsum += n * n;
        if (n > maxChainLen) {
            maxChainLen = n;
            maxChain = i;
        }
    }

    mean = JS_MeanAndStdDev(nchains, ht->nentries, sqsum, &sigma);

    fprintf(fp, "\nHash table statistics:\n");
    fprintf(fp, "     number of lookups: %u\n", ht->nlookups);
    fprintf(fp, "     number of entries: %u\n", ht->nentries);
    fprintf(fp, "       number of grows: %u\n", ht->ngrows);
    fprintf(fp, "     number of shrinks: %u\n", ht->nshrinks);
    fprintf(fp, "   mean steps per hash: %g\n", (double)ht->nsteps
                                                / ht->nlookups);
    fprintf(fp, "mean hash chain length: %g\n", mean);
    fprintf(fp, "    standard deviation: %g\n", sigma);
    fprintf(fp, " max hash chain length: %u\n", maxChainLen);
    fprintf(fp, "        max hash chain: [%u]\n", maxChain);

    for (he = ht->buckets[maxChain], i = 0; he; he = he->next, i++)
        if (dump(he, i, fp) != HT_ENUMERATE_NEXT)
            break;
}
示例#5
0
PL_HashTableRawRemove(PLHashTable *ht, PLHashEntry **hep, PLHashEntry *he)
{
    PRUint32 i, n;
    PLHashEntry *next, **oldbuckets;
    PRSize nb;

    *hep = he->next;
    (*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_ENTRY);

    /* Shrink table if it's underloaded */
    n = NBUCKETS(ht);
    if (--ht->nentries < UNDERLOADED(n)) {
        oldbuckets = ht->buckets;
        nb = n * sizeof(PLHashEntry*) / 2;
        ht->buckets = (PLHashEntry**)(
            (*ht->allocOps->allocTable)(ht->allocPriv, nb));
        if (!ht->buckets) {
            ht->buckets = oldbuckets;
            return;
        }
        memset(ht->buckets, 0, nb);
#ifdef HASHMETER
        ht->nshrinks++;
#endif
        ht->shift++;

        for (i = 0; i < n; i++) {
            for (he = oldbuckets[i]; he; he = next) {
                next = he->next;
                hep = PL_HashTableRawLookup(ht, he->keyHash, he->key);
                PR_ASSERT(*hep == 0);
                he->next = 0;
                *hep = he;
            }
        }
#ifdef DEBUG
        memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]);
#endif
        (*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets);
    }
}
示例#6
0
PL_HashTableDestroy(PLHashTable *ht)
{
    PRUint32 i, n;
    PLHashEntry *he, *next;
    const PLHashAllocOps *allocOps = ht->allocOps;
    void *allocPriv = ht->allocPriv;

    n = NBUCKETS(ht);
    for (i = 0; i < n; i++) {
        for (he = ht->buckets[i]; he; he = next) {
            next = he->next;
            (*allocOps->freeEntry)(allocPriv, he, HT_FREE_ENTRY);
        }
    }
#ifdef DEBUG
    memset(ht->buckets, 0xDB, n * sizeof ht->buckets[0]);
#endif
    (*allocOps->freeTable)(allocPriv, ht->buckets);
#ifdef DEBUG
    memset(ht, 0xDB, sizeof *ht);
#endif
    (*allocOps->freeTable)(allocPriv, ht);
}
示例#7
0
JS_HashTableDestroy(JSHashTable *ht)
{
    uint32 i, n;
    JSHashEntry *he, **hep;
    JSHashAllocOps *allocOps = ht->allocOps;
    void *allocPriv = ht->allocPriv;

    n = NBUCKETS(ht);
    for (i = 0; i < n; i++) {
        hep = &ht->buckets[i];
        while ((he = *hep) != NULL) {
            *hep = he->next;
            allocOps->freeEntry(allocPriv, he, HT_FREE_ENTRY);
        }
    }
#ifdef DEBUG
    memset(ht->buckets, 0xDB, n * sizeof ht->buckets[0]);
#endif
    allocOps->freeTable(allocPriv, ht->buckets, n * sizeof ht->buckets[0]);
#ifdef DEBUG
    memset(ht, 0xDB, sizeof *ht);
#endif
    allocOps->freeTable(allocPriv, ht, sizeof *ht);
}
示例#8
0
HashEntry *HashTableRawAdd(HashTable *ht, HashEntry **hep,
                           HashNumber keyHash, const void *key, void *value)
{
    Uint32 i = 0, n = 0, nbuckets = 0;
    HashEntry *he = NULL, *next = NULL, **oldbuckets = NULL;
    Size_t nb = 0;

    /* Grow the table if it is overloaded */
    n = NBUCKETS(ht);
    if (ht->nentries >= OVERLOADED(n))
    {
        oldbuckets = ht->buckets;
        nbuckets = hash_next_prime(n + 1);
        nb = 2 * nbuckets * sizeof(HashEntry *);
        ht->buckets = (HashEntry **)((*ht->allocOps->allocTable)(ht->allocPriv, nb));
        if (!ht->buckets)
        {
            ht->buckets = oldbuckets;
            return 0;
        }
        memset(ht->buckets, 0, nb);
        ht->nbuckets = nbuckets;
#ifdef HASHMETER
        ht->ngrows++;
#endif

        for (i = 0; i < n; i++)
        {
            for (he = oldbuckets[i]; he; he = next)
            {
                next = he->next;
                hep = HashTableRawLookup(ht, he->keyHash, he->key);
                if (*hep != 0)
                {
                    PR_LOG("##### Oops! %s: Severe problem.\n", __func__);
                    return 0;
                }
                he->next = 0;
                *hep = he;
            }
        }
#ifdef HASHDEBUG
        memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]);
#endif
        (*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets);
        hep = HashTableRawLookup(ht, keyHash, key);
    }

    /* Make a new key value entry */
    he = (*ht->allocOps->allocEntry)(ht->allocPriv, key);
    if (!he)
    {
        return 0;
    }

    he->keyHash = keyHash;
    he->key = key;
    he->value = value;
    he->next = *hep;
    *hep = he;
    ht->nentries++;

    return he;
}