diff options
author | Peter Zhu <peter@peterzhu.ca> | 2023-11-24 10:25:06 -0500 |
---|---|---|
committer | Peter Zhu <peter@peterzhu.ca> | 2023-11-24 13:29:04 -0500 |
commit | 269c705f93c4db631f4cad89991bc5d69a7dcd03 (patch) | |
tree | ab71fb98e0a7465aae04ff3a2338222c58a51104 /variable.c | |
parent | e201b81f79828c30500947fe8c8ea3c515e3d112 (diff) | |
download | ruby-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.c | 23 |
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]); } } } |