From 58b5b3d92d57d8b025ad7192fc415603a5a68dff Mon Sep 17 00:00:00 2001 From: Nikita Smith Date: Tue, 14 Jul 2026 13:37:40 -0700 Subject: [PATCH] search chunks only grow while resolving libraries, so revisit only symbols appended since this library's last search --- src/linker/lnk.c | 48 +++++++++++++++++++++++++++++++++----------- src/linker/lnk.h | 2 +- src/linker/lnk_lib.h | 4 ++++ 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/linker/lnk.c b/src/linker/lnk.c index 5e69365c..77accc35 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -1647,13 +1647,20 @@ THREAD_POOL_TASK_FUNC(lnk_search_lib_task) LNK_LibMemberInfo *lib_member_infos = task->lib_member_infos; LNK_LibMemberRefList *member_ref_list = &task->member_ref_lists[task_id]; - for EachNode(c, LNK_SymbolHashTrieChunk, symtab->search_chunks[task_id].first) { - for EachIndex(i, c->count) { - LNK_Symbol *symbol = c->v[i].symbol; + LNK_SymbolHashTrieChunk *start_chunk = task->reset_search_cursor ? 0 : lib->search_cursor_chunks[task_id]; + U64 start_idx = task->reset_search_cursor ? 0 : lib->search_cursor_indices[task_id]; + LNK_SymbolHashTrieChunk *end_chunk = symtab->search_chunks[task_id].last; + U64 end_count = end_chunk ? end_chunk->count : 0; + for EachNode(c, LNK_SymbolHashTrieChunk, start_chunk ? start_chunk : symtab->search_chunks[task_id].first) { + U64 i_begin = (c == start_chunk) ? start_idx : 0; + U64 i_end = (c == end_chunk) ? end_count : c->count; + for (U64 i = i_begin; i < i_end; i += 1) { + LNK_Symbol *symbol = c->v[i].symbol; LNK_ObjSymbolRef symbol_ref = lnk_ref_from_symbol(symbol); COFF_ParsedSymbol symbol_parsed = lnk_parsed_from_symbol(symbol); COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol_parsed); + if (symbol_interp == COFF_SymbolValueInterp_Undefined) { U32 member_idx; if (lnk_search_lib(lib, symbol->name, &member_idx)) { @@ -1684,6 +1691,10 @@ THREAD_POOL_TASK_FUNC(lnk_search_lib_task) } } } + + // cache search cursors + lib->search_cursor_chunks[task_id] = end_chunk; + lib->search_cursor_indices[task_id] = end_count; } internal LNK_Lib * @@ -1819,19 +1830,32 @@ lnk_link_inputs(TP_Context *tp, for EachIndex(member_idx, lib->member_count) { lnk_queue_lib_member(arena->v[0], &imports_hm, link->lib_member_infos_hm, &member_ref_lists[0], null_symbol, lib, lib_member_infos, member_idx); } - } else { - // search symbols in lib + } else { // search symbols in lib MemoryZeroTyped(member_ref_lists, tp->worker_count); + + // anti-dep mode changes which weak symbols can resolve from this lib + B32 reset_search_cursor = lib->search_cursor_chunks != 0 && lib->searched_anti_deps != search_anti_deps; + + // lazy alloc cursors for tracking searched symbols + if (lib->search_cursor_chunks == 0) { + lib->search_cursor_chunks = push_array(link->arena, LNK_SymbolHashTrieChunk *, tp->worker_count); + lib->search_cursor_indices = push_array(link->arena, U64, tp->worker_count); + } + LNK_SearchLibTask search_task = { - .search_anti_deps = search_anti_deps, - .link = link, - .imports_hm = &imports_hm, - .lib = lib, - .symtab = symtab, - .lib_member_infos = lib_member_infos, - .member_ref_lists = member_ref_lists + .search_anti_deps = search_anti_deps, + .reset_search_cursor = reset_search_cursor, + .link = link, + .imports_hm = &imports_hm, + .lib = lib, + .symtab = symtab, + .lib_member_infos = lib_member_infos, + .member_ref_lists = member_ref_lists }; tp_for_parallel(tp, arena, tp->worker_count, lnk_search_lib_task, &search_task); + + // cache last search mode, if the mode changes then skipped weak anti-dependency must be searched again + lib->searched_anti_deps = search_anti_deps; } LNK_LibMemberRefList queued_members = {0}; diff --git a/src/linker/lnk.h b/src/linker/lnk.h index 86485831..e4a80205 100644 --- a/src/linker/lnk.h +++ b/src/linker/lnk.h @@ -205,6 +205,7 @@ typedef struct LNK_BaseRelocPageArray typedef struct { B32 search_anti_deps; + B32 reset_search_cursor; LNK_Link *link; HashMap *imports_hm; LNK_SymbolTable *symtab; @@ -410,4 +411,3 @@ internal LNK_ImageContext lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_C internal void lnk_log_link_stats(LNK_ObjList obj_list, LNK_LibList *lib_index, LNK_SectionTable *sectab); internal void lnk_log_timers(void); - diff --git a/src/linker/lnk_lib.h b/src/linker/lnk_lib.h index eed5e2de..6db16e29 100644 --- a/src/linker/lnk_lib.h +++ b/src/linker/lnk_lib.h @@ -15,6 +15,10 @@ typedef struct LNK_Lib String8Array symbol_names; String8 long_names; U64 input_idx; + + struct LNK_SymbolHashTrieChunk **search_cursor_chunks; + U64 *search_cursor_indices; + B32 searched_anti_deps; } LNK_Lib; typedef struct LNK_LibNode