aboutsummaryrefslogtreecommitdiffstats
path: root/variable.c
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2023-11-24 10:25:06 -0500
committerPeter Zhu <peter@peterzhu.ca>2023-11-24 13:29:04 -0500
commit269c705f93c4db631f4cad89991bc5d69a7dcd03 (patch)
treeab71fb98e0a7465aae04ff3a2338222c58a51104 /variable.c
parente201b81f79828c30500947fe8c8ea3c515e3d112 (diff)
downloadruby-269c705f93c4db631f4cad89991bc5d69a7dcd03.tar.gz
Fix compaction for generic ivars
When generic instance variable has a shape, it is marked movable. If it it transitions to too complex, it needs to update references otherwise it may have incorrect references.
Diffstat (limited to 'variable.c')
-rw-r--r--variable.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/variable.c b/variable.c
index 5eeee636bb..056572cc36 100644
--- a/variable.c
+++ b/variable.c
@@ -1066,17 +1066,34 @@ gen_ivtbl_resize(struct gen_ivtbl *old, uint32_t n)
}
void
-rb_mark_and_update_generic_ivar(VALUE obj)
+rb_mark_generic_ivar(VALUE obj)
{
struct gen_ivtbl *ivtbl;
if (rb_gen_ivtbl_get(obj, 0, &ivtbl)) {
if (rb_shape_obj_too_complex(obj)) {
- rb_mark_tbl(ivtbl->as.complex.table);
+ rb_mark_tbl_no_pin(ivtbl->as.complex.table);
}
else {
for (uint32_t i = 0; i < ivtbl->as.shape.numiv; i++) {
- rb_gc_mark_and_move(&ivtbl->as.shape.ivptr[i]);
+ rb_gc_mark_movable(ivtbl->as.shape.ivptr[i]);
+ }
+ }
+ }
+}
+
+void
+rb_ref_update_generic_ivar(VALUE obj)
+{
+ struct gen_ivtbl *ivtbl;
+
+ if (rb_gen_ivtbl_get(obj, 0, &ivtbl)) {
+ if (rb_shape_obj_too_complex(obj)) {
+ rb_gc_ref_update_table_values_only(ivtbl->as.complex.table);
+ }
+ else {
+ for (uint32_t i = 0; i < ivtbl->as.shape.numiv; i++) {
+ ivtbl->as.shape.ivptr[i] = rb_gc_location(ivtbl->as.shape.ivptr[i]);
}
}
}