diff options
-rw-r--r-- | variable.c | 212 |
1 files changed, 151 insertions, 61 deletions
@@ -72,6 +72,22 @@ struct ivar_update { #endif }; void Init_var_tables(void) { @@ -1231,7 +1247,7 @@ rb_ivar_lookup(VALUE obj, ID id, VALUE undef) case T_CLASS: case T_MODULE: { - bool found; VALUE val; RB_VM_LOCK_ENTER(); @@ -1240,18 +1256,30 @@ rb_ivar_lookup(VALUE obj, ID id, VALUE undef) shape_id = RCLASS_SHAPE_ID(obj); #endif - attr_index_t index = 0; - shape = rb_shape_get_shape_by_id(shape_id); - found = rb_shape_get_iv_index(shape, id, &index); - - if (found) { - ivar_list = RCLASS_IVPTR(obj); - RUBY_ASSERT(ivar_list); - - val = ivar_list[index]; } else { - val = undef; } } RB_VM_LOCK_LEAVE(); @@ -1439,6 +1467,60 @@ rb_ensure_generic_iv_list_size(VALUE obj, rb_shape_t *shape, uint32_t newsize) return ivtbl; } // @note May raise when there are too many instance variables. rb_shape_t * rb_grow_iv_list(VALUE obj) @@ -1446,10 +1528,13 @@ rb_grow_iv_list(VALUE obj) rb_shape_t * initial_shape = rb_shape_get_shape(obj); RUBY_ASSERT(initial_shape->capacity > 0); rb_shape_t * res = rb_shape_transition_shape_capa(initial_shape); - - rb_ensure_iv_list_size(obj, initial_shape->capacity, res->capacity); - - rb_shape_set_shape(obj, res); return res; } @@ -1470,12 +1555,12 @@ rb_obj_ivar_set(VALUE obj, ID id, VALUE val) uint32_t num_iv = shape->capacity; if (rb_shape_obj_too_complex(obj)) { - st_table * table = ROBJECT_IV_HASH(obj); - st_insert(table, (st_data_t)id, (st_data_t)val); - RB_OBJ_WRITTEN(obj, Qundef, val); return 0; } if (!rb_shape_get_iv_index(shape, id, &index)) { index = shape->next_iv_index; if (index >= MAX_IVARS) { @@ -1487,31 +1572,20 @@ rb_obj_ivar_set(VALUE obj, ID id, VALUE val) if (UNLIKELY(shape->next_iv_index >= num_iv)) { RUBY_ASSERT(shape->next_iv_index == num_iv); - shape = rb_grow_iv_list(obj); RUBY_ASSERT(shape->type == SHAPE_CAPACITY_CHANGE); } - rb_shape_t *next_shape = rb_shape_get_next(shape, obj, id); if (next_shape->type == SHAPE_OBJ_TOO_COMPLEX) { - st_table * table = st_init_numtable_with_size(shape->next_iv_index); - - // Evacuate all previous values from shape into id_table - rb_ivar_foreach(obj, rb_obj_evacuate_ivs_to_hash_table, (st_data_t)table); - - // Insert new value too - st_insert(table, (st_data_t)id, (st_data_t)val); - RB_OBJ_WRITTEN(obj, Qundef, val); - - rb_shape_set_too_complex(obj); - RUBY_ASSERT(rb_shape_obj_too_complex(obj)); - - if (!(RBASIC(obj)->flags & ROBJECT_EMBED)) { - xfree(ROBJECT(obj)->as.heap.ivptr); - } - - ROBJECT(obj)->as.heap.ivptr = (VALUE *)table; - return 0; } else { @@ -1765,7 +1839,13 @@ class_ivar_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg) struct iv_itr_data itr_data; itr_data.obj = obj; itr_data.arg = arg; - iterate_over_shapes_with_callback(shape, func, &itr_data); } void @@ -3989,40 +4069,50 @@ int rb_class_ivar_set(VALUE obj, ID key, VALUE value) { RUBY_ASSERT(RB_TYPE_P(obj, T_CLASS) || RB_TYPE_P(obj, T_MODULE)); - int found; rb_check_frozen(obj); RB_VM_LOCK_ENTER(); { rb_shape_t * shape = rb_shape_get_shape(obj); - attr_index_t idx; - found = rb_shape_get_iv_index(shape, key, &idx); - - if (found) { - // Changing an existing instance variable - RUBY_ASSERT(RCLASS_IVPTR(obj)); - - RCLASS_IVPTR(obj)[idx] = value; - RB_OBJ_WRITTEN(obj, Qundef, value); } else { - // Creating and setting a new instance variable - // Move to a shape which fits the new ivar - idx = shape->next_iv_index; - shape = rb_shape_get_next(shape, obj, key); - // We always allocate a power of two sized IV array. This way we - // only need to realloc when we expand into a new power of two size - if ((idx & (idx - 1)) == 0) { - size_t newsize = idx ? idx * 2 : 1; - REALLOC_N(RCLASS_IVPTR(obj), VALUE, newsize); } - RUBY_ASSERT(RCLASS_IVPTR(obj)); - RB_OBJ_WRITE(obj, &RCLASS_IVPTR(obj)[idx], value); - rb_shape_set_shape(obj, shape); } } RB_VM_LOCK_LEAVE(); |