diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index 25af87b610..834eb627ef 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -1969,6 +1969,19 @@ assert_equal 'ok', %q{ roundtripped_obj.instance_variable_get(:@array1) == [1] ? :ok : roundtripped_obj } +# move object with generic ivars and existing id2ref table +# [Bug #21664] +assert_equal 'ok', %q{ + obj = [1] + obj.instance_variable_set("@field", :ok) + ObjectSpace._id2ref(obj.object_id) # build id2ref table + + ractor = Ractor.new { Ractor.receive } + ractor.send(obj, move: true) + obj = ractor.value + obj.instance_variable_get("@field") +} + # copy object with complex generic ivars assert_equal 'ok', %q{ # Make Array too_complex diff --git a/ractor.c b/ractor.c index 70594443d6..48fbf7cfb9 100644 --- a/ractor.c +++ b/ractor.c @@ -1973,13 +1973,12 @@ move_leave(VALUE obj, struct obj_traverse_replace_data *data) rb_gc_writebarrier_remember(data->replacement); void rb_replace_generic_ivar(VALUE clone, VALUE obj); // variable.c - - rb_gc_obj_id_moved(data->replacement); - if (UNLIKELY(rb_obj_exivar_p(obj))) { rb_replace_generic_ivar(data->replacement, obj); } + rb_gc_obj_id_moved(data->replacement); + VALUE flags = T_OBJECT | FL_FREEZE | (RBASIC(obj)->flags & FL_PROMOTED); // Avoid mutations using bind_call, etc.