static uint hash_key(hashtable_t *table, void *key) { uint hash = 0; if (table->hash_key_func != NULL) { hash = table->hash_key_func(key); } else if (table->hashtype == HASH_STRING || table->hashtype == HASH_STRING_NOCASE) { const char *s = (const char *) key; char c; uint i, shift; uint max_shift = ALIGN_FORWARD(table->table_bits, 8); /* XXX: share w/ core's hash_value() function */ for (i = 0; s[i] != '\0'; i++) { c = s[i]; if (table->hashtype == HASH_STRING_NOCASE) c = (char) tolower(c); shift = (i % 4) * 8; if (shift > max_shift) shift = max_shift; hash ^= c << shift; } } else { /* HASH_INTPTR, or fallback for HASH_CUSTOM in release build */ ASSERT(table->hashtype == HASH_INTPTR, "hashtable.c hash_key internal error: invalid hash type"); hash = (uint)(ptr_uint_t) key; } return HASH_FUNC_BITS(hash, table->table_bits); }
/* Lookup an entry by pc and return a pointer to the corresponding entry . * Returns NULL if no such entry exists. * Caller must hold htable_mutex if drcontext == NULL. */ static trace_head_entry_t * lookup_trace_head_entry(void *drcontext, void *tag) { trace_head_entry_t **table = htable; trace_head_entry_t *e; uint hindex; hindex = (uint) HASH_FUNC_BITS((ptr_uint_t)tag, HASH_BITS); for (e = table[hindex]; e; e = e->next) { if (e->tag == tag) return e; } return NULL; }
/* Caller must hold htable_mutex if drcontext == NULL. */ static trace_head_entry_t * add_trace_head_entry(void *drcontext, void *tag) { trace_head_entry_t **table = htable; trace_head_entry_t *e; uint hindex; e = (trace_head_entry_t *) dr_global_alloc(sizeof(trace_head_entry_t)); e->tag = tag; e->end_next = 0; e->size = 0; e->has_ret = false; e->is_trace_head = false; hindex = (uint) HASH_FUNC_BITS((ptr_uint_t)tag, HASH_BITS); e->next = table[hindex]; table[hindex] = e; return e; }
/* Lookup an entry by tag and index and delete it. * Returns false if no such entry exists. * Caller must hold htable_mutex if drcontext == NULL. */ static bool remove_trace_head_entry(void *drcontext, void *tag) { trace_head_entry_t **table = htable; trace_head_entry_t *e, *prev; uint hindex; hindex = (uint) HASH_FUNC_BITS((ptr_uint_t)tag, HASH_BITS); for (prev = NULL, e = table[hindex]; e; prev = e, e = e->next) { if (e->tag == tag) { if (prev) prev->next = e->next; else table[hindex] = e->next; dr_global_free(e, sizeof(trace_head_entry_t)); return true; } } return false; }
static uint hash_key(hashtable_t *table, void *key) { uint hash = 0; if (table->hash_key_func != NULL) { hash = table->hash_key_func(key); } else if (table->hashtype == HASH_STRING || table->hashtype == HASH_STRING_NOCASE) { const char *s = (const char *) key; char c; for (c = *s; c != '\0'; c = *(s++)) { if (table->hashtype == HASH_STRING_NOCASE) c = (char) tolower(c); hash ^= (c << (((s - (const char *)key) %4) * 8)); } } else { /* HASH_INTPTR, or fallback for HASH_CUSTOM in release build */ ASSERT(table->hashtype == HASH_INTPTR, "hashtable.c hash_key internal error: invalid hash type"); hash = (uint)(ptr_uint_t) key; } return HASH_FUNC_BITS(hash, table->table_bits); }