diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 733248ec..37e5f437 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -754,10 +754,10 @@ ctrl_process_read(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, return actual_bytes_read; } -internal String8 +internal CTRL_ProcessMemorySlice ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range) { - String8 result = {0}; + CTRL_ProcessMemorySlice result = {0}; if(range.max > range.min && dim_1u64(range) <= MB(256) && range.min <= 0x000FFFFFFFFFFFFFull && @@ -821,6 +821,7 @@ ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID mac { page_found = 1; MemoryCopy((U8*)read_out + (page_vaddr-page_range.min), page_data.str, KB(4)); + result.fresh = result.fresh || !!(node4->page_fresh_flags[lvl5_idx/64] & (1ull<<(lvl5_idx%64))); } else { @@ -898,6 +899,16 @@ ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID mac }; U128 page_key = hs_hash_from_data(str8((U8 *)page_key_data, sizeof(page_key_data))); U128 page_hash = hs_submit_data(page_key, &page_arena, str8((U8 *)page_base, KB(4))); + if(!u128_match(node4->page_hashes[lvl5_idx], u128_zero()) && + !u128_match(node4->page_hashes[lvl5_idx], page_hash)) + { + node4->page_fresh_flags[lvl5_idx/64] |= (1ull<<(lvl5_idx%64)); + } + else + { + node4->page_fresh_flags[lvl5_idx/64] &= ~(1ull<<(lvl5_idx%64)); + } + result.fresh = result.fresh || !!(node4->page_fresh_flags[lvl5_idx/64] & (1ull<<(lvl5_idx%64))); node4->page_hashes[lvl5_idx] = page_hash; } else @@ -910,22 +921,22 @@ ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID mac //- rjf: fill result by skipping/chopping read memory U64 byte_in_page_idx = (range.min&0x0000000000000FFFull) >> 0; - result.str = (U8*)read_out + byte_in_page_idx; - result.size = dim_1u64(range); + result.data.str = (U8*)read_out + byte_in_page_idx; + result.data.size = dim_1u64(range); hs_scope_close(scope); } return result; } -internal String8 +internal CTRL_ProcessMemorySlice ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, U64 vaddr, U64 limit, U64 endt_us) { - String8 result = ctrl_query_cached_data_from_process_vaddr_range(arena, machine_id, process, r1u64(vaddr, vaddr+limit)); - for(U64 idx = 0; idx < result.size; idx += 1) + CTRL_ProcessMemorySlice result = ctrl_query_cached_data_from_process_vaddr_range(arena, machine_id, process, r1u64(vaddr, vaddr+limit)); + for(U64 idx = 0; idx < result.data.size; idx += 1) { - if(result.str[idx] == 0) + if(result.data.str[idx] == 0) { - result.size = idx; + result.data.size = idx; break; } } diff --git a/src/ctrl/ctrl_core.h b/src/ctrl/ctrl_core.h index 6947bde7..c667c7de 100644 --- a/src/ctrl/ctrl_core.h +++ b/src/ctrl/ctrl_core.h @@ -333,6 +333,8 @@ struct CTRL_ProcessMemoryCacheNode4 { U64 page_memgen_idxs[256]; U128 page_hashes[256]; + U128 last_page_hashes[256]; + U64 page_fresh_flags[4]; }; typedef struct CTRL_ProcessMemoryCacheNode3 CTRL_ProcessMemoryCacheNode3; @@ -406,6 +408,13 @@ struct CTRL_ProcessMemoryCache CTRL_ProcessMemoryCacheStripe *stripes; }; +typedef struct CTRL_ProcessMemorySlice CTRL_ProcessMemorySlice; +struct CTRL_ProcessMemorySlice +{ + String8 data; + B32 fresh; +}; + //////////////////////////////// //~ rjf: Wakeup Hook Function Types @@ -560,8 +569,8 @@ internal Architecture ctrl_arch_from_handle(CTRL_MachineID machine, CTRL_Handle //- rjf: process memory reading/writing internal U64 ctrl_process_read(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, void *dst); -internal String8 ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range); -internal String8 ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, U64 vaddr, U64 limit, U64 endt_us); +internal CTRL_ProcessMemorySlice ctrl_query_cached_data_from_process_vaddr_range(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range); +internal CTRL_ProcessMemorySlice ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(Arena *arena, CTRL_MachineID machine_id, CTRL_Handle process, U64 vaddr, U64 limit, U64 endt_us); internal B32 ctrl_process_write_data(CTRL_MachineID machine_id, CTRL_Handle process, U64 vaddr, String8 data); internal U128 ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, CTRL_Handle process, Rng1U64 range, B32 zero_terminated); diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index abc88674..62f0ca98 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -3486,12 +3486,14 @@ df_tls_base_vaddr_from_thread(DF_Entity *thread) U64 thread_info_addr = ctrl_tls_root_vaddr_from_thread(thread->ctrl_machine_id, thread->ctrl_handle); U64 tls_addr_off = tls_index*addr_size; U64 tls_addr_array = 0; - String8 tls_addr_array_data = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(thread_info_addr, thread_info_addr+addr_size)); + CTRL_ProcessMemorySlice tls_addr_array_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(thread_info_addr, thread_info_addr+addr_size)); + String8 tls_addr_array_data = tls_addr_array_slice.data; if(tls_addr_array_data.size >= 8) { MemoryCopy(&tls_addr_array, tls_addr_array_data.str, sizeof(U64)); } - String8 result_data = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(tls_addr_array + tls_addr_off, tls_addr_array + tls_addr_off + addr_size)); + CTRL_ProcessMemorySlice result_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(tls_addr_array + tls_addr_off, tls_addr_array + tls_addr_off + addr_size)); + String8 result_data = result_slice.data; if(result_data.size >= 8) { MemoryCopy(&base_vaddr, result_data.str, sizeof(U64)); @@ -3953,7 +3955,8 @@ df_eval_memory_read(void *u, void *out, U64 addr, U64 size) Assert(process->kind == DF_EntityKind_Process); Temp scratch = scratch_begin(0, 0); B32 result = 0; - String8 data = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(addr, addr+size)); + CTRL_ProcessMemorySlice slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(addr, addr+size)); + String8 data = slice.data; if(data.size == size) { result = 1; @@ -4251,7 +4254,8 @@ df_value_mode_eval_from_eval(TG_Graph *graph, RADDBG_Parsed *rdbg, DF_CtrlCtx *c Rng1U64 vaddr_range = r1u64(eval.offset, eval.offset + type_byte_size); if(dim_1u64(vaddr_range) == type_byte_size) { - String8 data = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, vaddr_range); + CTRL_ProcessMemorySlice slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, vaddr_range); + String8 data = slice.data; MemoryZeroArray(eval.imm_u128); MemoryCopy(eval.imm_u128, data.str, Min(data.size, sizeof(U64)*2)); eval.mode = EVAL_EvalMode_Value; @@ -4328,14 +4332,16 @@ df_dynamically_typed_eval_from_eval(TG_Graph *graph, RADDBG_Parsed *rdbg, DF_Ctr { U64 ptr_vaddr = eval.offset; U64 addr_size = bit_size_from_arch(arch)/8; - String8 ptr_value_memory = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, - r1u64(ptr_vaddr, ptr_vaddr+addr_size)); + CTRL_ProcessMemorySlice ptr_value_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, + r1u64(ptr_vaddr, ptr_vaddr+addr_size)); + String8 ptr_value_memory = ptr_value_slice.data; if(ptr_value_memory.size >= addr_size) { U64 class_base_vaddr = 0; MemoryCopy(&class_base_vaddr, ptr_value_memory.str, addr_size); - String8 vtable_base_ptr_memory = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, - r1u64(class_base_vaddr, class_base_vaddr+addr_size)); + CTRL_ProcessMemorySlice vtable_base_ptr_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, + r1u64(class_base_vaddr, class_base_vaddr+addr_size)); + String8 vtable_base_ptr_memory = vtable_base_ptr_slice.data; if(vtable_base_ptr_memory.size >= addr_size) { U64 vtable_vaddr = 0; diff --git a/src/df/gfx/df_gfx.c b/src/df/gfx/df_gfx.c index f73482dd..8a559f2d 100644 --- a/src/df/gfx/df_gfx.c +++ b/src/df/gfx/df_gfx.c @@ -6786,7 +6786,8 @@ df_single_line_eval_value_strings_from_eval(Arena *arena, DF_EvalVizStringFlags if(!has_array && direct_type_is_string && (flags & DF_EvalVizStringFlag_ReadOnlyDisplayRules) && eval.mode == EVAL_EvalMode_Addr) { U64 string_memory_addr = value_eval.imm_u64; - String8 text = ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(arena, process->ctrl_machine_id, process->ctrl_handle, string_memory_addr, 256, max_U64); + CTRL_ProcessMemorySlice text_slice = ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(arena, process->ctrl_machine_id, process->ctrl_handle, string_memory_addr, 256, max_U64); + String8 text = text_slice.data; space_taken += f_dim_from_tag_size_string(font, font_size, text).x; space_taken += 2*f_dim_from_tag_size_string(font, font_size, str8_lit("\"")).x; str8_list_push(arena, &list, str8_lit("\"")); @@ -6858,7 +6859,8 @@ df_single_line_eval_value_strings_from_eval(Arena *arena, DF_EvalVizStringFlags special_case = 1; DF_Entity *thread = df_entity_from_handle(ctrl_ctx->thread); DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); - String8 text = ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(arena, process->ctrl_machine_id, process->ctrl_handle, eval.offset, 256, max_U64); + CTRL_ProcessMemorySlice text_slice = ctrl_query_cached_zero_terminated_data_from_process_vaddr_limit(arena, process->ctrl_machine_id, process->ctrl_handle, eval.offset, 256, max_U64); + String8 text = text_slice.data; space_taken += f_dim_from_tag_size_string(font, font_size, text).x; space_taken += 2*f_dim_from_tag_size_string(font, font_size, str8_lit("\"")).x; str8_list_push(arena, &list, str8_lit("\"")); @@ -9009,6 +9011,9 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); DF_Entity *selected_thread = df_entity_from_handle(ctrl_ctx->thread); + DF_Entity *selected_thread_process = df_entity_ancestor_from_kind(selected_thread, DF_EntityKind_Process); + U64 selected_thread_rip_unwind_vaddr = df_query_cached_rip_from_thread_unwind(selected_thread, ctrl_ctx->unwind_count); + DF_Entity *selected_thread_module = df_module_from_process_vaddr(selected_thread_process, selected_thread_rip_unwind_vaddr); CTRL_Event stop_event = df_ctrl_last_stop_event(); DF_Entity *stopper_thread = df_entity_from_ctrl_handle(stop_event.machine_id, stop_event.entity); B32 is_focused = ui_is_focus_active(); @@ -9847,7 +9852,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ { has_line_info = (src2dasm_list->first->v.remap_line == line_num); line_info_line_num = line_num; - line_info_t = src2dasm_list->first->v.binary->alive_t; + line_info_t = selected_thread_module->alive_t; } if(dasm2src_list->first != 0) { @@ -9866,7 +9871,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ DF_Entity *binary = dasm2src_info->binary; has_line_info = 1; line_info_line_num = dasm2src_info->pt.line; - line_info_t = binary->alive_t; + line_info_t = selected_thread_module->alive_t; } } if(has_line_info) @@ -9969,7 +9974,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ { mapped_special = 1; new_color_kind = DF_ThemeColor_CodeFunction; - mix_t = binary->alive_t; + mix_t = selected_thread_module->alive_t; } } if(!mapped_special) @@ -9979,7 +9984,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ { mapped_special = 1; new_color_kind = DF_ThemeColor_CodeType; - mix_t = binary->alive_t; + mix_t = selected_thread_module->alive_t; } } if(!mapped_special) @@ -9989,7 +9994,7 @@ df_code_slice(DF_Window *ws, DF_CtrlCtx *ctrl_ctx, EVAL_ParseCtx *parse_ctx, DF_ { mapped_special = 1; new_color_kind = DF_ThemeColor_CodeLocal; - mix_t = binary->alive_t; + mix_t = selected_thread_module->alive_t; } } break; diff --git a/src/df/gfx/df_view_rule_hooks.c b/src/df/gfx/df_view_rule_hooks.c index 2d4c0550..6b53f149 100644 --- a/src/df/gfx/df_view_rule_hooks.c +++ b/src/df/gfx/df_view_rule_hooks.c @@ -30,7 +30,8 @@ df_view_rule_hooks__rgba_from_eval(DF_Eval eval, TG_Graph *graph, RADDBG_Parsed U64 array_total_size = tg_byte_size_from_graph_raddbg_key(graph, raddbg, type_key); U64 array_total_size_capped = ClampTop(array_total_size, 64); Rng1U64 array_memory_vaddr_rng = r1u64(eval.offset, eval.offset + array_total_size_capped); - String8 array_memory = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, array_memory_vaddr_rng); + CTRL_ProcessMemorySlice array_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, array_memory_vaddr_rng); + String8 array_memory = array_slice.data; TG_Key element_type_key = tg_unwrapped_direct_from_graph_raddbg_key(graph, raddbg, type_key); TG_Kind element_type_kind = tg_kind_from_key(element_type_key); U64 element_type_size = tg_byte_size_from_graph_raddbg_key(graph, raddbg, element_type_key); @@ -66,7 +67,8 @@ df_view_rule_hooks__rgba_from_eval(DF_Eval eval, TG_Graph *graph, RADDBG_Parsed U64 struct_total_size = tg_byte_size_from_graph_raddbg_key(graph, raddbg, type_key); U64 struct_total_size_capped = ClampTop(struct_total_size, 64); Rng1U64 struct_memory_vaddr_rng = r1u64(eval.offset, eval.offset + struct_total_size_capped); - String8 struct_memory = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, struct_memory_vaddr_rng); + CTRL_ProcessMemorySlice struct_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, struct_memory_vaddr_rng); + String8 struct_memory = struct_slice.data; TG_Type *type = tg_type_from_graph_raddbg_key(scratch.arena, graph, raddbg, type_key); for(U64 element_idx = 0, member_idx = 0; element_idx < 4 && member_idx < type->count; diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index dc66c9c6..2e0b8ca1 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -1032,7 +1032,23 @@ df_eval_watch_view_build(DF_Window *ws, DF_Panel *panel, DF_View *view, DF_EvalW //- rjf: build normal row if(!(row->flags & DF_EvalVizRowFlag_Canvas)) { - ui_set_next_flags(disabled_flags); + B32 row_is_fresh = 0; + if(row->eval.mode == EVAL_EvalMode_Addr) + { + Temp temp = temp_begin(scratch.arena); + U64 vaddr = row->eval.offset; + U64 size = tg_byte_size_from_graph_raddbg_key(parse_ctx.type_graph, parse_ctx.rdbg, row->eval.type_key); + CTRL_ProcessMemorySlice slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(vaddr, vaddr+size)); + row_is_fresh = slice.fresh; + temp_end(temp); + } + ui_set_next_flags(disabled_flags|(UI_BoxFlag_DrawBackground*row_is_fresh)); + if(row_is_fresh) + { + Vec4F32 fresh_bg_color = df_rgba_from_theme_color(DF_ThemeColor_Highlight0); + fresh_bg_color.w *= 0.25f; + ui_set_next_background_color(fresh_bg_color); + } UI_NamedTableVectorF("row_%I64x", row_hash) { //- rjf: expression diff --git a/src/hash_store/hash_store.c b/src/hash_store/hash_store.c index b8d89673..0d25bdce 100644 --- a/src/hash_store/hash_store.c +++ b/src/hash_store/hash_store.c @@ -122,7 +122,7 @@ hs_submit_data(U128 key, Arena **data_arena, String8 data) } //- rjf: commit this hash to key cache - U128 key_old_hash = {0}; + U128 key_expired_hash = {0}; OS_MutexScopeW(key_stripe->rw_mutex) { HS_KeyNode *key_node = 0; @@ -142,15 +142,19 @@ hs_submit_data(U128 key, Arena **data_arena, String8 data) } if(key_node) { - key_old_hash = key_node->hash; - key_node->hash = hash; + if(key_node->hash_history_gen+1 >= ArrayCount(key_node->hash_history)) + { + key_expired_hash = key_node->hash_history[(key_node->hash_history_gen-1)%ArrayCount(key_node->hash_history)]; + } + key_node->hash_history[key_node->hash_history_gen%ArrayCount(key_node->hash_history)] = hash; + key_node->hash_history_gen += 1; } } - //- rjf: if this key was correllated with an old hash, dec key ref count of old hash - if(!u128_match(key_old_hash, u128_zero())) + //- rjf: if this key's history cache was full, dec key ref count of oldest hash + if(!u128_match(key_expired_hash, u128_zero())) { - U64 old_hash_slot_idx = key_old_hash.u64[1]%hs_shared->slots_count; + U64 old_hash_slot_idx = key_expired_hash.u64[1]%hs_shared->slots_count; U64 old_hash_stripe_idx = old_hash_slot_idx%hs_shared->stripes_count; HS_Slot *old_hash_slot = &hs_shared->slots[old_hash_slot_idx]; HS_Stripe *old_hash_stripe = &hs_shared->stripes[old_hash_stripe_idx]; @@ -158,7 +162,7 @@ hs_submit_data(U128 key, Arena **data_arena, String8 data) { for(HS_Node *n = old_hash_slot->first; n != 0; n = n->next) { - if(u128_match(n->hash, key_old_hash)) + if(u128_match(n->hash, key_expired_hash)) { ins_atomic_u64_dec_eval(&n->key_ref_count); break; @@ -250,9 +254,9 @@ hs_hash_from_key(U128 key) { for(HS_KeyNode *n = key_slot->first; n != 0; n = n->next) { - if(u128_match(n->key, key)) + if(u128_match(n->key, key) && n->hash_history_gen > 0) { - result = n->hash; + result = n->hash_history[(n->hash_history_gen-1)%ArrayCount(n->hash_history)]; break; } } diff --git a/src/hash_store/hash_store.h b/src/hash_store/hash_store.h index 10e11e3d..bec35029 100644 --- a/src/hash_store/hash_store.h +++ b/src/hash_store/hash_store.h @@ -12,7 +12,8 @@ struct HS_KeyNode { HS_KeyNode *next; U128 key; - U128 hash; + U128 hash_history[2]; + U64 hash_history_gen; }; typedef struct HS_KeySlot HS_KeySlot;