summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean Boussier <jean.boussier@gmail.com>2025-08-25 14:58:53 +0200
committerJean Boussier <jean.boussier@gmail.com>2025-08-25 17:13:00 +0200
commit0a621790f085c7e3d9c85c7b6b725944cb32d4fc (patch)
tree6f47a515b7814cd06e86c41b7cff121b4c613c9c
parent4139849e4ba92db0b33791e70115adce1908547a (diff)
Refactor rb_obj_ivar_set to use generic_shape_ivar
-rw-r--r--variable.c56
1 files changed, 25 insertions, 31 deletions
diff --git a/variable.c b/variable.c
index 967a7139ca..56b8993b2d 100644
--- a/variable.c
+++ b/variable.c
@@ -1895,53 +1895,47 @@ rb_obj_copy_fields_to_hash_table(VALUE obj, st_table *table)
rb_field_foreach(obj, rb_obj_copy_ivs_to_hash_table_i, (st_data_t)table, false);
}
+static attr_index_t
+obj_complex_ivar_set(VALUE obj, ID id, VALUE val)
+{
+ RUBY_ASSERT(rb_shape_obj_too_complex_p(obj));
+
+ st_table *table = ROBJECT_FIELDS_HASH(obj);
+ st_insert(table, (st_data_t)id, (st_data_t)val);
+ RB_OBJ_WRITTEN(obj, Qundef, val);
+ return 0;
+}
+
attr_index_t
rb_obj_ivar_set(VALUE obj, ID id, VALUE val)
{
shape_id_t current_shape_id = RBASIC_SHAPE_ID(obj);
if (UNLIKELY(rb_shape_too_complex_p(current_shape_id))) {
- goto too_complex;
+ return obj_complex_ivar_set(obj, id, val);
}
- attr_index_t index;
- if (!rb_shape_get_iv_index(current_shape_id, id, &index)) {
- index = RSHAPE_LEN(current_shape_id);
- if (index >= SHAPE_MAX_FIELDS) {
- rb_raise(rb_eArgError, "too many instance variables");
- }
+ bool newivar;
+ shape_id_t target_shape_id = generic_shape_ivar(obj, id, &newivar);
+ attr_index_t index = RSHAPE_INDEX(target_shape_id);
- shape_id_t next_shape_id = rb_shape_transition_add_ivar(obj, id);
- if (UNLIKELY(rb_shape_too_complex_p(next_shape_id))) {
- current_shape_id = rb_evict_fields_to_hash(obj);
- goto too_complex;
+ if (newivar) {
+ if (UNLIKELY(rb_shape_too_complex_p(target_shape_id))) {
+ rb_evict_fields_to_hash(obj);
+ return obj_complex_ivar_set(obj, id, val);
}
- else if (UNLIKELY(RSHAPE_CAPACITY(next_shape_id) != RSHAPE_CAPACITY(current_shape_id))) {
- RUBY_ASSERT(RSHAPE_CAPACITY(next_shape_id) > RSHAPE_CAPACITY(current_shape_id));
- rb_ensure_iv_list_size(obj, RSHAPE_CAPACITY(current_shape_id), RSHAPE_CAPACITY(next_shape_id));
+
+ if (UNLIKELY(RSHAPE_CAPACITY(target_shape_id) != RSHAPE_CAPACITY(current_shape_id))) {
+ RUBY_ASSERT(RSHAPE_CAPACITY(target_shape_id) > RSHAPE_CAPACITY(current_shape_id));
+ rb_ensure_iv_list_size(obj, RSHAPE_CAPACITY(current_shape_id), RSHAPE_CAPACITY(target_shape_id));
}
- RUBY_ASSERT(RSHAPE_TYPE_P(next_shape_id, SHAPE_IVAR),
- "next_shape_id: 0x%" PRIx32 " RSHAPE_TYPE(next_shape_id): %d",
- next_shape_id, (int)RSHAPE_TYPE(next_shape_id));
- RUBY_ASSERT(index == (RSHAPE_INDEX(next_shape_id)));
- RBASIC_SET_SHAPE_ID(obj, next_shape_id);
+ RBASIC_SET_SHAPE_ID(obj, target_shape_id);
}
- VALUE *table = ROBJECT_FIELDS(obj);
- RB_OBJ_WRITE(obj, &table[index], val);
+ RB_OBJ_WRITE(obj, &ROBJECT_FIELDS(obj)[index], val);
return index;
-
-too_complex:
- {
- RUBY_ASSERT(rb_shape_obj_too_complex_p(obj));
-
- st_table *table = ROBJECT_FIELDS_HASH(obj);
- st_insert(table, (st_data_t)id, (st_data_t)val);
- RB_OBJ_WRITTEN(obj, Qundef, val);
- }
- return 0;
}
static void