static unsigned ValToBin(unsigned logscale, uint32_t val) { unsigned bin; if (val <= 1) return val; bin = (logscale == 10) ? (unsigned) ceil(log10((double) val)) : (logscale == 2) ? (unsigned) CeilingLog2Size(val) : val; return Min(bin, 10U); }
/* ** Iterate over the entries in the hash table calling func for each ** entry found. Stop if "f" says to (return value & JS_ENUMERATE_STOP). ** Return a count of the number of elements scanned. */ int JS_HashTableEnumerateEntries(JSHashTable *ht, JSHashEnumerator f, void *arg) { JSHashEntry *he, **hep, **bucket; uint32_t nlimit, n, nbuckets, newlog2; int rv; nlimit = ht->nentries; n = 0; for (bucket = ht->buckets; n != nlimit; ++bucket) { hep = bucket; while ((he = *hep) != nullptr) { 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 = CeilingLog2Size(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; }
JSHashTable * JS_NewHashTable(uint32_t n, JSHashFunction keyHash, JSHashComparator keyCompare, JSHashComparator valueCompare, const JSHashAllocOps *allocOps, void *allocPriv) { JSHashTable *ht; size_t nb; if (n <= MINBUCKETS) { n = MINBUCKETSLOG2; } else { n = CeilingLog2Size(n); if (int32_t(n) < 0) return nullptr; } if (!allocOps) allocOps = &defaultHashAllocOps; ht = (JSHashTable*) allocOps->allocTable(allocPriv, sizeof *ht); if (!ht) return nullptr; memset(ht, 0, sizeof *ht); ht->shift = JS_HASH_BITS - n; n = JS_BIT(n); nb = n * sizeof(JSHashEntry *); ht->buckets = (JSHashEntry**) allocOps->allocTable(allocPriv, nb); if (!ht->buckets) { allocOps->freeTable(allocPriv, ht, nb); return nullptr; } memset(ht->buckets, 0, nb); ht->keyHash = keyHash; ht->keyCompare = keyCompare; ht->valueCompare = valueCompare; ht->allocOps = allocOps; ht->allocPriv = allocPriv; return ht; }
void JS_DumpHistogram(JSBasicStats *bs, FILE *fp) { unsigned bin; uint32_t cnt, max; double sum, mean; for (bin = 0, max = 0, sum = 0; bin <= 10; bin++) { cnt = bs->hist[bin]; if (max < cnt) max = cnt; sum += cnt; } mean = sum / cnt; for (bin = 0; bin <= 10; bin++) { unsigned val = BinToVal(bs->logscale, bin); unsigned end = (bin == 10) ? 0 : BinToVal(bs->logscale, bin + 1); cnt = bs->hist[bin]; if (val + 1 == end) fprintf(fp, " [%6u]", val); else if (end != 0) fprintf(fp, "[%6u, %6u]", val, end - 1); else fprintf(fp, "[%6u, +inf]", val); fprintf(fp, ": %8u ", cnt); if (cnt != 0) { if (max > 1e6 && mean > 1e3) cnt = uint32_t(ceil(log10((double) cnt))); else if (max > 16 && mean > 8) cnt = CeilingLog2Size(cnt); for (unsigned i = 0; i < cnt; i++) putc('*', fp); } putc('\n', fp); } }