diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 2bc669a6..4108349c 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -58,7 +58,7 @@ ctrl_init(CTRL_WakeupFunctionType *wakeup_hook) ctrl_state->u2ms_ring_mutex = os_mutex_alloc(); ctrl_state->u2ms_ring_cv = os_condition_variable_alloc(); ctrl_state->ctrl_thread = os_launch_thread(ctrl_thread__entry_point, 0, 0); - ctrl_state->ms_thread_count = Min(4, os_logical_core_count()-1); + ctrl_state->ms_thread_count = Clamp(1, os_logical_core_count()-1, 4); ctrl_state->ms_threads = push_array(arena, OS_Handle, ctrl_state->ms_thread_count); for(U64 idx = 0; idx < ctrl_state->ms_thread_count; idx += 1) { diff --git a/src/dbgi/dbgi.c b/src/dbgi/dbgi.c index 57d36643..19dc2a46 100644 --- a/src/dbgi/dbgi.c +++ b/src/dbgi/dbgi.c @@ -30,6 +30,16 @@ dbgi_init(void) dbgi_shared->binary_stripes[idx].rw_mutex = os_rw_mutex_alloc(); dbgi_shared->binary_stripes[idx].cv = os_condition_variable_alloc(); } + dbgi_shared->fuzzy_search_slots_count = 64; + dbgi_shared->fuzzy_search_stripes_count = 8; + dbgi_shared->fuzzy_search_slots = push_array(arena, DBGI_FuzzySearchSlot, dbgi_shared->fuzzy_search_slots_count); + dbgi_shared->fuzzy_search_stripes = push_array(arena, DBGI_FuzzySearchStripe, dbgi_shared->fuzzy_search_stripes_count); + for(U64 idx = 0; idx < dbgi_shared->fuzzy_search_stripes_count; idx += 1) + { + dbgi_shared->fuzzy_search_stripes[idx].arena = arena_alloc(); + dbgi_shared->fuzzy_search_stripes[idx].rw_mutex = os_rw_mutex_alloc(); + dbgi_shared->fuzzy_search_stripes[idx].cv = os_condition_variable_alloc(); + } dbgi_shared->u2p_ring_mutex = os_mutex_alloc(); dbgi_shared->u2p_ring_cv = os_condition_variable_alloc(); dbgi_shared->u2p_ring_size = KB(64); @@ -44,6 +54,17 @@ dbgi_init(void) { dbgi_shared->parse_threads[idx] = os_launch_thread(dbgi_parse_thread_entry_point, (void *)idx, 0); } + dbgi_shared->fuzzy_thread_count = Clamp(1, os_logical_core_count()-1, 4); + dbgi_shared->fuzzy_threads = push_array(arena, DBGI_FuzzySearchThread, dbgi_shared->fuzzy_thread_count); + for(U64 idx = 0; idx < dbgi_shared->fuzzy_thread_count; idx += 1) + { + DBGI_FuzzySearchThread *thread = &dbgi_shared->fuzzy_threads[idx]; + thread->u2f_ring_mutex = os_mutex_alloc(); + thread->u2f_ring_cv = os_condition_variable_alloc(); + thread->u2f_ring_size = KB(64); + thread->u2f_ring_base = push_array_no_zero(dbgi_shared->arena, U8, thread->u2f_ring_size); + thread->thread = os_launch_thread(dbgi_fuzzy_thread__entry_point, (void *)idx, 0); + } } //////////////////////////////// @@ -169,6 +190,12 @@ dbgi_scope_close(DBGI_Scope *scope) ins_atomic_u64_dec_eval(&tb->binary->scope_touch_count); SLLStackPush(dbgi_tctx->free_tb, tb); } + for(DBGI_TouchedFuzzySearch *tfs = scope->first_tfs, *next = 0; tfs != 0; tfs = next) + { + next = tfs->next; + ins_atomic_u64_dec_eval(&tfs->node->scope_touch_count); + SLLStackPush(dbgi_tctx->free_tfs, tfs); + } SLLStackPush(dbgi_tctx->free_scope, scope); } @@ -192,7 +219,18 @@ dbgi_scope_touch_binary__stripe_mutex_r_guarded(DBGI_Scope *scope, DBGI_Binary * internal void dbgi_scope_touch_fuzzy_search__stripe_mutex_r_guarded(DBGI_Scope *scope, DBGI_FuzzySearchNode *node) { - + DBGI_TouchedFuzzySearch *tfs = dbgi_tctx->free_tfs; + ins_atomic_u64_inc_eval(&node->scope_touch_count); + if(tfs != 0) + { + SLLStackPop(dbgi_tctx->free_tfs); + } + else + { + tfs = push_array(dbgi_tctx->arena, DBGI_TouchedFuzzySearch, 1); + } + tfs->node = node; + SLLQueuePush(scope->first_tfs, scope->last_tfs, tfs); } //////////////////////////////// @@ -297,6 +335,7 @@ dbgi_parse_from_exe_path(DBGI_Scope *scope, String8 exe_path, U64 endt_us) Temp scratch = scratch_begin(0, 0); exe_path = path_normalized_from_string(scratch.arena, exe_path); DBGI_Parse *parse = &dbgi_parse_nil; + if(exe_path.size != 0) { U64 hash = dbgi_hash_from_string(exe_path); U64 slot_idx = hash%dbgi_shared->binary_slots_count; @@ -346,17 +385,22 @@ dbgi_parse_from_exe_path(DBGI_Scope *scope, String8 exe_path, U64 endt_us) //~ rjf: Fuzzy Search Cache Functions internal DBGI_FuzzySearchItemArray -dbgi_fuzzy_search_items_from_key_exe_query(DBGI_Scope *scope, U128 key, String8 exe_path, String8 query, U64 endt_us) +dbgi_fuzzy_search_items_from_key_exe_query(DBGI_Scope *scope, U128 key, String8 exe_path, String8 query, U64 endt_us, B32 *stale_out) { + Temp scratch = scratch_begin(0, 0); DBGI_FuzzySearchItemArray items = {0}; -#if 0 + exe_path = path_normalized_from_string(scratch.arena, exe_path); { + //- rjf: unpack key U64 slot_idx = key.u64[1]%dbgi_shared->fuzzy_search_slots_count; U64 stripe_idx = slot_idx%dbgi_shared->fuzzy_search_stripes_count; DBGI_FuzzySearchSlot *slot = &dbgi_shared->fuzzy_search_slots[slot_idx]; DBGI_FuzzySearchStripe *stripe = &dbgi_shared->fuzzy_search_stripes[stripe_idx]; + + //- rjf: query and/or request OS_MutexScopeR(stripe->rw_mutex) for(;;) { + // rjf: map key -> node DBGI_FuzzySearchNode *node = 0; for(DBGI_FuzzySearchNode *n = slot->first; n != 0; n = n->next) { @@ -366,34 +410,56 @@ dbgi_fuzzy_search_items_from_key_exe_query(DBGI_Scope *scope, U128 key, String8 break; } } + + // rjf: no node? -> allocate if(node == 0) OS_MutexScopeRWPromote(stripe->rw_mutex) { node = push_array(stripe->arena, DBGI_FuzzySearchNode, 1); - DLLPushBack(slot->first, slot->last, node); + SLLQueuePush(slot->first, slot->last, node); node->key = key; - } - B32 stale = 1; - if(node->gen > 0) - { - U64 v_idx = (node->gen-1)%ArrayCount(node->v); - if(str8_match(exe_path, node->v[v_idx].exe_path, 0)) + for(U64 idx = 0; idx < ArrayCount(node->buckets); idx += 1) { - items = node->v[v_idx].items; - stale = str8_match(query, node->v[v_idx].query, 0); + node->buckets[idx].arena = arena_alloc(); } } - if(stale && node->submitted != 0) OS_MutexScopeRWPromote(stripe->rw_mutex) + + // rjf: try to grab last valid results for this key/query; determine if stale + B32 stale = 1; + if(str8_match(exe_path, node->buckets[node->gen%ArrayCount(node->buckets)].exe_path, 0) && node->gen != 0) { - node->submitted = (U64)!!dbgi_u2f_enqueue_req(key, exe_path, query, endt_us); + dbgi_scope_touch_fuzzy_search__stripe_mutex_r_guarded(scope, node); + items = node->gen_items; + stale = !str8_match(query, node->buckets[node->gen%ArrayCount(node->buckets)].query, 0); + *stale_out = stale; } + + // rjf: if stale -> request again + if(stale) OS_MutexScopeRWPromote(stripe->rw_mutex) + { + if(node->submit_gen == node->gen) + { + node->submit_gen += 1; + arena_clear(node->buckets[node->submit_gen%ArrayCount(node->buckets)].arena); + node->buckets[node->submit_gen%ArrayCount(node->buckets)].exe_path = push_str8_copy(node->buckets[node->submit_gen%ArrayCount(node->buckets)].arena, exe_path); + node->buckets[node->submit_gen%ArrayCount(node->buckets)].query = push_str8_copy(node->buckets[node->submit_gen%ArrayCount(node->buckets)].arena, query); + } + if(os_now_microseconds() >= node->last_time_submitted_us+100000 && dbgi_u2f_enqueue_req(key, endt_us)) + { + node->last_time_submitted_us = os_now_microseconds(); + } + } + + // rjf: not stale, or timeout -> break if(!stale || os_now_microseconds() >= endt_us) { break; } + + // rjf: no results, but have time to wait -> wait os_condition_variable_wait_rw_r(stripe->cv, stripe->rw_mutex, endt_us); } } -#endif + scratch_end(scratch); return items; } @@ -963,19 +1029,154 @@ dbgi_parse_thread_entry_point(void *p) //~ rjf: Fuzzy Searching Threads internal B32 -dbgi_u2f_enqueue_req(U128 key, String8 exe_path, String8 query, U64 endt_us) +dbgi_u2f_enqueue_req(U128 key, U64 endt_us) { - return 0; + B32 sent = 0; + DBGI_FuzzySearchThread *thread = &dbgi_shared->fuzzy_threads[key.u64[1]%dbgi_shared->fuzzy_thread_count]; + OS_MutexScope(thread->u2f_ring_mutex) for(;;) + { + U64 unconsumed_size = thread->u2f_ring_write_pos - thread->u2f_ring_read_pos; + U64 available_size = thread->u2f_ring_size - unconsumed_size; + if(available_size >= sizeof(U128)) + { + sent = 1; + thread->u2f_ring_write_pos += ring_write_struct(thread->u2f_ring_base, thread->u2f_ring_size, thread->u2f_ring_write_pos, &key); + break; + } + os_condition_variable_wait(thread->u2f_ring_cv, thread->u2f_ring_mutex, endt_us); + } + if(sent) + { + os_condition_variable_broadcast(thread->u2f_ring_cv); + } + return sent; } internal void -dbgi_u2f_dequeue_req(Arena *arena, U128 *key_out, String8 *exe_path_out, String8 *query_out) +dbgi_u2f_dequeue_req(Arena *arena, DBGI_FuzzySearchThread *thread, U128 *key_out) { - + OS_MutexScope(thread->u2f_ring_mutex) for(;;) + { + U64 unconsumed_size = thread->u2f_ring_write_pos - thread->u2f_ring_read_pos; + if(unconsumed_size >= sizeof(U128)) + { + thread->u2f_ring_read_pos += ring_read_struct(thread->u2f_ring_base, thread->u2f_ring_size, thread->u2f_ring_read_pos, key_out); + break; + } + os_condition_variable_wait(thread->u2f_ring_cv, thread->u2f_ring_mutex, max_U64); + } + os_condition_variable_broadcast(thread->u2f_ring_cv); } internal void dbgi_fuzzy_thread__entry_point(void *p) { - + TCTX tctx_; + tctx_init_and_equip(&tctx_); + ProfThreadName("[dbgi] fuzzy search #%I64U", (U64)p); + DBGI_FuzzySearchThread *thread = &dbgi_shared->fuzzy_threads[(U64)p]; + for(;;) + { + Temp scratch = scratch_begin(0, 0); + DBGI_Scope *scope = dbgi_scope_open(); + + //- rjf: dequeue next request + U128 key = {0}; + dbgi_u2f_dequeue_req(scratch.arena, thread, &key); + U64 slot_idx = key.u64[1]%dbgi_shared->fuzzy_search_slots_count; + U64 stripe_idx = slot_idx%dbgi_shared->fuzzy_search_stripes_count; + DBGI_FuzzySearchSlot *slot = &dbgi_shared->fuzzy_search_slots[slot_idx]; + DBGI_FuzzySearchStripe *stripe = &dbgi_shared->fuzzy_search_stripes[stripe_idx]; + + //- rjf: grab next exe_path/query for this key + B32 task_is_good = 0; + Arena *task_arena = 0; + String8 exe_path = {0}; + String8 query = {0}; + OS_MutexScopeW(stripe->rw_mutex) + { + for(DBGI_FuzzySearchNode *n = slot->first; n != 0; n = n->next) + { + if(u128_match(n->key, key)) + { + task_is_good = 1; + task_arena = n->buckets[n->submit_gen%ArrayCount(n->buckets)].arena; + exe_path = n->buckets[n->submit_gen%ArrayCount(n->buckets)].exe_path; + query = n->buckets[n->submit_gen%ArrayCount(n->buckets)].query; + break; + } + } + } + + //- rjf: form space-separated search needles + U8 splits[] = {' '}; + String8List query_needles = str8_split(scratch.arena, query, splits, ArrayCount(splits), 0); + + //- rjf: exe_path -> dbgi_parse, raddbg + DBGI_Parse *dbgi = dbgi_parse_from_exe_path(scope, exe_path, max_U64); + RADDBG_Parsed *rdbg = &dbgi->rdbg; + + //- rjf: rdbg * query -> item list + DBGI_FuzzySearchItemChunkList items_list = {0}; + if(task_is_good) + { + for(U64 procedure_idx = 0; procedure_idx < rdbg->procedure_count; procedure_idx += 1) + { + RADDBG_Procedure *procedure = &rdbg->procedures[procedure_idx]; + U64 name_size = 0; + U8 *name_base = raddbg_string_from_idx(rdbg, procedure->name_string_idx, &name_size); + String8 name = str8(name_base, name_size); + if(name.size == 0) { continue; } + FuzzyMatchRangeList matches = fuzzy_match_find(task_arena, query_needles, name); + if(matches.count == query_needles.node_count) + { + DBGI_FuzzySearchItemChunk *chunk = items_list.last; + if(chunk == 0 || chunk->count >= chunk->cap) + { + chunk = push_array(scratch.arena, DBGI_FuzzySearchItemChunk, 1); + chunk->cap = 512; + chunk->count = 0; + chunk->v = push_array_no_zero(scratch.arena, DBGI_FuzzySearchItem, chunk->cap); + SLLQueuePush(items_list.first, items_list.last, chunk); + items_list.chunk_count += 1; + } + chunk->v[chunk->count].procedure_idx = procedure_idx; + chunk->v[chunk->count].match_ranges = matches; + chunk->count += 1; + items_list.total_count += 1; + } + } + } + + //- rjf: item list -> item array + DBGI_FuzzySearchItemArray items = {0}; + if(task_is_good) + { + items.count = items_list.total_count; + items.v = push_array_no_zero(task_arena, DBGI_FuzzySearchItem, items.count); + U64 idx = 0; + for(DBGI_FuzzySearchItemChunk *chunk = items_list.first; chunk != 0; chunk = chunk->next) + { + MemoryCopy(items.v+idx, chunk->v, sizeof(DBGI_FuzzySearchItemChunk)*chunk->count); + idx += chunk->count; + } + } + + //- rjf: commit to cache + if(task_is_good) OS_MutexScopeW(stripe->rw_mutex) + { + for(DBGI_FuzzySearchNode *n = slot->first; n != 0; n = n->next) + { + if(u128_match(n->key, key)) + { + n->gen += 1; + n->gen_items = items; + break; + } + } + } + + dbgi_scope_close(scope); + scratch_end(scratch); + } } diff --git a/src/dbgi/dbgi.h b/src/dbgi/dbgi.h index 272cab46..7921fd11 100644 --- a/src/dbgi/dbgi.h +++ b/src/dbgi/dbgi.h @@ -103,13 +103,14 @@ struct DBGI_BinaryStripe typedef struct DBGI_FuzzySearchItem DBGI_FuzzySearchItem; struct DBGI_FuzzySearchItem { - U64 function_idx; + U64 procedure_idx; FuzzyMatchRangeList match_ranges; }; typedef struct DBGI_FuzzySearchItemChunk DBGI_FuzzySearchItemChunk; struct DBGI_FuzzySearchItemChunk { + DBGI_FuzzySearchItemChunk *next; DBGI_FuzzySearchItem *v; U64 count; U64 cap; @@ -131,25 +132,25 @@ struct DBGI_FuzzySearchItemArray U64 count; }; -typedef struct DBGI_FuzzySearchResult DBGI_FuzzySearchResult; -struct DBGI_FuzzySearchResult +typedef struct DBGI_FuzzySearchBucket DBGI_FuzzySearchBucket; +struct DBGI_FuzzySearchBucket { Arena *arena; String8 exe_path; String8 query; - DBGI_FuzzySearchItemArray items; }; typedef struct DBGI_FuzzySearchNode DBGI_FuzzySearchNode; struct DBGI_FuzzySearchNode { DBGI_FuzzySearchNode *next; - DBGI_FuzzySearchNode *prev; U128 key; - U64 submitted; U64 scope_touch_count; + U64 last_time_submitted_us; + DBGI_FuzzySearchBucket buckets[2]; U64 gen; - DBGI_FuzzySearchResult v[2]; + U64 submit_gen; + DBGI_FuzzySearchItemArray gen_items; }; typedef struct DBGI_FuzzySearchSlot DBGI_FuzzySearchSlot; @@ -167,6 +168,18 @@ struct DBGI_FuzzySearchStripe OS_Handle cv; }; +typedef struct DBGI_FuzzySearchThread DBGI_FuzzySearchThread; +struct DBGI_FuzzySearchThread +{ + OS_Handle thread; + OS_Handle u2f_ring_mutex; + OS_Handle u2f_ring_cv; + U64 u2f_ring_size; + U8 *u2f_ring_base; + U64 u2f_ring_write_pos; + U64 u2f_ring_read_pos; +}; + //////////////////////////////// //~ rjf: Weak Access Scope Types @@ -273,14 +286,6 @@ struct DBGI_Shared U64 u2p_ring_write_pos; U64 u2p_ring_read_pos; - // rjf: user -> fuzzy ring - OS_Handle u2f_ring_mutex; - OS_Handle u2f_ring_cv; - U64 u2f_ring_size; - U8 *u2f_ring_base; - U64 u2f_ring_write_pos; - U64 u2f_ring_read_pos; - // rjf: parse -> user event ring OS_Handle p2u_ring_mutex; OS_Handle p2u_ring_cv; @@ -293,7 +298,7 @@ struct DBGI_Shared U64 parse_thread_count; OS_Handle *parse_threads; U64 fuzzy_thread_count; - OS_Handle *fuzzy_threads; + DBGI_FuzzySearchThread *fuzzy_threads; }; //////////////////////////////// @@ -342,7 +347,7 @@ internal DBGI_Parse *dbgi_parse_from_exe_path(DBGI_Scope *scope, String8 exe_pat //////////////////////////////// //~ rjf: Fuzzy Search Cache Functions -internal DBGI_FuzzySearchItemArray dbgi_fuzzy_search_items_from_key_exe_query(DBGI_Scope *scope, U128 key, String8 exe_path, String8 query, U64 endt_us); +internal DBGI_FuzzySearchItemArray dbgi_fuzzy_search_items_from_key_exe_query(DBGI_Scope *scope, U128 key, String8 exe_path, String8 query, U64 endt_us, B32 *stale_out); //////////////////////////////// //~ rjf: Parse Threads @@ -358,8 +363,8 @@ internal void dbgi_parse_thread_entry_point(void *p); //////////////////////////////// //~ rjf: Fuzzy Searching Threads -internal B32 dbgi_u2f_enqueue_req(U128 key, String8 exe_path, String8 query, U64 endt_us); -internal void dbgi_u2f_dequeue_req(Arena *arena, U128 *key_out, String8 *exe_path_out, String8 *query_out); +internal B32 dbgi_u2f_enqueue_req(U128 key, U64 endt_us); +internal void dbgi_u2f_dequeue_req(Arena *arena, DBGI_FuzzySearchThread *thread, U128 *key_out); internal void dbgi_fuzzy_thread__entry_point(void *p); diff --git a/src/df/gfx/df_gfx.c b/src/df/gfx/df_gfx.c index 41c422a0..e3a88283 100644 --- a/src/df/gfx/df_gfx.c +++ b/src/df/gfx/df_gfx.c @@ -10495,7 +10495,7 @@ df_fancy_string_list_from_code_string(Arena *arena, F32 alpha, B32 indirection_s return fancy_strings; } -internal void +internal UI_Box * df_code_label(F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String8 string) { Temp scratch = scratch_begin(0, 0); @@ -10503,6 +10503,7 @@ df_code_label(F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String UI_Box *box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); ui_box_equip_display_fancy_strings(box, &fancy_strings); scratch_end(scratch); + return box; } //////////////////////////////// diff --git a/src/df/gfx/df_gfx.h b/src/df/gfx/df_gfx.h index 4086fa7f..e4fd68f8 100644 --- a/src/df/gfx/df_gfx.h +++ b/src/df/gfx/df_gfx.h @@ -1046,7 +1046,7 @@ internal B32 df_do_dasm_controls(DASM_Handle handle, U64 line_count_per_page, Tx internal UI_Signal df_error_label(String8 string); internal B32 df_help_label(String8 string); internal D_FancyStringList df_fancy_string_list_from_code_string(Arena *arena, F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String8 string); -internal void df_code_label(F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String8 string); +internal UI_Box *df_code_label(F32 alpha, B32 indirection_size_change, Vec4F32 base_color, String8 string); //////////////////////////////// //~ rjf: UI Widgets: Line Edit diff --git a/src/df/gfx/df_gfx.mdesk b/src/df/gfx/df_gfx.mdesk index c9cc8433..dd0be3ae 100644 --- a/src/df/gfx/df_gfx.mdesk +++ b/src/df/gfx/df_gfx.mdesk @@ -52,10 +52,10 @@ DF_DefaultBindingTable: //- rjf: focused panel changing { "next_panel" Comma ctrl 0 0 } { "prev_panel" Comma ctrl shift 0 } - { "focus_panel_right" Right ctrl shift alt } - { "focus_panel_left" Left ctrl shift alt } - { "focus_panel_up" Up ctrl shift alt } - { "focus_panel_down" Down ctrl shift alt } + { "focus_panel_right" Right ctrl 0 alt } + { "focus_panel_left" Left ctrl 0 alt } + { "focus_panel_up" Up ctrl 0 alt } + { "focus_panel_down" Down ctrl 0 alt } //- rjf: undo/redo //{ "undo" Z ctrl 0 0 } @@ -76,8 +76,8 @@ DF_DefaultBindingTable: { "move_tab_right" PageDown ctrl shift 0 } { "move_tab_left" PageUp ctrl shift 0 } { "close_tab" W ctrl 0 0 } - { "tab_bar_top" Up ctrl 0 alt } - { "tab_bar_bottom" Down ctrl 0 alt } + { "tab_bar_top" Up ctrl shift alt } + { "tab_bar_bottom" Down ctrl shift alt } //- rjf: files { "open" O ctrl 0 0 } diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index 9e720359..cb94e2c9 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -2803,8 +2803,124 @@ DF_VIEW_CMD_FUNCTION_DEF(SymbolLister) DF_VIEW_UI_FUNCTION_DEF(SymbolLister) { + ProfBeginFunction(); + Temp scratch = scratch_begin(0, 0); + DBGI_Scope *scope = dbgi_scope_open(); + F32 row_height_px = floor_f32(ui_top_font_size()*2.5f); + DF_CtrlCtx ctrl_ctx = df_ctrl_ctx_from_view(ws, view); + DF_Entity *thread = df_entity_from_handle(ctrl_ctx.thread); + DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); + U64 thread_unwind_rip_vaddr = df_query_cached_rip_from_thread_unwind(thread, ctrl_ctx.unwind_count); + DF_Entity *module = df_module_from_process_vaddr(process, thread_unwind_rip_vaddr); + DF_Entity *binary = df_binary_file_from_module(module); + String8 exe_path = df_full_path_from_entity(scratch.arena, binary); String8 query = str8(view->query_buffer, view->query_string_size); + TG_Graph *graph = tg_graph_begin(bit_size_from_arch(df_architecture_from_entity(thread))/8, 256); + //- rjf: grab state + typedef struct DF_SymbolListerViewState DF_SymbolListerViewState; + struct DF_SymbolListerViewState + { + Vec2S64 cursor; + }; + DF_SymbolListerViewState *slv = df_view_user_state(view, DF_SymbolListerViewState); + + //- rjf: query -> raddbg, filtered items + U128 fuzzy_search_key = {(U64)view, df_hash_from_string(str8_struct(&view))}; + DBGI_Parse *dbgi = dbgi_parse_from_exe_path(scope, exe_path, os_now_microseconds()+100); + RADDBG_Parsed *rdbg = &dbgi->rdbg; + B32 items_stale = 0; + DBGI_FuzzySearchItemArray items = dbgi_fuzzy_search_items_from_key_exe_query(scope, fuzzy_search_key, exe_path, query, os_now_microseconds()+100, &items_stale); + if(items_stale) + { + df_gfx_request_frame(); + } + + //- rjf: submit best match when hitting enter w/ no selection + if(slv->cursor.y == 0 && items.count != 0 && os_key_press(ui_events(), ui_window(), 0, OS_Key_Return)) + { + U64 procedure_idx = items.v[0].procedure_idx; + if(0 < procedure_idx && procedure_idx < rdbg->procedure_count) + { + RADDBG_Procedure *procedure = &rdbg->procedures[procedure_idx]; + U64 name_size = 0; + U8 *name_base = raddbg_string_from_idx(rdbg, procedure->name_string_idx, &name_size); + String8 name = str8(name_base, name_size); + DF_CmdParams p = df_cmd_params_from_view(ws, panel, view); + p.string = name; + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_String); + df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_CompleteQuery)); + } + } + + //- rjf: build contents + Rng1S64 visible_row_range = {0}; + UI_ScrollListParams scroll_list_params = {0}; + { + Vec2F32 content_dim = dim_2f32(rect); + scroll_list_params.flags = UI_ScrollListFlag_All; + scroll_list_params.row_height_px = row_height_px; + scroll_list_params.dim_px = v2f32(content_dim.x, content_dim.y); + scroll_list_params.cursor_range = r2s64(v2s64(0, 0), v2s64(0, items.count)); + scroll_list_params.item_range = r1s64(0, items.count); + scroll_list_params.cursor_min_is_empty_selection[Axis2_Y] = 1; + } + UI_ScrollListSignal scroll_list_sig = {0}; + UI_Focus(UI_FocusKind_On) + UI_ScrollList(&scroll_list_params, &view->scroll_pos.y, &slv->cursor, &visible_row_range, &scroll_list_sig) + UI_Focus(UI_FocusKind_Null) + UI_Font(df_font_from_slot(DF_FontSlot_Code)) + { + //- rjf: build rows + for(U64 idx = visible_row_range.min; + idx <= visible_row_range.max && idx < items.count; + idx += 1) + UI_Focus((slv->cursor.y == idx+1) ? UI_FocusKind_On : UI_FocusKind_Off) + { + DBGI_FuzzySearchItem *item = &items.v[idx]; + if(item->procedure_idx >= rdbg->procedure_count) { continue; } + RADDBG_Procedure *procedure = &rdbg->procedures[item->procedure_idx]; + U64 name_size = 0; + U8 *name_base = raddbg_string_from_idx(rdbg, procedure->name_string_idx, &name_size); + String8 name = str8(name_base, name_size); + TG_Key type_key = tg_key_zero(); + if(procedure->type_idx < rdbg->type_node_count) + { + RADDBG_TypeNode *type_node = &rdbg->type_nodes[procedure->type_idx]; + type_key = tg_key_ext(tg_kind_from_raddbg_type_kind(type_node->kind), procedure->type_idx); + } + ui_set_next_hover_cursor(OS_Cursor_HandPoint); + UI_Box *box = ui_build_box_from_stringf(UI_BoxFlag_Clickable| + UI_BoxFlag_DrawBackground| + UI_BoxFlag_DrawBorder| + UI_BoxFlag_DrawText| + UI_BoxFlag_DrawHotEffects| + UI_BoxFlag_DrawActiveEffects, + "###procedure_%I64x", item->procedure_idx); + UI_Parent(box) UI_PrefWidth(ui_text_dim(10, 1)) + { + UI_Box *box = df_code_label(1.f, 0, df_rgba_from_theme_color(DF_ThemeColor_CodeFunction), name); + df_box_equip_fuzzy_match_range_list_vis(box, item->match_ranges); + if(!tg_key_match(tg_key_zero(), type_key)) + { + String8 type_string = tg_string_from_key(scratch.arena, graph, rdbg, type_key); + df_code_label(0.5f, 0, df_rgba_from_theme_color(DF_ThemeColor_WeakText), type_string); + } + } + UI_Signal sig = ui_signal_from_box(box); + if(sig.clicked) + { + DF_CmdParams p = df_cmd_params_from_view(ws, panel, view); + p.string = name; + df_cmd_params_mark_slot(&p, DF_CmdParamSlot_String); + df_push_cmd__root(&p, df_cmd_spec_from_core_cmd_kind(DF_CoreCmdKind_CompleteQuery)); + } + } + } + + dbgi_scope_close(scope); + scratch_end(scratch); + ProfEnd(); } //////////////////////////////// diff --git a/src/df/gfx/generated/df_gfx.meta.h b/src/df/gfx/generated/df_gfx.meta.h index 9935a75a..9f3efdbf 100644 --- a/src/df/gfx/generated/df_gfx.meta.h +++ b/src/df/gfx/generated/df_gfx.meta.h @@ -956,10 +956,10 @@ DF_StringBindingPair df_g_default_binding_table[] = {str8_lit_comp("rotate_panel_columns"), {OS_Key_2, 0 |OS_EventFlag_Ctrl }}, {str8_lit_comp("next_panel"), {OS_Key_Comma, 0 |OS_EventFlag_Ctrl }}, {str8_lit_comp("prev_panel"), {OS_Key_Comma, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift }}, -{str8_lit_comp("focus_panel_right"), {OS_Key_Right, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift |OS_EventFlag_Alt}}, -{str8_lit_comp("focus_panel_left"), {OS_Key_Left, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift |OS_EventFlag_Alt}}, -{str8_lit_comp("focus_panel_up"), {OS_Key_Up, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift |OS_EventFlag_Alt}}, -{str8_lit_comp("focus_panel_down"), {OS_Key_Down, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift |OS_EventFlag_Alt}}, +{str8_lit_comp("focus_panel_right"), {OS_Key_Right, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Alt}}, +{str8_lit_comp("focus_panel_left"), {OS_Key_Left, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Alt}}, +{str8_lit_comp("focus_panel_up"), {OS_Key_Up, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Alt}}, +{str8_lit_comp("focus_panel_down"), {OS_Key_Down, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Alt}}, {str8_lit_comp("close_panel"), {OS_Key_P, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift }}, {str8_lit_comp("next_tab"), {OS_Key_PageDown, 0 |OS_EventFlag_Ctrl }}, {str8_lit_comp("prev_tab"), {OS_Key_PageUp, 0 |OS_EventFlag_Ctrl }}, @@ -968,8 +968,8 @@ DF_StringBindingPair df_g_default_binding_table[] = {str8_lit_comp("move_tab_right"), {OS_Key_PageDown, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift }}, {str8_lit_comp("move_tab_left"), {OS_Key_PageUp, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift }}, {str8_lit_comp("close_tab"), {OS_Key_W, 0 |OS_EventFlag_Ctrl }}, -{str8_lit_comp("tab_bar_top"), {OS_Key_Up, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Alt}}, -{str8_lit_comp("tab_bar_bottom"), {OS_Key_Down, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Alt}}, +{str8_lit_comp("tab_bar_top"), {OS_Key_Up, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift |OS_EventFlag_Alt}}, +{str8_lit_comp("tab_bar_bottom"), {OS_Key_Down, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift |OS_EventFlag_Alt}}, {str8_lit_comp("open"), {OS_Key_O, 0 |OS_EventFlag_Ctrl }}, {str8_lit_comp("reload_active"), {OS_Key_R, 0 |OS_EventFlag_Ctrl |OS_EventFlag_Shift }}, {str8_lit_comp("switch"), {OS_Key_I, 0 |OS_EventFlag_Ctrl }}, diff --git a/src/file_stream/file_stream.c b/src/file_stream/file_stream.c index 0521e9ea..2bf6fe57 100644 --- a/src/file_stream/file_stream.c +++ b/src/file_stream/file_stream.c @@ -24,11 +24,11 @@ fs_init(void) fs_shared->u2s_ring_base = push_array_no_zero(arena, U8, fs_shared->u2s_ring_size); fs_shared->u2s_ring_cv = os_condition_variable_alloc(); fs_shared->u2s_ring_mutex = os_mutex_alloc(); - fs_shared->streamer_count = Min(4, os_logical_core_count()-1); + fs_shared->streamer_count = Clamp(1, os_logical_core_count()-1, 4); fs_shared->streamers = push_array(arena, OS_Handle, 1); for(U64 idx = 0; idx < fs_shared->streamer_count; idx += 1) { - fs_shared->streamers[idx] = os_launch_thread(fs_streamer_thread__entry_point, &idx, 0); + fs_shared->streamers[idx] = os_launch_thread(fs_streamer_thread__entry_point, (void *)idx, 0); } } diff --git a/src/geo_cache/geo_cache.c b/src/geo_cache/geo_cache.c index fd96bfdc..09bdbbe4 100644 --- a/src/geo_cache/geo_cache.c +++ b/src/geo_cache/geo_cache.c @@ -35,7 +35,7 @@ geo_init(void) geo_shared->u2x_ring_base = push_array_no_zero(arena, U8, geo_shared->u2x_ring_size); geo_shared->u2x_ring_cv = os_condition_variable_alloc(); geo_shared->u2x_ring_mutex = os_mutex_alloc(); - geo_shared->xfer_thread_count = Min(4, os_logical_core_count()-1); + geo_shared->xfer_thread_count = Clamp(1, os_logical_core_count()-1, 4); geo_shared->xfer_threads = push_array(arena, OS_Handle, geo_shared->xfer_thread_count); for(U64 idx = 0; idx < geo_shared->xfer_thread_count; idx += 1) { diff --git a/src/text_cache/text_cache.c b/src/text_cache/text_cache.c index 82c2504b..9aca682a 100644 --- a/src/text_cache/text_cache.c +++ b/src/text_cache/text_cache.c @@ -412,7 +412,7 @@ txt_init(void) txt_shared->u2p_ring_base = push_array_no_zero(arena, U8, txt_shared->u2p_ring_size); txt_shared->u2p_ring_cv = os_condition_variable_alloc(); txt_shared->u2p_ring_mutex = os_mutex_alloc(); - txt_shared->parse_thread_count = Min(4, os_logical_core_count()-1); + txt_shared->parse_thread_count = Clamp(1, os_logical_core_count()-1, 4); txt_shared->parse_threads = push_array(arena, OS_Handle, txt_shared->parse_thread_count); for(U64 idx = 0; idx < txt_shared->parse_thread_count; idx += 1) { diff --git a/src/texture_cache/texture_cache.c b/src/texture_cache/texture_cache.c index 6118d0f1..1003e2f4 100644 --- a/src/texture_cache/texture_cache.c +++ b/src/texture_cache/texture_cache.c @@ -48,7 +48,7 @@ tex_init(void) tex_shared->u2x_ring_base = push_array_no_zero(arena, U8, tex_shared->u2x_ring_size); tex_shared->u2x_ring_cv = os_condition_variable_alloc(); tex_shared->u2x_ring_mutex = os_mutex_alloc(); - tex_shared->xfer_thread_count = Min(4, os_logical_core_count()-1); + tex_shared->xfer_thread_count = Clamp(1, os_logical_core_count()-1, 4); tex_shared->xfer_threads = push_array(arena, OS_Handle, tex_shared->xfer_thread_count); for(U64 idx = 0; idx < tex_shared->xfer_thread_count; idx += 1) { diff --git a/src/txti/txti.c b/src/txti/txti.c index 2be72a2e..c1abb060 100644 --- a/src/txti/txti.c +++ b/src/txti/txti.c @@ -20,7 +20,7 @@ txti_init(void) txti_state->entity_map_stripes.v[idx].cv = os_condition_variable_alloc(); txti_state->entity_map_stripes.v[idx].rw_mutex = os_rw_mutex_alloc(); } - txti_state->mut_thread_count = Min(4, os_logical_core_count()); + txti_state->mut_thread_count = Clamp(1, os_logical_core_count(), 4); txti_state->mut_threads = push_array(txti_state->arena, TXTI_MutThread, txti_state->mut_thread_count); for(U64 idx = 0; idx < txti_state->mut_thread_count; idx += 1) {