Add generic ivar reference updating step

Previously, generic ivars worked differently than the other global tables
during compaction. The other global tables had their references updated
through iteration during rb_gc_update_vm_references. Generic ivars updated
the keys when the object moved and updated the values while reference
updating the object. This is inefficient as this required one lookup for
every moved object and one lookup for every object with generic ivars.

Instead, this commit changes it to iterate over the generic ivar table to
update both the keys and values.
This commit is contained in:
Peter Zhu 2025-01-21 16:36:03 -05:00
parent 7070b1b196
commit 89240eb2fb
Notes: git 2025-01-22 13:55:10 +00:00
4 changed files with 28 additions and 32 deletions

View file

@ -1136,31 +1136,40 @@ rb_mark_generic_ivar(VALUE obj)
}
}
void
rb_ref_update_generic_ivar(VALUE obj)
static int
rb_generic_ivar_update_references_i(st_data_t key, st_data_t val, st_data_t _data)
{
struct gen_ivtbl *ivtbl;
VALUE orig_obj = (VALUE)key;
VALUE obj = rb_gc_location(orig_obj);
struct gen_ivtbl *ivtbl = (struct gen_ivtbl *)val;
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]);
}
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]);
}
}
if (obj != orig_obj) {
st_insert(generic_iv_tbl_, (st_data_t)obj, (st_data_t)ivtbl);
return ST_DELETE;
}
else {
return ST_CONTINUE;
}
}
void
rb_mv_generic_ivar(VALUE rsrc, VALUE dst)
rb_generic_ivar_update_references(void)
{
st_data_t key = (st_data_t)rsrc;
st_data_t ivtbl;
if (st_delete(generic_ivtbl_no_ractor_check(rsrc), &key, &ivtbl))
st_insert(generic_ivtbl_no_ractor_check(dst), (st_data_t)dst, ivtbl);
DURING_GC_COULD_MALLOC_REGION_START();
{
st_foreach(generic_iv_tbl_, rb_generic_ivar_update_references_i, (st_data_t)0);
}
DURING_GC_COULD_MALLOC_REGION_END();
}
void