From 0350290262ea0fbc4e1807901797ee8a6970c2b9 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 27 Mar 2025 14:26:59 +0100 Subject: Ractor: Fix moving embedded objects [Bug #20271] [Bug #20267] [Bug #20255] `rb_obj_alloc(RBASIC_CLASS(obj))` will always allocate from the basic 40B pool, so if `obj` is larger than `40B`, we'll create a corrupted object when we later copy the shape_id. Instead we can use the same logic than ractor copy, which is to use `rb_obj_clone`, and later ask the GC to free the original object. We then must turn it into a `T_OBJECT`, because otherwise just changing its class to `RactorMoved` leaves a lot of ways to keep using the object, e.g.: ``` a = [1, 2, 3] Ractor.new{}.send(a, move: true) [].concat(a) # Should raise, but wasn't. ``` If it turns out that `rb_obj_clone` isn't performant enough for some uses, we can always have carefully crafted specialized paths for the types that would benefit from it. --- variable.c | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'variable.c') diff --git a/variable.c b/variable.c index 468f2c3930..b987a57f1e 100644 --- a/variable.c +++ b/variable.c @@ -2157,27 +2157,6 @@ rb_copy_generic_ivar(VALUE clone, VALUE obj) } } -void -rb_replace_generic_ivar(VALUE clone, VALUE obj) -{ - RUBY_ASSERT(FL_TEST(obj, FL_EXIVAR)); - - RB_VM_LOCK_ENTER(); - { - st_data_t ivtbl, obj_data = (st_data_t)obj; - if (st_lookup(generic_iv_tbl_, (st_data_t)obj, &ivtbl)) { - st_insert(generic_iv_tbl_, (st_data_t)clone, ivtbl); - st_delete(generic_iv_tbl_, &obj_data, NULL); - } - else { - rb_bug("unreachable"); - } - } - RB_VM_LOCK_LEAVE(); - - FL_SET(clone, FL_EXIVAR); -} - void rb_ivar_foreach(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg) { -- cgit v1.2.3