aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gc.c10
-rw-r--r--internal/gc.h2
-rw-r--r--internal/variable.h3
-rw-r--r--variable.c23
4 files changed, 32 insertions, 6 deletions
diff --git a/gc.c b/gc.c
index 260b891b1e..2d7eb4de93 100644
--- a/gc.c
+++ b/gc.c
@@ -7255,7 +7255,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
gc_mark_set_parent(objspace, obj);
if (FL_TEST(obj, FL_EXIVAR)) {
- rb_mark_and_update_generic_ivar(obj);
+ rb_mark_generic_ivar(obj);
}
switch (BUILTIN_TYPE(obj)) {
@@ -10249,6 +10249,12 @@ gc_ref_update_table_values_only(rb_objspace_t *objspace, st_table *tbl)
}
}
+void
+rb_gc_ref_update_table_values_only(st_table *tbl)
+{
+ gc_ref_update_table_values_only(&rb_objspace, tbl);
+}
+
static void
gc_update_table_refs(rb_objspace_t * objspace, st_table *tbl)
{
@@ -10623,7 +10629,7 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
gc_report(4, objspace, "update-refs: %p ->\n", (void *)obj);
if (FL_TEST(obj, FL_EXIVAR)) {
- rb_mark_and_update_generic_ivar(obj);
+ rb_ref_update_generic_ivar(obj);
}
switch (BUILTIN_TYPE(obj)) {
diff --git a/internal/gc.h b/internal/gc.h
index 188497b007..34a6043e8a 100644
--- a/internal/gc.h
+++ b/internal/gc.h
@@ -250,6 +250,8 @@ void rb_gc_mark_and_move(VALUE *ptr);
void rb_gc_mark_weak(VALUE *ptr);
void rb_gc_remove_weak(VALUE parent_obj, VALUE *ptr);
+void rb_gc_ref_update_table_values_only(st_table *tbl);
+
#define rb_gc_mark_and_move_ptr(ptr) do { \
VALUE _obj = (VALUE)*(ptr); \
rb_gc_mark_and_move(&_obj); \
diff --git a/internal/variable.h b/internal/variable.h
index 63b074a308..b2a30c7c58 100644
--- a/internal/variable.h
+++ b/internal/variable.h
@@ -53,7 +53,8 @@ void rb_evict_ivars_to_hash(VALUE obj);
RUBY_SYMBOL_EXPORT_BEGIN
/* variable.c (export) */
-void rb_mark_and_update_generic_ivar(VALUE);
+void rb_mark_generic_ivar(VALUE obj);
+void rb_ref_update_generic_ivar(VALUE);
void rb_mv_generic_ivar(VALUE src, VALUE dst);
VALUE rb_const_missing(VALUE klass, VALUE name);
int rb_class_ivar_set(VALUE klass, ID vid, VALUE value);
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]);
}
}
}