ZJIT: Add missing write barrier in profiling (GH-13922)

Fixes `TestZJIT::test_require_rubygems`. It was crashing locally due to
false collection of a live object. See
<https://alanwu.space/post/write-barrier/>.

Co-authored-by: Max Bernstein <max@bernsteinbear.com>
Co-authored-by: Takashi Kokubun <takashi.kokubun@shopify.com>
Co-authored-by: Stan Lo <stan.lo@shopify.com>
This commit is contained in:
Alan Wu 2025-07-16 19:25:37 -04:00 committed by GitHub
parent 571a8d2753
commit 960fae438b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 6 additions and 0 deletions

View File

@ -167,6 +167,7 @@ fn main() {
.allowlist_function("rb_gc_mark_movable")
.allowlist_function("rb_gc_location")
.allowlist_function("rb_gc_writebarrier")
.allowlist_function("rb_gc_writebarrier_remember")
// VALUE variables for Ruby class objects
// From include/ruby/internal/globals.h

View File

@ -852,6 +852,7 @@ unsafe extern "C" {
) -> *const rb_callable_method_entry_t;
pub fn rb_obj_info(obj: VALUE) -> *const ::std::os::raw::c_char;
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;
pub fn rb_obj_shape_id(obj: VALUE) -> shape_id_t;
pub fn rb_shape_get_iv_index(shape_id: shape_id_t, id: ID, value: *mut attr_index_t) -> bool;

View File

@ -89,6 +89,10 @@ fn profile_operands(profiler: &mut Profiler, profile: &mut IseqProfile, n: usize
let opnd_type = Type::from_value(profiler.peek_at_stack((n - i - 1) as isize));
types[i] = types[i].union(opnd_type);
}
// In the loop above, we probably added a new reference to the profile through
// the VALUE in Type. It's messy and relatively slow to conditionally run a
// write barrier for each Type, so just remember to re-mark the iseq.
unsafe { rb_gc_writebarrier_remember(profiler.iseq.into()) };
}
#[derive(Debug)]