Do not inline the slow path of frequently called functions

This commit is contained in:
Lior Halphon 2023-04-25 13:06:14 +03:00
parent 237e127b36
commit 32a419ad2e
6 changed files with 38 additions and 19 deletions

View File

@ -30,10 +30,8 @@ static uint16_t bank_for_addr(GB_gameboy_t *gb, uint16_t addr)
return 0;
}
void GB_apply_cheat(GB_gameboy_t *gb, uint16_t address, uint8_t *value)
static noinline void apply_cheat(GB_gameboy_t *gb, uint16_t address, uint8_t *value)
{
if (likely(!gb->cheat_enabled)) return;
if (likely(gb->cheat_count == 0)) return; // Optimization
if (unlikely(!gb->boot_rom_finished)) return;
const GB_cheat_hash_t *hash = gb->cheat_hash[hash_addr(address)];
if (likely(!hash)) return;
@ -49,6 +47,13 @@ void GB_apply_cheat(GB_gameboy_t *gb, uint16_t address, uint8_t *value)
}
}
void GB_apply_cheat(GB_gameboy_t *gb, uint16_t address, uint8_t *value)
{
if (likely(!gb->cheat_enabled)) return;
if (likely(gb->cheat_count == 0)) return; // Optimization
apply_cheat(gb, address, value);
}
bool GB_cheats_enabled(GB_gameboy_t *gb)
{
return gb->cheat_enabled;

View File

@ -685,6 +685,11 @@ exit:
return ret;
}
static void update_debug_active(GB_gameboy_t *gb)
{
gb->debug_active = !gb->debug_disable && (gb->debug_stopped || gb->debug_fin_command || gb->debug_next_command || gb->breakpoints);
}
struct debugger_command_s;
typedef bool debugger_command_imp_t(GB_gameboy_t *gb, char *arguments, char *modifiers, const struct debugger_command_s *command);
typedef char *debugger_completer_imp_t(GB_gameboy_t *gb, const char *string, uintptr_t *context);
@ -763,7 +768,7 @@ static bool interrupt(GB_gameboy_t *gb, char *arguments, char *modifiers, const
return true;
}
gb->debug_stopped = true;
GB_debugger_break(gb);
return true;
}
@ -2253,7 +2258,7 @@ static bool _GB_debugger_test_write_watchpoint(GB_gameboy_t *gb, value_t addr, u
return false;
}
if (!gb->watchpoints[index].condition) {
gb->debug_stopped = true;
GB_debugger_break(gb);
GB_log(gb, "Watchpoint: [%s] = $%02x\n", debugger_value_to_string(gb, addr, true), value);
return true;
}
@ -2266,7 +2271,7 @@ static bool _GB_debugger_test_write_watchpoint(GB_gameboy_t *gb, value_t addr, u
return false;
}
if (condition) {
gb->debug_stopped = true;
GB_debugger_break(gb);
GB_log(gb, "Watchpoint: [%s] = $%02x\n", debugger_value_to_string(gb, addr, true), value);
return true;
}
@ -2298,7 +2303,7 @@ static bool _GB_debugger_test_read_watchpoint(GB_gameboy_t *gb, value_t addr)
return false;
}
if (!gb->watchpoints[index].condition) {
gb->debug_stopped = true;
GB_debugger_break(gb);
GB_log(gb, "Watchpoint: [%s]\n", debugger_value_to_string(gb, addr, true));
return true;
}
@ -2311,7 +2316,7 @@ static bool _GB_debugger_test_read_watchpoint(GB_gameboy_t *gb, value_t addr)
return false;
}
if (condition) {
gb->debug_stopped = true;
GB_debugger_break(gb);
GB_log(gb, "Watchpoint: [%s]\n", debugger_value_to_string(gb, addr, true));
return true;
}
@ -2464,10 +2469,8 @@ typedef enum {
static jump_to_return_t test_jump_to_breakpoints(GB_gameboy_t *gb, uint16_t *address);
void GB_debugger_run(GB_gameboy_t *gb)
static void noinline debugger_run(GB_gameboy_t *gb)
{
if (gb->debug_disable) return;
if (!gb->undo_state) {
gb->undo_state = malloc(GB_get_save_state_size_no_bess(gb));
GB_save_state_to_buffer_no_bess(gb, gb->undo_state);
@ -2475,10 +2478,10 @@ void GB_debugger_run(GB_gameboy_t *gb)
char *input = NULL;
if (gb->debug_next_command && gb->debug_call_depth <= 0 && !gb->halted) {
gb->debug_stopped = true;
GB_debugger_break(gb);
}
if (gb->debug_fin_command && gb->debug_call_depth <= -1) {
gb->debug_stopped = true;
GB_debugger_break(gb);
}
if (gb->debug_stopped) {
if (!gb->help_shown) {
@ -2492,7 +2495,7 @@ next_command:
free(input);
}
if (gb->breakpoints && !gb->debug_stopped && should_break(gb, gb->pc, false)) {
gb->debug_stopped = true;
GB_debugger_break(gb);
GB_log(gb, "Breakpoint: PC = %s\n", value_to_string(gb, gb->pc, true));
GB_cpu_disassemble(gb, gb->pc, 5);
}
@ -2511,11 +2514,11 @@ next_command:
GB_log(gb, "Jumping to breakpoint: PC = %s\n", value_to_string(gb, gb->pc, true));
GB_cpu_disassemble(gb, gb->pc, 5);
GB_load_state_from_buffer(gb, gb->nontrivial_jump_state, -1);
gb->debug_stopped = true;
GB_debugger_break(gb);
}
}
else if (jump_to_result == JUMP_TO_BREAK) {
gb->debug_stopped = true;
GB_debugger_break(gb);
GB_log(gb, "Jumping to breakpoint: PC = %s\n", value_to_string(gb, address, true));
GB_cpu_disassemble(gb, gb->pc, 5);
gb->non_trivial_jump_breakpoint_occured = false;
@ -2548,6 +2551,7 @@ next_command:
if (input == NULL) {
/* Debugging is no currently available, continue running */
gb->debug_stopped = false;
update_debug_active(gb);
return;
}
@ -2557,6 +2561,12 @@ next_command:
free(input);
}
update_debug_active(gb);
}
void GB_debugger_run(GB_gameboy_t *gb)
{
if (likely(!gb->debug_active)) return;
debugger_run(gb);
}
void GB_debugger_handle_async_commands(GB_gameboy_t *gb)
@ -2675,6 +2685,7 @@ bool GB_debugger_evaluate(GB_gameboy_t *gb, const char *string, uint16_t *result
void GB_debugger_break(GB_gameboy_t *gb)
{
gb->debug_stopped = true;
update_debug_active(gb);
}
bool GB_debugger_is_stopped(GB_gameboy_t *gb)
@ -2685,6 +2696,7 @@ bool GB_debugger_is_stopped(GB_gameboy_t *gb)
void GB_debugger_set_disabled(GB_gameboy_t *gb, bool disabled)
{
gb->debug_disable = disabled;
update_debug_active(gb);
}
/* Jump-to breakpoints */

View File

@ -11,6 +11,7 @@
#define unlikely(x) GB_unlikely(x)
#define internal __attribute__((visibility("internal")))
#define noinline __attribute__((noinline))
#if __clang__
#define unrolled _Pragma("unroll")

View File

@ -76,7 +76,7 @@ static char *default_input_callback(GB_gameboy_t *gb)
}
if (expression[0] == '\x03') {
gb->debug_stopped = true;
GB_debugger_break(gb);
free(expression);
return strdup("");
}
@ -1183,7 +1183,7 @@ unsigned GB_run(GB_gameboy_t *gb)
GB_set_running_thread(gb);
GB_cpu_run(gb);
GB_clear_running_thread(gb);
if (gb->vblank_just_occured) {
if (unlikely(gb->vblank_just_occured)) {
GB_debugger_handle_async_commands(gb);
GB_set_running_thread(gb);
GB_rewind_push(gb);

View File

@ -736,6 +736,7 @@ struct GB_gameboy_internal_s {
/*** Debugger ***/
volatile bool debug_stopped, debug_disable;
bool debug_fin_command, debug_next_command;
bool debug_active; // Cached value determining if GB_debugger_run does anything
bool help_shown;
/* Breakpoints */

View File

@ -950,7 +950,7 @@ LD_X_Y(a,b) LD_X_Y(a,c) LD_X_Y(a,d) LD_X_Y(a,e) LD_X_Y(a,h) LD_X_Y(a,l) LD_X_DHL
static void ld_b_b(GB_gameboy_t *gb, uint8_t opcode)
{
if (gb->has_software_breakpoints) {
gb->debug_stopped = true;
GB_debugger_break(gb);
}
}