mkxp-z/libretro/ruby-setjmp.patch
刘皓 82444abed2
Fix stack pointer leak in libretro builds
There's currently a memory leak in libretro builds where memory usage
increases by several kilobytes every frame you hold down an arrow key
while the player character is visible on the map in KNight-Blade.

This fixes a bug where parts of the WebAssembly stack are leaked when an
exception is caught in Ruby. There seems to be another source of memory
leaking, though, because memory usage still increases by several
kilobytes every frame like before.

I'm pretty sure this bug I fixed is an internal Ruby bug that I should
be creating a pull request to fix. I'll create one once I fully fix the
memory leak, since there might be more Ruby bugs that I have yet to
find.
2025-03-25 16:19:08 -04:00

42 lines
1.7 KiB
Diff

# Fixes a bug in WASI builds of Ruby where the stack pointer gets corrupted after a `longjmp` gets caught by `rb_wasm_try_catch_loop_run`.
--- a/wasm/setjmp.c
+++ b/wasm/setjmp.c
@@ -143,6 +143,7 @@ rb_wasm_try_catch_init(struct rb_wasm_try_catch *try_catch,
try_catch->try_f = try_f;
try_catch->catch_f = catch_f;
try_catch->context = context;
+ try_catch->stack_pointer = NULL;
}
// NOTE: This function is not processed by Asyncify due to a call of asyncify_stop_rewind
@@ -154,6 +155,10 @@ rb_wasm_try_catch_loop_run(struct rb_wasm_try_catch *try_catch, rb_wasm_jmp_buf
target->state = JMP_BUF_STATE_CAPTURED;
+ if (try_catch->stack_pointer == NULL) {
+ try_catch->stack_pointer = rb_wasm_get_stack_pointer();
+ }
+
switch ((enum try_catch_phase)try_catch->state) {
case TRY_CATCH_PHASE_MAIN:
// may unwind
@@ -175,6 +180,8 @@ rb_wasm_try_catch_loop_run(struct rb_wasm_try_catch *try_catch, rb_wasm_jmp_buf
// stop unwinding
// (but call stop_rewind to update the asyncify state to "normal" from "unwind")
asyncify_stop_rewind();
+ // reset the stack pointer to what it was before the most recent call to try_f or catch_f
+ rb_wasm_set_stack_pointer(try_catch->stack_pointer);
// clear the active jmpbuf because it's already stopped
_rb_wasm_active_jmpbuf = NULL;
// reset jmpbuf state to be able to unwind again
--- a/wasm/setjmp.h
+++ b/wasm/setjmp.h
@@ -65,6 +65,7 @@ struct rb_wasm_try_catch {
rb_wasm_try_catch_func_t try_f;
rb_wasm_try_catch_func_t catch_f;
void *context;
+ void *stack_pointer;
int state;
};