diff options
author | Peter Zhu <peter@peterzhu.ca> | 2023-11-22 10:04:57 -0500 |
---|---|---|
committer | Peter Zhu <peter@peterzhu.ca> | 2023-11-23 09:11:24 -0500 |
commit | 7f7613c2c7550d3b008fc132821ccf305f119cac (patch) | |
tree | eb90f7feae660599fd9223dcc8724ea835e6d1c3 /variable.c | |
parent | f1c32c0ee08e924e202f529ee8438d2de4f2702a (diff) | |
download | ruby-7f7613c2c7550d3b008fc132821ccf305f119cac.tar.gz |
Fix compacting during evacuation of generic ivars
When evacuating generic instance variables, the instance variables exist
in both the array and the ST table. We need to ensure it has switched
to the ST table before performing any operations that can trigger GC
compaction.
Diffstat (limited to 'variable.c')
-rw-r--r-- | variable.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/variable.c b/variable.c index 8151e55b85..5eeee636bb 100644 --- a/variable.c +++ b/variable.c @@ -1379,7 +1379,23 @@ rb_obj_convert_to_too_complex(VALUE obj, st_table *table) RB_VM_LOCK_ENTER(); { struct st_table *gen_ivs = generic_ivtbl_no_ractor_check(obj); - st_lookup(gen_ivs, (st_data_t)obj, (st_data_t *)&old_ivptr); + + struct gen_ivtbl *old_ivtbl = NULL; + st_lookup(gen_ivs, (st_data_t)obj, (st_data_t *)&old_ivtbl); + + if (old_ivtbl) { + /* We need to modify old_ivtbl to have the too complex shape + * and hold the table because the xmalloc could trigger a GC + * compaction. We want the table to be updated rather than than + * the original ivptr. */ +#if SHAPE_IN_BASIC_FLAGS + rb_shape_set_shape_id(obj, OBJ_TOO_COMPLEX_SHAPE_ID); +#else + old_ivtbl->shape_id = OBJ_TOO_COMPLEX_SHAPE_ID; +#endif + old_ivtbl->as.complex.table = table; + old_ivptr = (VALUE *)old_ivtbl; + } struct gen_ivtbl *ivtbl = xmalloc(sizeof(struct gen_ivtbl)); ivtbl->as.complex.table = table; @@ -1627,7 +1643,9 @@ rb_ensure_iv_list_size(VALUE obj, uint32_t current_capacity, uint32_t new_capaci int rb_obj_copy_ivs_to_hash_table_i(ID key, VALUE val, st_data_t arg) { - st_insert((st_table *)arg, (st_data_t)key, (st_data_t)val); + RUBY_ASSERT(!st_lookup((st_table *)arg, (st_data_t)key, NULL)); + + st_add_direct((st_table *)arg, (st_data_t)key, (st_data_t)val); return ST_CONTINUE; } |