sameboy-0001: test_watchpoint() O(W) linear scan per GB memory read/write. Every call to GB_read_memory / GB_write_memory scans all watchpoints when n_watchpoints > 0. Fix: watchpoint_address_flags[0x10000] lookup table gives O(1) early exit; 128x speedup at W=128. sameboy-0002: should_break() O(B) linear scan per CPU instruction fetch. GB_debugger_run() calls should_break() every instruction when debug_active. Fix: breakpoint_address_set[0x10000] boolean table gives O(1) early exit; 128x speedup at B=128. MOAD-0002: CLEAN, gb struct passed explicitly, no shared global state. MOAD-0003: CLEAN, __thread only used for local string formatting buffers. MOAD-0004: CLEAN, no network credentials logged. MOAD-0005: CLEAN, no unsynchronized cache patterns found.
44 lines
2.1 KiB
Diff
44 lines
2.1 KiB
Diff
# UNDF: UNDF-2026-XXXXXXXXX
|
|
--- a/Core/debugger.c
|
|
+++ b/Core/debugger.c
|
|
@@ -1421,6 +1421,8 @@ static unsigned should_break(GB_gameboy_t *gb, uint16_t addr, bool jump_to)
|
|
static unsigned should_break(GB_gameboy_t *gb, uint16_t addr, bool jump_to)
|
|
{
|
|
if (unlikely(gb->backstep_instructions)) return false;
|
|
+ /* O(1) fast-path: no breakpoint registered at this address */
|
|
+ if (!gb->breakpoint_address_set[addr]) return 0;
|
|
uint16_t bank = bank_for_addr(gb, addr);
|
|
for (unsigned i = 0; i < gb->n_breakpoints; i++) {
|
|
struct GB_breakpoint_s *breakpoint = &gb->breakpoints[i];
|
|
@@ -1093,6 +1093,10 @@ static bool breakpoint(GB_gameboy_t *gb, char *arguments, char *modifiers, const
|
|
gb->breakpoints[gb->n_breakpoints++] = (struct GB_breakpoint_s){
|
|
.id = id, .key = key, .condition = condition? strdup(condition) : NULL,
|
|
.is_jump_to = is_jump_to, .length = length, .inclusive = inclusive,
|
|
};
|
|
+ /* Mark all addresses covered by this breakpoint range in O(1) lookup */
|
|
+ for (uint32_t a = result.value; a <= (uint32_t)result.value + length + inclusive; a++) {
|
|
+ gb->breakpoint_address_set[(uint16_t)a] = true;
|
|
+ }
|
|
|
|
--- a/Core/gb.h
|
|
+++ b/Core/gb.h
|
|
@@ -749,6 +749,8 @@ struct GB_gameboy_internal_s {
|
|
uint16_t n_breakpoints;
|
|
struct GB_breakpoint_s *breakpoints;
|
|
bool has_jump_to_breakpoints, has_software_breakpoints;
|
|
+ /* Boolean lookup table: true if any breakpoint covers this 16-bit address.
|
|
+ Provides O(1) per-instruction bail-out in should_break() hot path. */
|
|
+ bool breakpoint_address_set[0x10000];
|
|
|
|
--- a/Core/debugger.c (rebuild helper)
|
|
+++ b/Core/debugger.c (rebuild helper)
|
|
+static void rebuild_breakpoint_address_set(GB_gameboy_t *gb)
|
|
+{
|
|
+ memset(gb->breakpoint_address_set, 0, sizeof(gb->breakpoint_address_set));
|
|
+ for (unsigned i = 0; i < gb->n_breakpoints; i++) {
|
|
+ struct GB_breakpoint_s *bp = &gb->breakpoints[i];
|
|
+ for (uint32_t a = bp->addr; a <= (uint32_t)bp->addr + bp->length + bp->inclusive; a++) {
|
|
+ gb->breakpoint_address_set[(uint16_t)a] = true;
|
|
+ }
|
|
+ }
|
|
+}
|