diff options
author | Jean Boussier <[email protected]> | 2023-11-16 17:50:21 +0100 |
---|---|---|
committer | Jean Boussier <[email protected]> | 2023-11-17 09:19:21 +0100 |
commit | 94c9f166632a901e563463933efd42e618432d70 () | |
tree | 948304c7e1b048d53cba547c49c0bac828066659 /variable.c | |
parent | 498b086c374608005278c0f7d105df1925e13a22 (diff) |
Refactor rb_obj_evacuate_ivs_to_hash_table
That function is a bit too low level to called from multiple places. It's always used in tandem with `rb_shape_set_too_complex` and both have to know how the object is laid out to update the `iv_ptr`. So instead we can provide two higher level function: - `rb_obj_copy_ivs_to_hash_table` to prepare a `st_table` from an arbitrary oject. - `rb_obj_convert_to_too_complex` to assign the new `st_table` to the old object, and safely free the old `iv_ptr`. Unfortunately both can't be combined into one, because `rb_obj_copy_ivar` need `rb_obj_copy_ivs_to_hash_table` to copy from one object to another.
-rw-r--r-- | variable.c | 90 |
1 files changed, 50 insertions, 40 deletions
@@ -1371,55 +1371,59 @@ rb_attr_delete(VALUE obj, ID id) } void -rb_evict_ivars_to_hash(VALUE obj) { RUBY_ASSERT(!rb_shape_obj_too_complex(obj)); - st_table *table = st_init_numtable_with_size(rb_ivar_count(obj)); - - // Evacuate all previous values from shape into id_table - rb_ivar_foreach(obj, rb_obj_evacuate_ivs_to_hash_table, (st_data_t)table); switch (BUILTIN_TYPE(obj)) { - case T_OBJECT: - rb_shape_set_too_complex(obj); - - if (!(RBASIC(obj)->flags & ROBJECT_EMBED)) { - xfree(ROBJECT(obj)->as.heap.ivptr); - } - - ROBJECT_SET_IV_HASH(obj, table); - break; - case T_CLASS: - case T_MODULE: - rb_shape_set_too_complex(obj); - - xfree(RCLASS_IVPTR(obj)); - RCLASS_SET_IV_HASH(obj, table); - break; - default: - RB_VM_LOCK_ENTER(); - { - struct st_table *gen_ivs = generic_ivtbl_no_ractor_check(obj); - st_data_t old_ivtbl; - struct gen_ivtbl *ivtbl = NULL; - - if (st_delete(gen_ivs, &obj, &old_ivtbl)) { - ivtbl = (struct gen_ivtbl *)old_ivtbl; - } - - ivtbl = xrealloc(ivtbl, sizeof(struct gen_ivtbl)); - ivtbl->as.complex.table = table; #if SHAPE_IN_BASIC_FLAGS - rb_shape_set_too_complex(obj); #else - ivtbl->shape_id = OBJ_TOO_COMPLEX_SHAPE_ID; #endif - st_insert(gen_ivs, (st_data_t)obj, (st_data_t)ivtbl); - } - RB_VM_LOCK_LEAVE(); } RUBY_ASSERT(rb_shape_obj_too_complex(obj)); } @@ -1637,12 +1641,18 @@ rb_ensure_iv_list_size(VALUE obj, uint32_t current_capacity, uint32_t new_capaci } int -rb_obj_evacuate_ivs_to_hash_table(ID key, VALUE val, st_data_t arg) { st_insert((st_table *)arg, (st_data_t)key, (st_data_t)val); return ST_CONTINUE; } static VALUE * obj_ivar_set_shape_ivptr(VALUE obj, void *_data) { |