mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
artifact_cache: fix leak of old-generation artifacts, when those artifacts are replaced by newer generation computations. artifacts can opaquely hold things like arena pointers, and so when we replace them in the cache, we need to respect the lookup api's provision of create/destroy hooks for the cache, such that the artifacts can be released correctly (using the destroy hook) before being replaced. this is separate from regular eviction.
This commit is contained in:
+1
-1
@@ -49,7 +49,7 @@ commands =
|
||||
// .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
// .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg debug telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
// .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
.f1 = { .win = "build raddbg opengl", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
.f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
|
||||
//- rjf: [raddbg wsl]
|
||||
// .f1 = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
|
||||
@@ -422,6 +422,18 @@ ac_async_tick(void)
|
||||
{
|
||||
if(str8_match(n->key, r->key, 0))
|
||||
{
|
||||
// rjf: eliminate existing values, if nay
|
||||
if(cache->destroy && ins_atomic_u64_eval(&n->completion_count) > 0) for(;;)
|
||||
{
|
||||
if(access_pt_is_expired(&n->access_pt, .time = 0, .update_idxs = 0))
|
||||
{
|
||||
cache->destroy(n->val);
|
||||
break;
|
||||
}
|
||||
cond_var_wait_rw(stripe->cv, stripe->rw_mutex, 1, max_U64);
|
||||
}
|
||||
|
||||
// rjf: write new value
|
||||
n->last_completed_gen = gen;
|
||||
n->val = val;
|
||||
ins_atomic_u64_dec_eval(&n->working_count);
|
||||
@@ -531,6 +543,18 @@ ac_async_tick(void)
|
||||
{
|
||||
if(str8_match(n->key, r->key, 0))
|
||||
{
|
||||
// rjf: eliminate existing values, if nay
|
||||
if(cache->destroy && ins_atomic_u64_eval(&n->completion_count) > 0) for(;;)
|
||||
{
|
||||
if(access_pt_is_expired(&n->access_pt, .time = 0, .update_idxs = 0))
|
||||
{
|
||||
cache->destroy(n->val);
|
||||
break;
|
||||
}
|
||||
cond_var_wait_rw(stripe->cv, stripe->rw_mutex, 1, max_U64);
|
||||
}
|
||||
|
||||
// rjf: store
|
||||
n->last_completed_gen = gen;
|
||||
n->val = val;
|
||||
ins_atomic_u64_dec_eval(&n->working_count);
|
||||
|
||||
+79
-1
@@ -1,6 +1,25 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Global Arena Table
|
||||
|
||||
#if ARENA_TABLE_DEBUG
|
||||
typedef struct ArenaTableNode ArenaTableNode;
|
||||
struct ArenaTableNode
|
||||
{
|
||||
ArenaTableNode *next;
|
||||
Arena *arena;
|
||||
};
|
||||
global U64 arena_table_take_init = 0;
|
||||
global U64 arena_table_inited = 0;
|
||||
global U64 arena_table_lock = 0;
|
||||
global ArenaTableNode *arena_table = 0;
|
||||
global U64 arena_table_count = 0;
|
||||
global U64 arena_table_cap = 0;
|
||||
global ArenaTableNode *free_arena_table_node = 0;
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Arena Functions
|
||||
|
||||
@@ -8,7 +27,7 @@
|
||||
|
||||
internal Arena *
|
||||
arena_alloc_(ArenaParams *params)
|
||||
{
|
||||
{
|
||||
U64 reserve_size = params->reserve_size;
|
||||
U64 commit_size = params->commit_size;
|
||||
|
||||
@@ -73,6 +92,47 @@ arena_alloc_(ArenaParams *params)
|
||||
#if ARENA_FREE_LIST
|
||||
arena->free_last = 0;
|
||||
#endif
|
||||
|
||||
// rjf: store in global arena table
|
||||
#if ARENA_TABLE_DEBUG
|
||||
if(ins_atomic_u64_eval_cond_assign(&arena_table_take_init, 1, 0) == 0)
|
||||
{
|
||||
arena_table = reserve_memory(GB(256));
|
||||
arena_table_cap = 4096;
|
||||
commit_memory(arena_table, arena_table_cap * sizeof(arena_table[0]));
|
||||
ins_atomic_u64_inc_eval(&arena_table_inited);
|
||||
}
|
||||
for(;!ins_atomic_u64_eval(&arena_table_inited);) {}
|
||||
for(;;)
|
||||
{
|
||||
B32 got_lock = (ins_atomic_u64_eval_cond_assign(&arena_table_lock, 1, 0) == 0);
|
||||
if(got_lock)
|
||||
{
|
||||
ArenaTableNode *node = free_arena_table_node;
|
||||
if(node != 0)
|
||||
{
|
||||
SLLStackPop(free_arena_table_node);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = &arena_table[arena_table_count];
|
||||
if(arena_table_count >= arena_table_cap)
|
||||
{
|
||||
U64 arena_table_cap__pre_grow = arena_table_cap;
|
||||
arena_table_cap *= 2;
|
||||
U64 arena_table_cap__post_grow = arena_table_cap;
|
||||
commit_memory(arena_table + arena_table_cap__pre_grow, sizeof(arena_table[0]) * (arena_table_cap__post_grow - arena_table_cap__pre_grow));
|
||||
}
|
||||
arena_table_count += 1;
|
||||
}
|
||||
node->arena = arena;
|
||||
arena->table_node = node;
|
||||
ins_atomic_u64_eval_assign(&arena_table_lock, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return arena;
|
||||
}
|
||||
|
||||
@@ -87,6 +147,24 @@ arena_release(Arena *arena)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ARENA_TABLE_DEBUG
|
||||
for(Arena *n = arena->current; n != 0; n = n->prev)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
B32 got_lock = (ins_atomic_u64_eval_cond_assign(&arena_table_lock, 1, 0) == 0);
|
||||
if(got_lock)
|
||||
{
|
||||
ArenaTableNode *table_node = n->table_node;
|
||||
MemoryZeroStruct(table_node);
|
||||
SLLStackPush(free_arena_table_node, table_node);
|
||||
ins_atomic_u64_eval_assign(&arena_table_lock, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for(Arena *n = arena->current, *prev = 0; n != 0; n = prev)
|
||||
{
|
||||
prev = n->prev;
|
||||
|
||||
@@ -46,6 +46,9 @@ struct Arena
|
||||
#if ARENA_FREE_LIST
|
||||
Arena *free_last;
|
||||
#endif
|
||||
#if ARENA_TABLE_DEBUG
|
||||
struct ArenaTableNode *table_node;
|
||||
#endif
|
||||
};
|
||||
StaticAssert(sizeof(Arena) <= ARENA_HEADER_SIZE, arena_header_size_check);
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ tctx_alloc(void)
|
||||
{
|
||||
#if PROFILE_TELEMETRY
|
||||
thread_static static char name[2][1024];
|
||||
raddbg_snprintf(name[0], sizeof(name[0]), "Scratch/0[TID:%u]", os_tid());
|
||||
raddbg_snprintf(name[1], sizeof(name[1]), "Scratch/1[TID:%u]", os_tid());
|
||||
raddbg_snprintf(name[0], sizeof(name[0]), "Scratch/0[TID:%u]", tid());
|
||||
raddbg_snprintf(name[1], sizeof(name[1]), "Scratch/1[TID:%u]", tid());
|
||||
Arena *arena_0 = arena_alloc(.name = name[0]);
|
||||
Arena *arena_1 = arena_alloc(.name = name[1]);
|
||||
#else
|
||||
|
||||
@@ -6820,7 +6820,7 @@ d_call_stack_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U6
|
||||
good = 1;
|
||||
call_stack[0] = d_call_stack_from_unwind(arena, process, &unwind);
|
||||
}
|
||||
if(unwind.flags & D_UnwindFlag_Stale)
|
||||
else
|
||||
{
|
||||
retry = 1;
|
||||
}
|
||||
|
||||
+43
-15
@@ -4,19 +4,45 @@
|
||||
////////////////////////////////
|
||||
//~ rjf: post-0.9.25 TODO notes
|
||||
//
|
||||
// [ ] "autos" collection, which can be evaluated
|
||||
// [ ] show "autos" inline in source code near thread?
|
||||
// [ ] step out of scopes / loops
|
||||
// [ ] memory_size(...) view for quickly evaluating memory sizes
|
||||
// [ ] value coloring view in watch window, so you can quickly scroll & see values outside of a threshold
|
||||
//
|
||||
// [ ] project/user file improvements
|
||||
// [ ] "default" -> "untitled"
|
||||
// [ ] should clear default project data every time the program starts
|
||||
// [ ] new project / user should not require picking a path; should just
|
||||
// by default go to "untitled" in default user path
|
||||
// [ ] more things should move to user data, but project-tagged - like
|
||||
// recent files, watches?, etc.
|
||||
//
|
||||
// [ ] killing/restarting thread performance (#780)
|
||||
// [ ] codebase-internal barrier impl (win7/linux support)
|
||||
// [ ] PDB -> RDI conversion memory usage
|
||||
// [ ] policy for closing debug info which is no longer relevant?
|
||||
// [ ] external window focusing bugs
|
||||
//
|
||||
// [ ] linux/dwarf fixes
|
||||
// [ ] excessive CPU usage on async threads - barrier impl?
|
||||
// [ ] step-over/step-into doesn't step successfully in many cases, just causes a continue
|
||||
// [ ] rd_frame has no type info, should be (void -> void) - type should be generated but it
|
||||
// [x] rd_frame has no type info, should be (void -> void) - type should be generated but it
|
||||
// is not being hooked up correctly
|
||||
// [ ] type views for `MyByte *` example do not match correctly
|
||||
//
|
||||
// [ ] many threads hitting conditional breakpoints -> causes 0x8000003 exception!
|
||||
// [ ] string conditional breakpoints -> size != 0 check seems to fail, can test w/ "rd_init" subprogram type gen in d2r2
|
||||
// [ ] no selected thread -> causing evaluation failures, e.g. with go-to-definition
|
||||
//
|
||||
//- evaluation space coverage pass
|
||||
// [ ] eval space reads/writes -> needs staleness/badness info - replace ctrl layer, to apply to all spaces
|
||||
// [ ] need concrete ways of referring into a space at any offset - e.g. `process.memory + 0x1234`, `file:"foo".data + 0x1234`, `thread.regs + 0x80`, etc.
|
||||
// [ ] memory view needs to take advantage of above when peeking; ensure peeking works on files etc.
|
||||
// [ ] need to eliminate accelerators from evaluation context, and build them on the fly instead -
|
||||
// this is necessary because, for instance, the correct locals_map varies by expression, if we
|
||||
// want to (we do) support features like "look up call stack to find local"
|
||||
// [ ] unit / module name qualification
|
||||
//
|
||||
//- memory view pass
|
||||
// [ ] toggleable ascii column
|
||||
@@ -31,10 +57,10 @@
|
||||
// [ ] signify empty watch window "expression" slot more as a text field?
|
||||
//
|
||||
//- jeff notes
|
||||
// [ ] option to prefer addresses first with string ptrs
|
||||
// [ ] focus changing on f10/f11? may be related to auto_run/auto_step - look at a bin/jeffr
|
||||
// [ ] option to turn off transient tabs altogether
|
||||
// [ ] single-line viz for pointers w/ bad (unmapped) addresses
|
||||
// [ ] option to prefer addresses first with string ptrs
|
||||
// [x] option to turn off transient tabs altogether
|
||||
//
|
||||
//- namespace/locations/variables RDI pass
|
||||
// [x] RDI_Local, RDI_GlobalVariable, RDI_ThreadVariable -> RDI_Variable
|
||||
@@ -58,12 +84,12 @@
|
||||
//- urgent fixes
|
||||
// [ ] (use msvc assert as an example) show fastfail exception info (code, name, etc.) - comes from ExceptionInformation @fastfail
|
||||
// [ ] stepping w/ spoofs & shadow stack enabled - writing spoof will send a stack buffer overrun event @shadow_stack_step
|
||||
// [ ] hardware breakpoints regression (global eval in ctrl)
|
||||
// [ ] native filesystem dialog, resizing raddbg window -> crash!
|
||||
// [ ] stdout/stderr path target setting is now busted >:(
|
||||
// [ ] stdout/stderr path target setting is now busted >:( (i think this is because of path confusion? check working dir)
|
||||
// [ ] target ui entry point should override built-in entry point
|
||||
// [ ] list of all tabs in palette
|
||||
// [ ] u64 + (ptr - ptr) seems to produce unexpected results - double check with C rules?
|
||||
// [x] hardware breakpoints regression (global eval in ctrl)
|
||||
//
|
||||
//- flow notes
|
||||
// [ ] "skip breakpoint, run to source", when stopped at a non-source location
|
||||
@@ -74,9 +100,9 @@
|
||||
//- memory view
|
||||
// [ ] have smaller visible range than entire memory space, within some bounds (e.g. 64KB)
|
||||
// [ ] dynamically expand memory space, based on scrolling
|
||||
// [ ] fix clicking through occluded panels etc.
|
||||
// [ ] disambiguate . character in ASCII columns
|
||||
// [ ] fix type intepretations of cursor in bottom pane
|
||||
// [x] fix type intepretations of cursor in bottom pane
|
||||
// [x] fix clicking through occluded panels etc.
|
||||
//
|
||||
//- watch improvements
|
||||
// [ ] *ALL* expressions in watch windows need to be editable.
|
||||
@@ -203,21 +229,21 @@
|
||||
// [ ] search-in-all-files
|
||||
// [ ] automatically snap to search matches when searching source files
|
||||
// [ ] memory view
|
||||
// [ ] memory view mutation controls
|
||||
// [ ] memory view user-made annotations
|
||||
// [ ] memory view searching
|
||||
// [x] memory view mutation controls
|
||||
// [ ] disasm view
|
||||
// [ ] visualize jump destinations in disasm
|
||||
//
|
||||
//- longer-term future features
|
||||
// [ ] long-term future notes from martins
|
||||
// [ ] core dump saving/loading
|
||||
// [ ] parallel call stacks view
|
||||
// [ ] parallel watch view
|
||||
// [ ] mixed native/interpreted/jit debugging
|
||||
// - it seems python has a top-level linked list of interpreter states,
|
||||
// which should allow the debugger to map native callstacks to python
|
||||
// code
|
||||
// [ ] core dump saving/loading
|
||||
// [ ] parallel call stacks view
|
||||
// [ ] parallel watch view
|
||||
// [ ] mixed native/interpreted/jit debugging
|
||||
// - it seems python has a top-level linked list of interpreter states,
|
||||
// which should allow the debugger to map native callstacks to python
|
||||
// code
|
||||
//
|
||||
//- code cleanup
|
||||
// [ ] eliminate explicit font parameters in the various ui paths (e.g.
|
||||
@@ -257,6 +283,8 @@
|
||||
#define FNT_INIT_MANUAL 1
|
||||
#define RD_INIT_MANUAL 1
|
||||
|
||||
#define ARENA_TABLE_DEBUG BUILD_DEBUG
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Includes
|
||||
|
||||
|
||||
@@ -278,11 +278,11 @@ internal R_OGL_FormatInfo r_ogl_format_info_from_tex2dformat(R_Tex2DFormat fmt);
|
||||
internal GLuint r_ogl_instance_buffer_from_size(U64 size);
|
||||
internal void r_ogl_debug_message_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam);
|
||||
|
||||
#define glUseProgramScope(...) DeferLoop(glUseProgram(__VA_ARGS__), glUseProgram(0))
|
||||
#define glBindVertexArrayScope(...) DeferLoop(glBindVertexArray(__VA_ARGS__), glBindVertexArray(0))
|
||||
#define glUseProgramScope(...) DeferLoop(glUseProgram(__VA_ARGS__), glUseProgram(0))
|
||||
#define glBindVertexArrayScope(...) DeferLoop(glBindVertexArray(__VA_ARGS__), glBindVertexArray(0))
|
||||
#define glBindFramebufferScope(target, ...) DeferLoop(glBindFramebuffer((target), __VA_ARGS__), glBindFramebuffer((target), 0))
|
||||
#define glBindTextureScope(target, ...) DeferLoop(glBindTexture((target), __VA_ARGS__), glBindTexture((target), 0))
|
||||
#define glEnableScope(...) DeferLoop(glEnable(__VA_ARGS__), glDisable(__VA_ARGS__))
|
||||
#define glBindTextureScope(target, ...) DeferLoop(glBindTexture((target), __VA_ARGS__), glBindTexture((target), 0))
|
||||
#define glEnableScope(...) DeferLoop(glEnable(__VA_ARGS__), glDisable(__VA_ARGS__))
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: OS-Specific Hooks
|
||||
|
||||
Reference in New Issue
Block a user