diff options
Diffstat (limited to 'variable.c')
-rw-r--r-- | variable.c | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/variable.c b/variable.c index 0f71b27418..745ace528f 100644 --- a/variable.c +++ b/variable.c @@ -1566,22 +1566,41 @@ rb_ivar_defined(VALUE obj, ID id) typedef int rb_ivar_foreach_callback_func(ID key, VALUE val, st_data_t arg); st_data_t rb_st_nth_key(st_table *tab, st_index_t index); +struct iv_itr_data { + VALUE obj; + struct gen_ivtbl * ivtbl; + st_data_t arg; +}; + static void -iterate_over_shapes_with_callback(rb_shape_t *shape, VALUE* iv_list, rb_ivar_foreach_callback_func *callback, st_data_t arg) +iterate_over_shapes_with_callback(rb_shape_t *shape, rb_ivar_foreach_callback_func *callback, struct iv_itr_data * itr_data) { switch ((enum shape_type)shape->type) { case SHAPE_ROOT: return; case SHAPE_IVAR: - iterate_over_shapes_with_callback(rb_shape_get_shape_by_id(shape->parent_id), iv_list, callback, arg); + iterate_over_shapes_with_callback(rb_shape_get_shape_by_id(shape->parent_id), callback, itr_data); + VALUE * iv_list; + switch(BUILTIN_TYPE(itr_data->obj)) { + case T_OBJECT: + iv_list = ROBJECT_IVPTR(itr_data->obj); + break; + case T_CLASS: + case T_MODULE: + iv_list = RCLASS_IVPTR(itr_data->obj); + break; + default: + iv_list = itr_data->ivtbl->ivptr; + break; + } VALUE val = iv_list[shape->next_iv_index - 1]; if (val != Qundef) { - callback(shape->edge_name, val, arg); + callback(shape->edge_name, val, itr_data->arg); } return; case SHAPE_IVAR_UNDEF: case SHAPE_FROZEN: - iterate_over_shapes_with_callback(rb_shape_get_shape_by_id(shape->parent_id), iv_list, callback, arg); + iterate_over_shapes_with_callback(rb_shape_get_shape_by_id(shape->parent_id), callback, itr_data); return; } } @@ -1590,7 +1609,10 @@ static void obj_ivar_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg) { rb_shape_t* shape = rb_shape_get_shape(obj); - iterate_over_shapes_with_callback(shape, ROBJECT_IVPTR(obj), func, arg); + struct iv_itr_data itr_data; + itr_data.obj = obj; + itr_data.arg = arg; + iterate_over_shapes_with_callback(shape, func, &itr_data); } static void @@ -1600,7 +1622,11 @@ gen_ivar_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg) struct gen_ivtbl *ivtbl; if (!rb_gen_ivtbl_get(obj, 0, &ivtbl)) return; - iterate_over_shapes_with_callback(shape, ivtbl->ivptr, func, arg); + struct iv_itr_data itr_data; + itr_data.obj = obj; + itr_data.ivtbl = ivtbl; + itr_data.arg = arg; + iterate_over_shapes_with_callback(shape, func, &itr_data); } static void @@ -1609,7 +1635,10 @@ class_ivar_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg) RUBY_ASSERT(RB_TYPE_P(obj, T_CLASS) || RB_TYPE_P(obj, T_MODULE)); rb_shape_t* shape = rb_shape_get_shape(obj); - iterate_over_shapes_with_callback(shape, RCLASS_IVPTR(obj), func, 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 |