PL_HashTableRawAdd(PLHashTable *ht, PLHashEntry **hep, PLHashNumber keyHash, const void *key, void *value) { PRUint32 i, n; PLHashEntry *he, *next, **oldbuckets; PRSize nb; /* Grow the table if it is overloaded */ n = NBUCKETS(ht); if (ht->nentries >= OVERLOADED(n)) { oldbuckets = ht->buckets; #if defined(WIN16) if (2 * n > 16000) return 0; #endif /* WIN16 */ nb = 2 * n * sizeof(PLHashEntry *); ht->buckets = (PLHashEntry**) ((*ht->allocOps->allocTable)(ht->allocPriv, nb)); if (!ht->buckets) { ht->buckets = oldbuckets; return 0; } memset(ht->buckets, 0, nb); #ifdef HASHMETER ht->ngrows++; #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); hep = PL_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; }
tmgraphnode *tmreader_component(tmreader *tmr, const char *name) { PLHashNumber hash; hash = PL_HashString(name); return (tmgraphnode*) *PL_HashTableRawLookup(tmr->components, hash, name); }
tmgraphnode *tmreader_filename(tmreader *tmr, uint32 serial) { const void *key; PLHashNumber hash; key = (const void*) serial; hash = hash_serial(key); return (tmgraphnode*) *PL_HashTableRawLookup(tmr->filenames, hash, key); }
tmmethodnode *tmreader_method(tmreader *tmr, uint32 serial) { const void *key; PLHashNumber hash; key = (const void*) serial; hash = hash_serial(key); return (tmmethodnode*) *PL_HashTableRawLookup(tmr->methods, hash, key); }
tmcallsite *tmreader_callsite(tmreader *tmr, uint32 serial) { const void *key; PLHashNumber hash; key = (const void*) serial; hash = hash_serial(key); return (tmcallsite*) *PL_HashTableRawLookup(tmr->callsites, hash, key); }
static int32_t* GetCOMPtrCount(void* aPtr) { PLHashEntry** hep = PL_HashTableRawLookup(gSerialNumbers, PLHashNumber(NS_PTR_TO_INT32(aPtr)), aPtr); if (hep && *hep) { return &((reinterpret_cast<serialNumberRecord*>((*hep)->value))->COMPtrCount); } else { return nullptr; } }
static int32_t* GetCOMPtrCount(void* aPtr) { PLHashEntry** hep = PL_HashTableRawLookup(gSerialNumbers, HashNumber(aPtr), aPtr); if (hep && *hep) { return &(static_cast<SerialNumberRecord*>((*hep)->value)->COMPtrCount); } return nullptr; }
PRBool ATSUILayoutCache::Get(atsuiLayoutCacheKey *key, ATSUTextLayout *txlayout) { PLHashEntry **hep = PL_HashTableRawLookup(mTable, HashKey(key), key); PLHashEntry *he = *hep; if( he ) { *txlayout = (ATSUTextLayout)he->value; return PR_TRUE; } return PR_FALSE; }
PL_HashTableLookup(PLHashTable *ht, const void *key) { PLHashNumber keyHash; PLHashEntry *he, **hep; keyHash = (*ht->keyHash)(key); hep = PL_HashTableRawLookup(ht, keyHash, key); if ((he = *hep) != 0) { return he->value; } return 0; }
static nsNamedVector* GetVector(PLHashTable* table, const void* key) { PLHashNumber hash = _hash_pointer(key); PLHashEntry** hep = PL_HashTableRawLookup(table, hash, key); PLHashEntry* he = *hep; if (he) return (nsNamedVector*) he->value; nsNamedVector* vec = new nsNamedVector(); if (vec) PL_HashTableRawAdd(table, hep, hash, key, vec); return vec; }
PL_HashTableRemove(PLHashTable *ht, const void *key) { PLHashNumber keyHash; PLHashEntry *he, **hep; keyHash = (*ht->keyHash)(key); hep = PL_HashTableRawLookup(ht, keyHash, key); if ((he = *hep) == 0) return PR_FALSE; /* Hit; remove element */ PL_HashTableRawRemove(ht, hep, he); return PR_TRUE; }
static intptr_t GetSerialNumber(void* aPtr, bool aCreate) { PLHashEntry** hep = PL_HashTableRawLookup(gSerialNumbers, HashNumber(aPtr), aPtr); if (hep && *hep) { return static_cast<SerialNumberRecord*>((*hep)->value)->serialNumber; } else if (aCreate) { SerialNumberRecord* record = new SerialNumberRecord(); WalkTheStackSavingLocations(record->allocationStack); PL_HashTableRawAdd(gSerialNumbers, hep, HashNumber(aPtr), aPtr, static_cast<void*>(record)); return gNextSerialNumber; } return 0; }
static intptr_t GetSerialNumber(void* aPtr, bool aCreate) { PLHashEntry** hep = PL_HashTableRawLookup(gSerialNumbers, PLHashNumber(NS_PTR_TO_INT32(aPtr)), aPtr); if (hep && *hep) { return reinterpret_cast<serialNumberRecord*>((*hep)->value)->serialNumber; } else if (aCreate) { serialNumberRecord *record = PR_NEW(serialNumberRecord); record->serialNumber = ++gNextSerialNumber; record->refCount = 0; record->COMPtrCount = 0; PL_HashTableRawAdd(gSerialNumbers, hep, PLHashNumber(NS_PTR_TO_INT32(aPtr)), aPtr, reinterpret_cast<void*>(record)); return gNextSerialNumber; } else { return 0; } }
PL_HashTableAdd(PLHashTable *ht, const void *key, void *value) { PLHashNumber keyHash; PLHashEntry *he, **hep; keyHash = (*ht->keyHash)(key); hep = PL_HashTableRawLookup(ht, keyHash, key); if ((he = *hep) != 0) { /* Hit; see if values match */ if ((*ht->valueCompare)(he->value, value)) { /* key,value pair is already present in table */ return he; } if (he->value) (*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_VALUE); he->value = value; return he; } return PL_HashTableRawAdd(ht, hep, keyHash, key, value); }
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); } }
static intptr_t GetSerialNumber(void* aPtr, bool aCreate) { PLHashEntry** hep = PL_HashTableRawLookup(gSerialNumbers, HashNumber(aPtr), aPtr); if (hep && *hep) { MOZ_RELEASE_ASSERT(!aCreate, "If an object already has a serial number, we should be destroying it."); return static_cast<SerialNumberRecord*>((*hep)->value)->serialNumber; } if (!aCreate) { return 0; } SerialNumberRecord* record = new SerialNumberRecord(); WalkTheStackSavingLocations(record->allocationStack); PL_HashTableRawAdd(gSerialNumbers, hep, HashNumber(aPtr), aPtr, static_cast<void*>(record)); return gNextSerialNumber; }
int tmreader_eventloop(tmreader *tmr, const char *filename, tmeventhandler eventhandler) { FILE *fp; char buf[NS_TRACE_MALLOC_MAGIC_SIZE]; tmevent event; static const char magic[] = NS_TRACE_MALLOC_MAGIC; if (strcmp(filename, "-") == 0) { fp = stdin; } else { #if defined(XP_WIN32) fp = fopen(filename, "rb"); #else fp = fopen(filename, "r"); #endif if (!fp) { fprintf(stderr, "%s: can't open %s: %s.\n", tmr->program, filename, strerror(errno)); return 0; } } if (read(fileno(fp), buf, sizeof buf) != sizeof buf || strncmp(buf, magic, sizeof buf) != 0) { fprintf(stderr, "%s: bad magic string %s at start of %s.\n", tmr->program, buf, filename); fprintf(stderr, "either the data file is out of date,\nor your tools are out of date.\n"); return 0; } /* Read in ticks per second. Used to convert platform specific intervals to time values */ if (read(fileno(fp), &tmr->ticksPerSec, sizeof tmr->ticksPerSec) != sizeof tmr->ticksPerSec) { fprintf(stderr, "%s: Cannot read ticksPerSec. Log file read error.\n", tmr->program); return 0; } tmr->ticksPerSec = PR_ntohl(tmr->ticksPerSec); #ifdef DEBUG_dp printf("DEBUG: ticks per sec = %d\n", tmr->ticksPerSec); #endif while (get_tmevent(fp, &event)) { switch (event.type) { case TM_EVENT_LIBRARY: { const void *key; PLHashNumber hash; PLHashEntry **hep, *he; key = (const void*) event.serial; hash = hash_serial(key); hep = PL_HashTableRawLookup(tmr->libraries, hash, key); he = *hep; PR_ASSERT(!he); if (he) exit(2); he = PL_HashTableRawAdd(tmr->libraries, hep, hash, key, event.u.libname); if (!he) { perror(tmr->program); return -1; } break; } case TM_EVENT_FILENAME: { const void *key; PLHashNumber hash; PLHashEntry **hep, *he; key = (const void*) event.serial; hash = hash_serial(key); hep = PL_HashTableRawLookup(tmr->filenames, hash, key); he = *hep; PR_ASSERT(!he); if (he) exit(2); he = PL_HashTableRawAdd(tmr->filenames, hep, hash, key, event.u.srcname); if (!he) { perror(tmr->program); return -1; } break; } case TM_EVENT_METHOD: { const void *key, *sourcekey; PLHashNumber hash, sourcehash; PLHashEntry **hep, *he, **sourcehep, *sourcehe; char *name, *head, *mark, save; tmgraphnode *comp, *lib; tmmethodnode *meth; key = (const void*) event.serial; hash = hash_serial(key); hep = PL_HashTableRawLookup(tmr->methods, hash, key); he = *hep; PR_ASSERT(!he); if (he) exit(2); name = event.u.method.name; he = PL_HashTableRawAdd(tmr->methods, hep, hash, key, name); if (!he) { perror(tmr->program); return -1; } meth = (tmmethodnode*) he; meth->linenumber = event.u.method.linenumber; sourcekey = (const void*)event.u.method.filename; sourcehash = hash_serial(sourcekey); sourcehep = PL_HashTableRawLookup(tmr->filenames, sourcehash, sourcekey); sourcehe = *sourcehep; meth->sourcefile = filename_name(sourcehe); head = name; mark = strchr(name, ':'); if (!mark) { mark = name; while (*mark != '\0' && *mark == '_') mark++; head = mark; mark = strchr(head, '_'); if (!mark) { mark = strchr(head, '+'); if (!mark) mark = head + strlen(head); } } save = *mark; *mark = '\0'; hash = PL_HashString(head); hep = PL_HashTableRawLookup(tmr->components, hash, head); he = *hep; if (he) { comp = (tmgraphnode*) he; } else { head = strdup(head); if (head) { he = PL_HashTableRawAdd(tmr->components, hep, hash, head, head); } if (!he) { perror(tmr->program); return -1; } comp = (tmgraphnode*) he; key = (const void*) event.u.method.library; hash = hash_serial(key); lib = (tmgraphnode*) *PL_HashTableRawLookup(tmr->libraries, hash, key); if (lib) { comp->up = lib; comp->next = lib->down; lib->down = comp; } } *mark = save; meth->graphnode.up = comp; meth->graphnode.next = comp->down; comp->down = &(meth->graphnode); break; } case TM_EVENT_CALLSITE: { const void *key, *mkey; PLHashNumber hash, mhash; PLHashEntry **hep, *he; tmcallsite *site, *parent; tmmethodnode *meth; key = (const void*) event.serial; hash = hash_serial(key); hep = PL_HashTableRawLookup(tmr->callsites, hash, key); he = *hep; /* there should not be an entry here! */ PR_ASSERT(!he); if (he) exit(2); if (event.u.site.parent == 0) { parent = &tmr->calltree_root; } else { parent = tmreader_callsite(tmr, event.u.site.parent); if (!parent) { fprintf(stderr, "%s: no parent for %lu (%lu)!\n", tmr->program, (unsigned long) event.serial, (unsigned long) event.u.site.parent); continue; } } he = PL_HashTableRawAdd(tmr->callsites, hep, hash, key, NULL); if (!he) { perror(tmr->program); return -1; } site = (tmcallsite*) he; site->parent = parent; site->siblings = parent->kids; parent->kids = site; site->kids = NULL; mkey = (const void*) event.u.site.method; mhash = hash_serial(mkey); meth = (tmmethodnode*) *PL_HashTableRawLookup(tmr->methods, mhash, mkey); site->method = meth; site->offset = event.u.site.offset; site->allocs.bytes.direct = site->allocs.bytes.total = 0; site->allocs.calls.direct = site->allocs.calls.total = 0; site->frees.bytes.direct = site->frees.bytes.total = 0; site->frees.calls.direct = site->frees.calls.total = 0; break; } case TM_EVENT_MALLOC: case TM_EVENT_CALLOC: case TM_EVENT_REALLOC: { tmcallsite *site; uint32 size, oldsize; double delta, sqdelta, sqszdelta = 0; tmgraphnode *comp, *lib; tmmethodnode *meth; site = tmreader_callsite(tmr, event.serial); if (!site) { fprintf(stderr, "%s: no callsite for '%c' (%lu)!\n", tmr->program, event.type, (unsigned long) event.serial); continue; } size = event.u.alloc.size; oldsize = event.u.alloc.oldsize; delta = (double)size - (double)oldsize; site->allocs.bytes.direct += (unsigned long)delta; if (event.type != TM_EVENT_REALLOC) site->allocs.calls.direct++; meth = site->method; if (meth) { meth->graphnode.allocs.bytes.direct += (unsigned long)delta; sqdelta = delta * delta; if (event.type == TM_EVENT_REALLOC) { sqszdelta = ((double)size * size) - ((double)oldsize * oldsize); meth->graphnode.sqsum += sqszdelta; } else { meth->graphnode.sqsum += sqdelta; meth->graphnode.allocs.calls.direct++; } comp = meth->graphnode.up; if (comp) { comp->allocs.bytes.direct += (unsigned long)delta; if (event.type == TM_EVENT_REALLOC) { comp->sqsum += sqszdelta; } else { comp->sqsum += sqdelta; comp->allocs.calls.direct++; } lib = comp->up; if (lib) { lib->allocs.bytes.direct += (unsigned long)delta; if (event.type == TM_EVENT_REALLOC) { lib->sqsum += sqszdelta; } else { lib->sqsum += sqdelta; lib->allocs.calls.direct++; } } } } break; } case TM_EVENT_FREE: { tmcallsite *site; uint32 size; tmgraphnode *comp, *lib; tmmethodnode *meth; site = tmreader_callsite(tmr, event.serial); if (!site) { fprintf(stderr, "%s: no callsite for '%c' (%lu)!\n", tmr->program, event.type, (unsigned long) event.serial); continue; } size = event.u.alloc.size; site->frees.bytes.direct += size; site->frees.calls.direct++; meth = site->method; if (meth) { meth->graphnode.frees.bytes.direct += size; meth->graphnode.frees.calls.direct++; comp = meth->graphnode.up; if (comp) { comp->frees.bytes.direct += size; comp->frees.calls.direct++; lib = comp->up; if (lib) { lib->frees.bytes.direct += size; lib->frees.calls.direct++; } } } break; } case TM_EVENT_STATS: break; } eventhandler(tmr, &event); } return 1; }