summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@ruby-lang.org>2019-08-26 11:31:52 -0700
committerAaron Patterson <tenderlove@ruby-lang.org>2019-08-26 11:31:52 -0700
commit09d8e06b335d7647fa5e0385980ba3f1a67a592b (patch)
tree8004f33f162627f44fff974f97e3becdf64a7e22
parentd9bfbe363d14f8258d239eb702729926571b88e7 (diff)
Try only updating hash value references
I'm afraid the keys to this hash are just integers, and those integers may look like VALUE pointers when they are not. Since we don't mark the keys to this hash, it's probably safe to say that none of them have moved, so we shouldn't try to update the references either.
-rw-r--r--gc.c37
1 files changed, 36 insertions, 1 deletions
diff --git a/gc.c b/gc.c
index f7b770b4c3..4d8ced7611 100644
--- a/gc.c
+++ b/gc.c
@@ -7769,6 +7769,41 @@ hash_foreach_replace(st_data_t key, st_data_t value, st_data_t argp, int error)
return ST_CONTINUE;
}
+static int
+hash_replace_ref_value(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
+{
+ rb_objspace_t *objspace = (rb_objspace_t *)argp;
+
+ if (gc_object_moved_p(objspace, (VALUE)*value)) {
+ *value = rb_gc_location((VALUE)*value);
+ }
+
+ return ST_CONTINUE;
+}
+
+static int
+hash_foreach_replace_value(st_data_t key, st_data_t value, st_data_t argp, int error)
+{
+ rb_objspace_t *objspace;
+
+ objspace = (rb_objspace_t *)argp;
+
+ if (gc_object_moved_p(objspace, (VALUE)value)) {
+ return ST_REPLACE;
+ }
+ return ST_CONTINUE;
+}
+
+static void
+gc_update_tbl_refs(rb_objspace_t * objspace, st_table *tbl)
+{
+ if (!tbl || tbl->num_entries == 0) return;
+
+ if (st_foreach_with_replace(tbl, hash_foreach_replace_value, hash_replace_ref_value, (st_data_t)objspace)) {
+ rb_raise(rb_eRuntimeError, "hash modified during iteration");
+ }
+}
+
static void
gc_update_table_refs(rb_objspace_t * objspace, st_table *tbl)
{
@@ -8020,7 +8055,7 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
}
if (!RCLASS_EXT(obj)) break;
if (RCLASS_IV_TBL(obj)) {
- gc_update_table_refs(objspace, RCLASS_IV_TBL(obj));
+ gc_update_tbl_refs(objspace, RCLASS_IV_TBL(obj));
}
update_class_ext(objspace, RCLASS_EXT(obj));
update_const_tbl(objspace, RCLASS_CONST_TBL(obj));