add per-item purging to the hash table

This commit is contained in:
Nikita Smith
2025-11-07 14:39:46 -08:00
committed by Ryan Fleury
parent 66606b0327
commit 880b8135cc
7 changed files with 89 additions and 58 deletions
+1 -4
View File
@@ -184,10 +184,7 @@ coff_lib_writer_serialize(Arena *arena, COFF_LibWriter *lib_writer, COFF_TimeSta
U64 name_with_slash_size = member->name.size + 1;
if (name_with_slash_size > COFF_Archive_MaxShortNameSize) {
// have we seen this member name before?
KeyValuePair *is_present = hash_table_search_string(name_ht, member->name);
if (is_present) {
name = is_present->value_string;
} else {
if (!hash_table_search_string_string(name_ht, member->name, &name)) {
name = push_str8f(scratch.arena, "/%u", long_names_list.total_size);
str8_list_pushf(scratch.arena, &long_names_list, "%S/\n", member->name);
hash_table_push_string_string(scratch.arena, name_ht, member->name, name);
+62 -30
View File
@@ -64,8 +64,8 @@ hash_table_push(Arena *arena, HashTable *ht, U64 hash, KeyValuePair v)
node->v = v;
U64 ibucket = hash % ht->cap;
SLLQueuePush(ht->buckets[ibucket].first, ht->buckets[ibucket].last, node);
++ht->count;
DLLPushBack(ht->buckets[ibucket].first, ht->buckets[ibucket].last, node);
ht->count += 1;
return node;
}
@@ -162,7 +162,7 @@ hash_table_push_path_raw(Arena *arena, HashTable *ht, String8 path, void *value)
////////////////////////////////
internal KeyValuePair *
internal BucketNode *
hash_table_search_string(HashTable *ht, String8 key_string)
{
U64 hash = hash_table_hasher(key_string);
@@ -170,13 +170,13 @@ hash_table_search_string(HashTable *ht, String8 key_string)
BucketList *bucket = ht->buckets + ibucket;
for (BucketNode *n = bucket->first; n != 0; n = n->next) {
if (str8_match(n->v.key_string, key_string, 0)) {
return &n->v;
return n;
}
}
return 0;
}
internal KeyValuePair *
internal BucketNode *
hash_table_search_u32(HashTable *ht, U32 key_u32)
{
U64 hash = hash_table_hasher(str8_struct(&key_u32));
@@ -184,13 +184,13 @@ hash_table_search_u32(HashTable *ht, U32 key_u32)
BucketList *bucket = ht->buckets + ibucket;
for (BucketNode *n = bucket->first; n != 0; n = n->next) {
if (n->v.key_u32 == key_u32) {
return &n->v;
return n;
}
}
return 0;
}
internal KeyValuePair *
internal BucketNode *
hash_table_search_u64(HashTable *ht, U64 key_u64)
{
U64 hash = hash_table_hasher(str8_struct(&key_u64));
@@ -198,25 +198,25 @@ hash_table_search_u64(HashTable *ht, U64 key_u64)
BucketList *bucket = ht->buckets + ibucket;
for (BucketNode *n = bucket->first; n != 0; n = n->next) {
if (n->v.key_u64 == key_u64) {
return &n->v;
return n;
}
}
return 0;
}
internal KeyValuePair *
internal BucketNode *
hash_table_search_path(HashTable *ht, String8 path)
{
Temp scratch = scratch_begin(0,0);
String8 path_canon = path;
path_canon = lower_from_str8(scratch.arena, path_canon);
path_canon = path_convert_slashes(scratch.arena, path_canon, PathStyle_UnixAbsolute);
KeyValuePair *result = hash_table_search_string(ht, path_canon);
BucketNode *result = hash_table_search_string(ht, path_canon);
scratch_end(scratch);
return result;
}
internal KeyValuePair *
internal BucketNode *
hash_table_search_raw(HashTable *ht, void *key)
{
U64 hash = hash_table_hasher(str8_struct(&key));
@@ -224,7 +224,7 @@ hash_table_search_raw(HashTable *ht, void *key)
BucketList *bucket = ht->buckets + ibucket;
for (BucketNode *n = bucket->first; n != 0; n = n->next) {
if (n->v.key_raw == key) {
return &n->v;
return n;
}
}
return 0;
@@ -233,10 +233,10 @@ hash_table_search_raw(HashTable *ht, void *key)
internal B32
hash_table_search_path_u64(HashTable *ht, String8 key, U64 *value_out)
{
KeyValuePair *result = hash_table_search_path(ht, key);
BucketNode *result = hash_table_search_path(ht, key);
if (result != 0) {
if (value_out != 0) {
*value_out = result->value_u64;
*value_out = result->v.value_u64;
}
return 1;
}
@@ -260,10 +260,10 @@ hash_table_push_raw_raw(Arena *arena, HashTable *ht, void *key, void *value)
internal B32
hash_table_search_string_u64(HashTable *ht, String8 key, U64 *value_out)
{
KeyValuePair *result = hash_table_search_string(ht, key);
BucketNode *result = hash_table_search_string(ht, key);
if (result != 0) {
if (value_out != 0) {
*value_out = result->value_u64;
*value_out = result->v.value_u64;
}
return 1;
}
@@ -273,10 +273,10 @@ hash_table_search_string_u64(HashTable *ht, String8 key, U64 *value_out)
internal B32
hash_table_search_string_string(HashTable *ht, String8 key, String8 *value_out)
{
KeyValuePair *result = hash_table_search_string(ht, key);
BucketNode *result = hash_table_search_string(ht, key);
if (result) {
if (value_out) {
*value_out = result->value_string;
*value_out = result->v.value_string;
}
return 1;
}
@@ -286,10 +286,10 @@ hash_table_search_string_string(HashTable *ht, String8 key, String8 *value_out)
internal B32
hash_table_search_u32_u32(HashTable *ht, U32 key, U32 *value_out)
{
KeyValuePair *result = hash_table_search_u32(ht, key);
BucketNode *result = hash_table_search_u32(ht, key);
if (result) {
if (value_out) {
*value_out = result->value_u32;
*value_out = result->v.value_u32;
}
return 1;
}
@@ -299,9 +299,9 @@ hash_table_search_u32_u32(HashTable *ht, U32 key, U32 *value_out)
internal void *
hash_table_search_string_raw(HashTable *ht, String8 key)
{
KeyValuePair *result = hash_table_search_string(ht, key);
BucketNode *result = hash_table_search_string(ht, key);
if (result) {
return result->value_raw;
return result->v.value_raw;
}
return 0;
}
@@ -309,22 +309,54 @@ hash_table_search_string_raw(HashTable *ht, String8 key)
internal void *
hash_table_search_u64_raw(HashTable *ht, U64 key_u64)
{
KeyValuePair *kv = hash_table_search_u64(ht, key_u64);
return kv ? kv->value_raw : 0;
BucketNode *n = hash_table_search_u64(ht, key_u64);
return n ? n->v.value_raw : 0;
}
internal void *
hash_table_search_path_raw(HashTable *ht, String8 path)
{
KeyValuePair *kv = hash_table_search_path(ht, path);
return kv ? kv->value_raw : 0;
BucketNode *n = hash_table_search_path(ht, path);
return n ? n->v.value_raw : 0;
}
internal void *
hash_table_search_raw_raw(HashTable *ht, void *key)
{
KeyValuePair *kv = hash_table_search_raw(ht, key);
return kv ? kv->value_raw : 0;
BucketNode *n = hash_table_search_raw(ht, key);
return n ? n->v.value_raw : 0;
}
internal void
hash_table_purge_item(HashTable *ht, U64 hash, BucketNode *node)
{
U64 bucket_idx = hash % ht->cap;
DLLRemove(ht->buckets[bucket_idx].first, ht->buckets[bucket_idx].last, node);
ht->count -= 1;
}
internal B32
hash_table_purge_u64(HashTable *ht, U64 key)
{
U64 hash = hash_table_hasher(str8_struct(&key));
BucketNode *n = hash_table_search_u64(ht, key);
if (n) {
hash_table_purge_item(ht, hash, n);
return 1;
}
return 0;
}
internal B32
hash_table_purge_string(HashTable *ht, String8 key)
{
U64 hash = hash_table_hasher(key);
BucketNode *n = hash_table_search_string(ht, key);
if (n) {
hash_table_purge_item(ht, hash, n);
return 1;
}
return 0;
}
internal int
@@ -451,7 +483,7 @@ remove_duplicates_u64_array(Arena *arena, U64Array arr)
HashTable *ht = hash_table_init(scratch.arena, ((U64)(F64)arr.count * 0.5));
for (U64 i = 0; i < arr.count; ++i) {
KeyValuePair *is_present = hash_table_search_u64(ht, arr.v[i]);
BucketNode *is_present = hash_table_search_u64(ht, arr.v[i]);
if (!is_present) {
hash_table_push_u64_raw(scratch.arena, ht, arr.v[i], 0);
}
@@ -474,7 +506,7 @@ remove_duplicates_str8_list(Arena *arena, String8List list)
HashTable *ht = hash_table_init(scratch.arena, list.node_count);
for (String8Node *node = list.first; node != 0; node = node->next) {
KeyValuePair *is_present = hash_table_search_string(ht, node->string);
BucketNode *is_present = hash_table_search_string(ht, node->string);
if (!is_present) {
hash_table_push_string_raw(scratch.arena, ht, node->string, 0);
str8_list_push(arena, &result, node->string);
+11 -6
View File
@@ -21,8 +21,9 @@ typedef struct KeyValuePair
typedef struct BucketNode
{
struct BucketNode *next;
KeyValuePair v;
struct BucketNode *next;
struct BucketNode *prev;
} BucketNode;
typedef struct BucketList
@@ -64,11 +65,11 @@ internal BucketNode * hash_table_push_path_u64 (Arena *arena, HashTable *ht,
internal BucketNode * hash_table_push_u64_u64 (Arena *arena, HashTable *ht, U64 key, U64 value);
internal BucketNode * hash_table_push_u32_u32 (Arena *arena, HashTable *ht, U32 key, U32 value);
internal KeyValuePair * hash_table_search_string (HashTable *ht, String8 key);
internal KeyValuePair * hash_table_search_u32 (HashTable *ht, U32 key);
internal KeyValuePair * hash_table_search_u64 (HashTable *ht, U64 key);
internal KeyValuePair * hash_table_search_path (HashTable *ht, String8 key);
internal KeyValuePair * hash_table_search_raw (HashTable *ht, void *key);
internal BucketNode * hash_table_search_string (HashTable *ht, String8 key);
internal BucketNode * hash_table_search_u32 (HashTable *ht, U32 key);
internal BucketNode * hash_table_search_u64 (HashTable *ht, U64 key);
internal BucketNode * hash_table_search_path (HashTable *ht, String8 key);
internal BucketNode * hash_table_search_raw (HashTable *ht, void *key);
internal B32 hash_table_search_path_u64 (HashTable *ht, String8 key, U64 *value_out);
internal B32 hash_table_search_string_u64 (HashTable *ht, String8 key, U64 *value_out);
@@ -80,6 +81,10 @@ internal void * hash_table_search_u64_raw (HashTable *ht, U64 key);
internal void * hash_table_search_path_raw (HashTable *ht, String8 key);
internal void * hash_table_search_raw_raw (HashTable *ht, void *key);
internal void hash_table_purge_item (HashTable *ht, U64 hash, BucketNode *node);
internal B32 hash_table_purge_u64 (HashTable *ht, U64 key);
internal B32 hash_table_purge_string(HashTable *ht, String8 key);
// --- Key Value Helpers -------------------------------------------------------
internal U32 * keys_from_hash_table_u32 (Arena *arena, HashTable *ht);
+1 -1
View File
@@ -1086,7 +1086,7 @@ lnk_inputer_push_lib_thin(LNK_Inputer *inputer, LNK_Config *config, LNK_InputSou
// warn about missing library
if (first_match.size == 0) {
KeyValuePair *was_reported = hash_table_search_path(inputer->missing_lib_ht, path);
BucketNode *was_reported = hash_table_search_path(inputer->missing_lib_ht, path);
if (was_reported == 0) {
hash_table_push_path_u64(inputer->arena, inputer->missing_lib_ht, path, 0);
lnk_error(LNK_Warning_FileNotFound, "unable to find library `%S`", path);
+6 -6
View File
@@ -1073,9 +1073,9 @@ lnk_expand_env_vars_windows(Arena *arena, HashTable *env_vars, String8 string)
if (open < close) {
String8 env_var_name = str8_substr(string, rng_1u64(open+1, close));
KeyValuePair *match = hash_table_search_path(env_vars, env_var_name);
BucketNode *match = hash_table_search_path(env_vars, env_var_name);
if (match) {
str8_list_push(scratch.arena, &list, match->value_string);
str8_list_push(scratch.arena, &list, match->v.value_string);
i = close+1;
} else {
str8_list_pushf(scratch.arena, &list, "%%%S", env_var_name);
@@ -2277,16 +2277,16 @@ lnk_config_from_cmd_line(String8List raw_cmd_line, LNK_CmdLine cmd_line)
// collect LIB and LIBPATH
if (config->flags & LNK_ConfigFlag_EnvLib) {
KeyValuePair *lib = hash_table_search_path(env_vars, str8_lit("lib"));
BucketNode *lib = hash_table_search_path(env_vars, str8_lit("lib"));
if (lib) {
String8List val_list = str8_split_by_string_chars(scratch.arena, lib->value_string, str8_lit(";"), 0);
String8List val_list = str8_split_by_string_chars(scratch.arena, lib->v.value_string, str8_lit(";"), 0);
String8List val_list_copy = str8_list_copy(arena, &val_list);
str8_list_concat_in_place(&config->lib_dir_list, &val_list_copy);
}
KeyValuePair *lib_path = hash_table_search_path(env_vars, str8_lit("libpath"));
BucketNode *lib_path = hash_table_search_path(env_vars, str8_lit("libpath"));
if (lib_path) {
String8List val_list = str8_split_by_string_chars(scratch.arena, lib->value_string, str8_lit(";"), 0);
String8List val_list = str8_split_by_string_chars(scratch.arena, lib->v.value_string, str8_lit(";"), 0);
String8List val_list_copy = str8_list_copy(arena, &val_list);
str8_list_concat_in_place(&config->lib_dir_list, &val_list_copy);
}
+6 -7
View File
@@ -587,9 +587,9 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_IO_Flags io_fla
};
// was this type server queued?
KeyValuePair *is_path_queued = hash_table_search_path(type_server_path_ht, type_server_path);
BucketNode *is_path_queued = hash_table_search_path(type_server_path_ht, type_server_path);
if (is_path_queued) {
struct HT_Value *present = is_path_queued->value_raw;
struct HT_Value *present = is_path_queued->v.value_raw;
// make sure type servers sigs match
if (MemoryMatchStruct(&ts.sig, &present->ts.sig)) {
@@ -4705,9 +4705,9 @@ THREAD_POOL_TASK_FUNC(lnk_convert_symbols_to_rdi_task)
// get link name through virtual offset look up
String8 link_name = {0};
if (symbol.kind == CV_SymKind_GDATA32) {
KeyValuePair *pair = hash_table_search_u64(task->extern_symbol_voff_ht, data_voff);
BucketNode *pair = hash_table_search_u64(task->extern_symbol_voff_ht, data_voff);
if (pair != 0) {
LNK_Symbol *link_symbol = pair->value_raw;
LNK_Symbol *link_symbol = pair->v.value_raw;
link_name = link_symbol->name;
}
}
@@ -4801,9 +4801,8 @@ THREAD_POOL_TASK_FUNC(lnk_convert_symbols_to_rdi_task)
// get link name through virtual offset look up
String8 link_name = str8(0,0);
if (symbol.kind == CV_SymKind_GPROC32) {
KeyValuePair *pair = hash_table_search_u64(task->extern_symbol_voff_ht, virt_range.min);
if (pair != 0) {
LNK_Symbol *link_symbol = pair->value_raw;
LNK_Symbol *link_symbol = hash_table_search_u64_raw(task->extern_symbol_voff_ht, virt_range.min);
if (link_symbol) {
link_name = link_symbol->name;
}
}
+1 -3
View File
@@ -161,9 +161,7 @@ lnk_section_table_purge(LNK_SectionTable *sectab, String8 name)
LNK_SectionNode *node = lnk_section_table_remove(sectab, name);
String8 name_with_flags = lnk_make_name_with_flags(scratch.arena, name, node->data.flags);
KeyValuePair *kv = hash_table_search_string(sectab->sect_ht, name_with_flags);
kv->key_string = str8_zero();
kv->value_raw = 0;
hash_table_purge_string(sectab->sect_ht, name_with_flags);
scratch_end(scratch);
}