From 386f87481632f1ba8de53fd94d314183034a4b06 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 26 May 2025 14:11:51 -0400 Subject: [PATCH] Don't copy FL_PROMOTED to new object in Ractor move We should not copy the FL_PROMOTED flag when we move an object in Ractor#send(move: true) because the newly created object may not be old. --- bootstraptest/test_ractor.rb | 1 + ractor.c | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index e8940d98f9..cbe732e4ea 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -2427,6 +2427,7 @@ end assert_equal 'ok', %q{ r = Ractor.new do o = Ractor.receive + GC.verify_internal_consistency GC.start o end diff --git a/ractor.c b/ractor.c index 94777cf512..b2446439a3 100644 --- a/ractor.c +++ b/ractor.c @@ -3656,8 +3656,15 @@ move_enter(VALUE obj, struct obj_traverse_replace_data *data) static enum obj_traverse_iterator_result move_leave(VALUE obj, struct obj_traverse_replace_data *data) { - size_t size = rb_gc_obj_slot_size(obj); - memcpy((void *)data->replacement, (void *)obj, size); + // Copy flags + VALUE ignored_flags = RUBY_FL_PROMOTED; + RBASIC(data->replacement)->flags = (RBASIC(obj)->flags & ~ignored_flags) | (RBASIC(data->replacement)->flags & ignored_flags); + // Copy contents without the flags + memcpy( + (char *)data->replacement + sizeof(VALUE), + (char *)obj + sizeof(VALUE), + rb_gc_obj_slot_size(obj) - sizeof(VALUE) + ); void rb_replace_generic_ivar(VALUE clone, VALUE obj); // variable.c