diff --git a/project.4coder b/project.4coder index 5881d188..40c41a21 100644 --- a/project.4coder +++ b/project.4coder @@ -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, }, diff --git a/src/artifact_cache/artifact_cache.c b/src/artifact_cache/artifact_cache.c index 3dd24a2d..53abac40 100644 --- a/src/artifact_cache/artifact_cache.c +++ b/src/artifact_cache/artifact_cache.c @@ -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); diff --git a/src/base/base_arena.c b/src/base/base_arena.c index e754399d..c83db36f 100644 --- a/src/base/base_arena.c +++ b/src/base/base_arena.c @@ -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; diff --git a/src/base/base_arena.h b/src/base/base_arena.h index 5a1d82c2..b3ba3782 100644 --- a/src/base/base_arena.h +++ b/src/base/base_arena.h @@ -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); diff --git a/src/base/base_thread_context.c b/src/base/base_thread_context.c index a6a8dfc2..42163610 100644 --- a/src/base/base_thread_context.c +++ b/src/base/base_thread_context.c @@ -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 diff --git a/src/dbg_engine/dbg_engine_ctrl.c b/src/dbg_engine/dbg_engine_ctrl.c index 08523c24..1e821a25 100644 --- a/src/dbg_engine/dbg_engine_ctrl.c +++ b/src/dbg_engine/dbg_engine_ctrl.c @@ -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; } diff --git a/src/raddbg/raddbg_main.c b/src/raddbg/raddbg_main.c index 46b59b94..e129dfc5 100644 --- a/src/raddbg/raddbg_main.c +++ b/src/raddbg/raddbg_main.c @@ -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 diff --git a/src/render/opengl/render_opengl.h b/src/render/opengl/render_opengl.h index b26fe155..e64ec04c 100644 --- a/src/render/opengl/render_opengl.h +++ b/src/render/opengl/render_opengl.h @@ -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