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.
Related issues
Bug #20255: Embedded arrays aren't moved correctly across ractors
Bug #20267: Hashes that use ar_table aren't moved properly across ractors
Bug #20271: Issue with moving embedded string across ractors
Ractor: Fix moving embedded objects
[Bug #20271]
[Bug #20267]
[Bug #20255]
rb_obj_alloc(RBASIC_CLASS(obj))will always allocate from the basic40B pool, so if
objis larger than40B, we'll create a corruptedobject 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 originalobject.
We then must turn it into a
T_OBJECT, because otherwisejust changing its class to
RactorMovedleaves a lot ofways to keep using the object, e.g.:
If it turns out that
rb_obj_cloneisn't performant enoughfor some uses, we can always have carefully crafted specialized
paths for the types that would benefit from it.