Copying GC support for EXIVAR

Instance variables held in gen_ivtbl are marked with rb_gc_mark.  It
prevents the referenced objects from moving, which is bad for copying
garbage collectors.

This commit allows those instance variables to be updated during
gc_update_object_references.
This commit is contained in:
Kunshan Wang 2022-10-27 17:47:47 +08:00 committed by Peter Zhu
parent d92289f633
commit de724487f0
Notes: git 2023-01-31 14:24:46 +00:00
3 changed files with 10 additions and 6 deletions

6
gc.c
View File

@ -7232,7 +7232,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
gc_mark_set_parent(objspace, obj); gc_mark_set_parent(objspace, obj);
if (FL_TEST(obj, FL_EXIVAR)) { if (FL_TEST(obj, FL_EXIVAR)) {
rb_mark_generic_ivar(obj); rb_mark_and_update_generic_ivar(obj);
} }
switch (BUILTIN_TYPE(obj)) { switch (BUILTIN_TYPE(obj)) {
@ -10560,6 +10560,10 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
gc_report(4, objspace, "update-refs: %p ->\n", (void *)obj); gc_report(4, objspace, "update-refs: %p ->\n", (void *)obj);
if (FL_TEST(obj, FL_EXIVAR)) {
rb_mark_and_update_generic_ivar(obj);
}
switch (BUILTIN_TYPE(obj)) { switch (BUILTIN_TYPE(obj)) {
case T_CLASS: case T_CLASS:
case T_MODULE: case T_MODULE:

View File

@ -42,7 +42,7 @@ int rb_obj_evacuate_ivs_to_hash_table(ID key, VALUE val, st_data_t arg);
RUBY_SYMBOL_EXPORT_BEGIN RUBY_SYMBOL_EXPORT_BEGIN
/* variable.c (export) */ /* variable.c (export) */
void rb_mark_generic_ivar(VALUE); void rb_mark_and_update_generic_ivar(VALUE);
void rb_mv_generic_ivar(VALUE src, VALUE dst); void rb_mv_generic_ivar(VALUE src, VALUE dst);
VALUE rb_const_missing(VALUE klass, VALUE name); VALUE rb_const_missing(VALUE klass, VALUE name);
int rb_class_ivar_set(VALUE klass, ID vid, VALUE value); int rb_class_ivar_set(VALUE klass, ID vid, VALUE value);

View File

@ -1020,22 +1020,22 @@ generic_ivar_update(st_data_t *k, st_data_t *v, st_data_t u, int existing)
} }
static void static void
gen_ivtbl_mark(const struct gen_ivtbl *ivtbl) gen_ivtbl_mark_and_update(struct gen_ivtbl *ivtbl)
{ {
uint32_t i; uint32_t i;
for (i = 0; i < ivtbl->numiv; i++) { for (i = 0; i < ivtbl->numiv; i++) {
rb_gc_mark(ivtbl->ivptr[i]); rb_gc_mark_and_move(&ivtbl->ivptr[i]);
} }
} }
void void
rb_mark_generic_ivar(VALUE obj) rb_mark_and_update_generic_ivar(VALUE obj)
{ {
struct gen_ivtbl *ivtbl; struct gen_ivtbl *ivtbl;
if (rb_gen_ivtbl_get(obj, 0, &ivtbl)) { if (rb_gen_ivtbl_get(obj, 0, &ivtbl)) {
gen_ivtbl_mark(ivtbl); gen_ivtbl_mark_and_update(ivtbl);
} }
} }