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.
This commit is contained in:
Aaron Patterson 2019-08-26 11:31:52 -07:00
Родитель d9bfbe363d
Коммит 09d8e06b33
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 953170BCB4FFAFC6
1 изменённых файлов: 36 добавлений и 1 удалений

37
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));