ZJIT: Use rb_gc_disable() over rb_gc_disable_no_rest()

no_rest() trips an assert inside the GC when we allocate with the GC
disabled this way:

    (gc_continue) ../src/gc/default/default.c:2029
    (newobj_cache_miss+0x128) [0x105040048] ../src/gc/default/default.c:2370
    (rb_gc_impl_new_obj+0x7c) [0x105036374] ../src/gc/default/default.c:2482
    (newobj_of) ../src/gc.c:995
    (rb_method_entry_alloc+0x40) [0x1051e6c64] ../src/vm_method.c:1102
    (rb_method_entry_complement_defined_class) ../src/vm_method.c:1180
    (prepare_callable_method_entry+0x14c) [0x1051e87b8] ../src/vm_method.c:1728
    (callable_method_entry_or_negative+0x1e8) [0x1051e809c] ../src/vm_method.c:1874

It's tries to continue the GC because it was out of space. Looks like
it's not safe to allocate new objects after using
rb_gc_disable_no_rest(); existing usages use it for malloc calls.
This commit is contained in:
Alan Wu 2025-10-15 13:53:57 -04:00
parent b052d706a5
commit 4c426e98a8
Notes: git 2025-10-15 20:37:15 +00:00
3 changed files with 3 additions and 3 deletions

View File

@ -130,7 +130,7 @@ fn main() {
.allowlist_function("rb_singleton_class")
.allowlist_function("rb_define_class")
.allowlist_function("rb_class_get_superclass")
.allowlist_function("rb_gc_disable_no_rest")
.allowlist_function("rb_gc_disable")
.allowlist_function("rb_gc_enable")
.allowlist_function("rb_gc_mark")
.allowlist_function("rb_gc_mark_movable")

View File

@ -897,7 +897,7 @@ where
// 2. If we yield to the GC while compiling, it re-enters our mark and update functions.
// This breaks `&mut` exclusivity since mark functions derive fresh `&mut` from statics
// while there is a stack frame below it that has an overlapping `&mut`. That's UB.
let gc_disabled_pre_call = unsafe { rb_gc_disable_no_rest() }.test();
let gc_disabled_pre_call = unsafe { rb_gc_disable() }.test();
let ret = match catch_unwind(func) {
Ok(result) => result,

View File

@ -746,6 +746,7 @@ unsafe extern "C" {
pub fn rb_gc_mark_movable(obj: VALUE);
pub fn rb_gc_location(obj: VALUE) -> VALUE;
pub fn rb_gc_enable() -> VALUE;
pub fn rb_gc_disable() -> VALUE;
pub fn rb_gc_writebarrier(old: VALUE, young: VALUE);
pub fn rb_class_get_superclass(klass: VALUE) -> VALUE;
pub static mut rb_cObject: VALUE;
@ -877,7 +878,6 @@ unsafe extern "C" {
buff_size: usize,
obj: VALUE,
) -> *const ::std::os::raw::c_char;
pub fn rb_gc_disable_no_rest() -> VALUE;
pub fn rb_ec_stack_check(ec: *mut rb_execution_context_struct) -> ::std::os::raw::c_int;
pub fn rb_gc_writebarrier_remember(obj: VALUE);
pub fn rb_shape_id_offset() -> i32;