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. --- internal/gc.h | 1 + 1 file changed, 1 insertion(+) (limited to 'internal') diff --git a/internal/gc.h b/internal/gc.h index 4e9b4554e8..454f8ec685 100644 --- a/internal/gc.h +++ b/internal/gc.h @@ -183,6 +183,7 @@ struct rb_gc_object_metadata_entry { /* gc.c */ RUBY_ATTR_MALLOC void *ruby_mimmalloc(size_t size); RUBY_ATTR_MALLOC void *ruby_mimcalloc(size_t num, size_t size); +void rb_gc_ractor_moved(VALUE dest, VALUE src); void ruby_mimfree(void *ptr); void rb_gc_prepare_heap(void); void rb_objspace_set_event_hook(const rb_event_flag_t event); -- cgit v1.2.3