ruby-changes:39045
From: ko1 <ko1@a...>
Date: Fri, 3 Jul 2015 20:25:16 +0900 (JST)
Subject: [ruby-changes:39045] ko1:r51126 (trunk): * method.h: introduce rb_callable_method_entry_t to remove
ko1 2015-07-03 20:24:50 +0900 (Fri, 03 Jul 2015) New Revision: 51126 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=51126 Log: * method.h: introduce rb_callable_method_entry_t to remove rb_control_frame_t::klass. [Bug #11278], [Bug #11279] rb_method_entry_t data belong to modules/classes. rb_method_entry_t::owner points defined module or class. module M def foo; end end In this case, owner is M. rb_callable_method_entry_t data belong to only classes. For modules, MRI creates corresponding T_ICLASS internally. rb_callable_method_entry_t can also belong to T_ICLASS. rb_callable_method_entry_t::defined_class points T_CLASS or T_ICLASS. rb_method_entry_t data for classes (not for modules) are also rb_callable_method_entry_t data because it is completely same data. In this case, rb_method_entry_t::owner == rb_method_entry_t::defined_class. For example, there are classes C and D, and incldues M, class C; include M; end class D; include M; end then, two T_ICLASS objects for C's super class and D's super class will be created. When C.new.foo is called, then M#foo is searcheed and rb_callable_method_t data is used by VM to invoke M#foo. rb_method_entry_t data is only one for M#foo. However, rb_callable_method_entry_t data are two (and can be more). It is proportional to the number of including (and prepending) classes (the number of T_ICLASS which point to the module). Now, created rb_callable_method_entry_t are collected when the original module M was modified. We can think it is a cache. We need to select what kind of method entry data is needed. To operate definition, then you need to use rb_method_entry_t. You can access them by the following functions. * rb_method_entry(VALUE klass, ID id); * rb_method_entry_with_refinements(VALUE klass, ID id); * rb_method_entry_without_refinements(VALUE klass, ID id); * rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me); To invoke methods, then you need to use rb_callable_method_entry_t which you can get by the following APIs corresponding to the above listed functions. * rb_callable_method_entry(VALUE klass, ID id); * rb_callable_method_entry_with_refinements(VALUE klass, ID id); * rb_callable_method_entry_without_refinements(VALUE klass, ID id); * rb_resolve_refined_method_callable(VALUE refinements, const rb_callable_method_entry_t *me); VM pushes rb_callable_method_entry_t, so that rb_vm_frame_method_entry() returns rb_callable_method_entry_t. You can check a super class of current method by rb_callable_method_entry_t::defined_class. * method.h: renamed from rb_method_entry_t::klass to rb_method_entry_t::owner. * internal.h: add rb_classext_struct::callable_m_tbl to cache rb_callable_method_entry_t data. We need to consider abotu this field again because it is only active for T_ICLASS. * class.c (method_entry_i): ditto. * class.c (rb_define_attr): rb_method_entry() does not takes defiend_class_ptr. * gc.c (mark_method_entry): mark RCLASS_CALLABLE_M_TBL() for T_ICLASS. * cont.c (fiber_init): rb_control_frame_t::klass is removed. * proc.c: fix `struct METHOD' data structure because rb_callable_method_t has all information. * vm_core.h: remove several fields. * rb_control_frame_t::klass. * rb_block_t::klass. And catch up changes. * eval.c: catch up changes. * gc.c: ditto. * insns.def: ditto. * vm.c: ditto. * vm_args.c: ditto. * vm_backtrace.c: ditto. * vm_dump.c: ditto. * vm_eval.c: ditto. * vm_insnhelper.c: ditto. * vm_method.c: ditto. Modified files: trunk/ChangeLog trunk/class.c trunk/cont.c trunk/eval.c trunk/gc.c trunk/insns.def trunk/internal.h trunk/method.h trunk/proc.c trunk/vm.c trunk/vm_args.c trunk/vm_backtrace.c trunk/vm_core.h trunk/vm_dump.c trunk/vm_eval.c trunk/vm_insnhelper.c trunk/vm_method.c Index: method.h =================================================================== --- method.h (revision 51125) +++ method.h (revision 51126) @@ -47,12 +47,20 @@ typedef struct rb_cref_struct { https://github.com/ruby/ruby/blob/trunk/method.h#L47 typedef struct rb_method_entry_struct { VALUE flags; - VALUE dummy; + const VALUE defined_class; struct rb_method_definition_struct * const def; ID called_id; - const VALUE klass; /* should be marked */ + const VALUE owner; } rb_method_entry_t; +typedef struct rb_callable_method_entry_struct { /* same fields with rb_method_entry_t */ + VALUE flags; + const VALUE defined_class; + struct rb_method_definition_struct * const def; + ID called_id; + const VALUE owner; +} rb_callable_method_entry_t; + #define METHOD_ENTRY_VISI(me) (rb_method_visibility_t)(((me)->flags & (IMEMO_FL_USER0 | IMEMO_FL_USER1)) >> (IMEMO_FL_USHIFT+0)) #define METHOD_ENTRY_BASIC(me) (int) (((me)->flags & (IMEMO_FL_USER2 )) >> (IMEMO_FL_USHIFT+2)) #define METHOD_ENTRY_SAFE(me) (int) (((me)->flags & (IMEMO_FL_USER3 | IMEMO_FL_USER4)) >> (IMEMO_FL_USHIFT+3)) @@ -85,6 +93,13 @@ METHOD_ENTRY_FLAGS_SET(rb_method_entry_t https://github.com/ruby/ruby/blob/trunk/method.h#L93 (me->flags & ~(IMEMO_FL_USER0|IMEMO_FL_USER1|IMEMO_FL_USER2|IMEMO_FL_USER3|IMEMO_FL_USER4)) | ((visi << IMEMO_FL_USHIFT+0) | (basic << (IMEMO_FL_USHIFT+2)) | (safe << IMEMO_FL_USHIFT+3)); } +static inline void +METHOD_ENTRY_FLAGS_COPY(rb_method_entry_t *dst, const rb_method_entry_t *src) +{ + dst->flags = + (dst->flags & ~(IMEMO_FL_USER0|IMEMO_FL_USER1|IMEMO_FL_USER2|IMEMO_FL_USER3|IMEMO_FL_USER4)) | + (src->flags & (IMEMO_FL_USER0|IMEMO_FL_USER1|IMEMO_FL_USER2|IMEMO_FL_USER3|IMEMO_FL_USER4)); +} typedef enum { VM_METHOD_TYPE_ISEQ, @@ -127,6 +142,7 @@ typedef struct rb_method_alias_struct { https://github.com/ruby/ruby/blob/trunk/method.h#L142 typedef struct rb_method_refined_struct { const struct rb_method_entry_struct * const orig_me; + const VALUE owner; } rb_method_refined_t; typedef struct rb_method_definition_struct { @@ -159,20 +175,23 @@ typedef struct rb_method_definition_stru https://github.com/ruby/ruby/blob/trunk/method.h#L175 void rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_visibility_t visi); void rb_add_method_iseq(VALUE klass, ID mid, VALUE iseqval, rb_cref_t *cref, rb_method_visibility_t visi); -rb_method_entry_t *rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_visibility_t visi); -rb_method_entry_t *rb_method_entry(VALUE klass, ID id, VALUE *define_class_ptr); -rb_method_entry_t *rb_method_entry_at(VALUE obj, ID id); void rb_add_refined_method_entry(VALUE refined_class, ID mid); -const rb_method_entry_t *rb_resolve_refined_method(VALUE refinements, - const rb_method_entry_t *me, - VALUE *defined_class_ptr); -const rb_method_entry_t *rb_method_entry_with_refinements(VALUE klass, ID id, - VALUE *defined_class_ptr); -const rb_method_entry_t *rb_method_entry_without_refinements(VALUE klass, ID id, - VALUE *defined_class_ptr); -rb_method_entry_t *rb_method_entry_get_without_cache(VALUE klass, ID id, VALUE *define_class_ptr); +rb_method_entry_t *rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_visibility_t visi); rb_method_entry_t *rb_method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *, rb_method_visibility_t noex); +rb_method_entry_t *rb_method_entry_create(ID called_id, VALUE klass, rb_method_visibility_t visi, const rb_method_definition_t *def); + +const rb_method_entry_t *rb_method_entry_at(VALUE obj, ID id); + +const rb_method_entry_t *rb_method_entry(VALUE klass, ID id); +const rb_method_entry_t *rb_method_entry_with_refinements(VALUE klass, ID id); +const rb_method_entry_t *rb_method_entry_without_refinements(VALUE klass, ID id); +const rb_method_entry_t *rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me); + +const rb_callable_method_entry_t *rb_callable_method_entry(VALUE klass, ID id); +const rb_callable_method_entry_t *rb_callable_method_entry_with_refinements(VALUE klass, ID id); +const rb_callable_method_entry_t *rb_callable_method_entry_without_refinements(VALUE klass, ID id); +const rb_callable_method_entry_t *rb_resolve_refined_method_callable(VALUE refinements, const rb_callable_method_entry_t *me); int rb_method_entry_arity(const rb_method_entry_t *me); int rb_method_entry_eq(const rb_method_entry_t *m1, const rb_method_entry_t *m2); @@ -185,8 +204,8 @@ VALUE rb_obj_method_location(VALUE obj, https://github.com/ruby/ruby/blob/trunk/method.h#L204 void rb_free_method_entry(const rb_method_entry_t *me); void rb_sweep_method_entry(void *vm); -rb_method_entry_t *rb_method_entry_create(ID called_id, VALUE klass, rb_method_visibility_t visi, const rb_method_definition_t *def); -rb_method_entry_t *rb_method_entry_clone(const rb_method_entry_t *me); +const rb_method_entry_t *rb_method_entry_clone(const rb_method_entry_t *me); +const rb_callable_method_entry_t *rb_method_entry_complement_defined_class(const rb_method_entry_t *src_me, VALUE defined_class); void rb_method_entry_copy(rb_method_entry_t *dst, const rb_method_entry_t *src); void rb_scope_visibility_set(rb_method_visibility_t); Index: insns.def =================================================================== --- insns.def (revision 51125) +++ insns.def (revision 51126) @@ -914,8 +914,7 @@ defineclass https://github.com/ruby/ruby/blob/trunk/insns.def#L914 } /* enter scope */ - vm_push_frame(th, class_iseq, VM_FRAME_MAGIC_CLASS, - klass, 0, + vm_push_frame(th, class_iseq, VM_FRAME_MAGIC_CLASS, klass, VM_ENVVAL_BLOCK_PTR(GET_BLOCK_PTR()), (VALUE)vm_cref_push(th, klass, NULL), class_iseq->iseq_encoded, GET_SP(), Index: ChangeLog =================================================================== --- ChangeLog (revision 51125) +++ ChangeLog (revision 51126) @@ -1,3 +1,118 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Fri Jul 03 20:05:10 2015 Koichi Sasada <ko1@a...> + + * method.h: introduce rb_callable_method_entry_t to remove + rb_control_frame_t::klass. + [Bug #11278], [Bug #11279] + + rb_method_entry_t data belong to modules/classes. + rb_method_entry_t::owner points defined module or class. + + module M + def foo; end + end + + In this case, owner is M. + + rb_callable_method_entry_t data belong to only classes. + For modules, MRI creates corresponding T_ICLASS internally. + rb_callable_method_entry_t can also belong to T_ICLASS. + + rb_callable_method_entry_t::defined_class points T_CLASS or + T_ICLASS. + rb_method_entry_t data for classes (not for modules) are also + rb_callable_method_entry_t data because it is completely same data. + In this case, rb_method_entry_t::owner == rb_method_entry_t::defined_class. + + For example, there are classes C and D, and incldues M, + + class C; include M; end + class D; include M; end + + then, two T_ICLASS objects for C's super class and D's super class + will be created. + + When C.new.foo is called, then M#foo is searcheed and + rb_callable_method_t data is used by VM to invoke M#foo. + + rb_method_entry_t data is only one for M#foo. + However, rb_callable_method_entry_t data are two (and can be more). + It is proportional to the number of including (and prepending) + classes (the number of T_ICLASS which point to the module). + + Now, created rb_callable_method_entry_t are collected when + the original module M was modified. We can think it is a cache. + + We need to select what kind of method entry data is needed. + To operate definition, then you need to use rb_method_entry_t. + + You can access them by the following functions. + + * rb_method_entry(VALUE klass, ID id); + * rb_method_entry_with_refinements(VALUE klass, ID id); + * rb_method_entry_without_refinements(VALUE klass, ID id); + * rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me); + + To invoke methods, then you need to use rb_callable_method_entry_t + which you can get by the following APIs corresponding to the + above listed functions. + + * rb_callable_method_entry(VALUE klass, ID id); + * rb_callable_method_entry_with_refinements(VALUE klass, ID id); + * rb_callable_method_entry_without_refinements(VALUE klass, ID id); + * rb_resolve_refined_method_callable(VALUE refinements, const rb_callable_method_entry_t *me); + + VM pushes rb_callable_method_entry_t, so that rb_vm_frame_method_entry() + returns rb_callable_method_entry_t. + You can check a super class of current method by + rb_callable_method_entry_t::defined_class. + + * method.h: renamed from rb_method_entry_t::klass to + rb_method_entry_t::owner. + + * internal.h: add rb_classext_struct::callable_m_tbl to cache + rb_callable_method_entry_t data. + + We need to consider abotu this field again because it is only + active for T_ICLASS. + + * class.c (method_entry_i): ditto. + + * class.c (rb_define_attr): rb_method_entry() does not takes + defiend_class_ptr. + + * gc.c (mark_method_entry): mark RCLASS_CALLABLE_M_TBL() for T_ICLASS. + + * cont.c (fiber_init): rb_control_frame_t::klass is removed. + + * proc.c: fix `struct METHOD' data structure because + rb_callable_method_t has all information. + + * vm_core.h: remove several fields. + * rb_control_frame_t::klass. + * rb_block_t::klass. + + And catch up changes. + + * eval.c: catch up changes. + + * gc.c: ditto. + + * insns.def: ditto. + + * vm.c: ditto. + + * vm_args.c: ditto. + + * vm_backtrace.c: ditto. + + * vm_dump.c: ditto. + + * vm_eval.c: ditto. + + * vm_insnhelper.c: ditto. + + * vm_method.c: ditto. + Fri Jul 3 14:30:18 2015 Nobuyoshi Nakada <nobu@r...> * win32/file.c: some mingw compilers need a tweek for the Index: vm_core.h =================================================================== --- vm_core.h (revision 51125) +++ vm_core.h (revision 51126) @@ -183,8 +183,7 @@ typedef struct rb_call_info_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L183 VALUE klass; /* inline cache: values */ - const rb_method_entry_t *me; - VALUE defined_class; + const rb_callable_method_entry_t *me; /* temporary values for method calling */ struct rb_block_struct *blockptr; @@ -524,7 +523,7 @@ typedef struct rb_vm_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L523 #endif #ifndef VM_DEBUG_VERIFY_METHOD_CACHE -#define VM_DEBUG_VERIFY_METHOD_CACHE 0 +#define VM_DEBUG_VERIFY_METHOD_CACHE (VM_DEBUG_MODE != 0) #endif typedef struct rb_control_frame_struct { @@ -533,10 +532,9 @@ typedef struct rb_control_frame_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L532 rb_iseq_t *iseq; /* cfp[2] */ VALUE flag; /* cfp[3] */ VALUE self; /* cfp[4] / block[0] */ - VALUE klass; /* cfp[5] / block[1] */ - VALUE *ep; /* cfp[6] / block[2] */ - rb_iseq_t *block_iseq; /* cfp[7] / block[3] */ - VALUE proc; /* cfp[8] / block[4] */ + VALUE *ep; /* cfp[6] / block[1] */ + rb_iseq_t *block_iseq; /* cfp[7] / block[2] */ + VALUE proc; /* cfp[8] / block[3] */ #if VM_DEBUG_BP_CHECK VALUE *bp_check; /* cfp[9] */ @@ -545,7 +543,6 @@ typedef struct rb_control_frame_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L543 typedef struct rb_block_struct { VALUE self; /* share with method frame if it's only block */ - VALUE klass; /* share with method frame if it's only block */ VALUE *ep; /* share with method frame if it's only block */ rb_iseq_t *iseq; VALUE proc; @@ -631,7 +628,7 @@ typedef struct rb_thread_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L628 const rb_block_t *passed_block; /* for bmethod */ - const rb_method_entry_t *passed_bmethod_me; + const rb_callable_method_entry_t *passed_bmethod_me; /* for cfunc */ rb_call_info_t *passed_ci; @@ -976,8 +973,7 @@ VALUE *rb_binding_add_dynavars(rb_bindin https://github.com/ruby/ruby/blob/trunk/vm_core.h#L973 void rb_vm_inc_const_missing_count(void); void rb_vm_gvl_destroy(rb_vm_t *vm); VALUE rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc, - const VALUE *argv, const rb_method_entry_t *me, - VALUE defined_class); + const VALUE *argv, const rb_callable_method_entry_t *me); void rb_thread_start_timer_thread(void); void rb_thread_stop_timer_thread(int); @@ -1024,7 +1020,7 @@ int rb_autoloading_value(VALUE mod, ID i https://github.com/ruby/ruby/blob/trunk/vm_core.h#L1020 void rb_vm_rewrite_cref(rb_cref_t *node, VALUE old_klass, VALUE new_klass, rb_cref_t **new_cref_ptr); -const rb_method_entry_t *rb_vm_frame_method_entry(const rb_control_frame_t *cfp); +const rb_callable_method_entry_t *rb_vm_frame_method_entry(const rb_control_frame_t *cfp); #define sysstack_error GET_VM()->special_exceptions[ruby_error_sysstack] Index: vm_eval.c =================================================================== --- vm_eval.c (revision 51125) +++ vm_eval.c (revision 51126) @@ -42,15 +42,13 @@ static VALUE send_internal(int argc, con https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L42 static VALUE vm_call0_body(rb_thread_t* th, rb_call_info_t *ci, const VALUE *argv); static VALUE -vm_call0(rb_thread_t* th, VALUE recv, ID id, int argc, const VALUE *argv, - const rb_method_entry_t *me, VALUE defined_class) +vm_call0(rb_thread_t* th, VALUE recv, ID id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me) { rb_call_info_t ci_entry, *ci = &ci_entry; ci->flag = 0; ci->mid = id; ci->recv = recv; - ci->defined_class = defined_class; ci->argc = argc; ci->me = me; ci->kw_arg = NULL; @@ -64,11 +62,11 @@ vm_call0_cfunc(rb_thread_t* th, rb_call_ https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L62 { VALUE val; - RUBY_DTRACE_CMETHOD_ENTRY_HOOK(th, ci->defined_class, ci->mid); - EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, ci->recv, ci->mid, ci->defined_class, Qnil); + RUBY_DTRACE_CMETHOD_ENTRY_HOOK(th, ci->me->owner, ci->mid); + EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, ci->recv, ci->mid, ci->me->owner, Qnil); { rb_control_frame_t *reg_cfp = th->cfp; - const rb_method_entry_t *me = ci->me; + const rb_callable_method_entry_t *me = ci->me; const rb_method_cfunc_t *cfunc = &me->def->body.cfunc; int len = cfunc->argc; VALUE recv = ci->recv; @@ -95,8 +93,8 @@ vm_call0_cfunc(rb_thread_t* th, rb_call_ https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L93 vm_pop_frame(th); } } - EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, ci->recv, ci->mid, ci->defined_class, val); - RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, ci->defined_class, ci->mid); + EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, ci->recv, ci->mid, ci->me->owner, val); + RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, ci->me->owner, ci->mid); return val; } @@ -105,21 +103,20 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L103 vm_call0_cfunc_with_frame(rb_thread_t* th, rb_call_info_t *ci, const VALUE *argv) { VALUE val; - const rb_method_entry_t *me = ci->me; + const rb_callable_method_entry_t *me = ci->me; const rb_method_cfunc_t *cfunc = &me->def->body.cfunc; int len = cfunc->argc; VALUE recv = ci->recv; - VALUE defined_class = ci->defined_class; int argc = ci->argc; ID mid = ci->mid; rb_block_t *blockptr = ci->blockptr; - RUBY_DTRACE_CMETHOD_ENTRY_HOOK(th, defined_class, mid); - EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, mid, defined_class, Qnil); + RUBY_DTRACE_CMETHOD_ENTRY_HOOK(th, me->owner, mid); + EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, mid, me->owner, Qnil); { rb_control_frame_t *reg_cfp = th->cfp; - vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, recv, defined_class, + vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, recv, VM_ENVVAL_BLOCK_PTR(blockptr), (VALUE)me, 0, reg_cfp->sp, 1, 0); @@ -134,8 +131,8 @@ vm_call0_cfunc_with_frame(rb_thread_t* t https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L131 VM_PROFILE_UP(3); vm_pop_frame(th); } - EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, mid, defined_class, val); - RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, defined_class, mid); + EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, mid, me->owner, val); + RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, me->owner, mid); return val; } @@ -198,14 +195,16 @@ vm_call0_body(rb_thread_t* th, rb_call_i https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L195 case VM_METHOD_TYPE_REFINED: { const rb_method_type_t type = ci->me->def->type; + VALUE super_class; + if (type == VM_METHOD_TYPE_REFINED && ci->me->def->body.refined.orig_me) { - ci->me = ci->me->def->body.refined.orig_me; + ci->me = refined_method_callable_without_refinement(ci->me); goto again; } - ci->defined_class = RCLASS_SUPER(ci->defined_class); + super_class = RCLASS_SUPER(ci->me->defined_class); - if (!ci->defined_class || !(ci->me = rb_method_entry(ci->defined_class, ci->mid, &ci->defined_class))) { + if (!super_class || !(ci->me = rb_callable_method_entry(super_class, ci->mid))) { enum method_missing_reason ex = (type == VM_METHOD_TYPE_ZSUPER) ? MISSING_SUPER : 0; ret = method_missing(ci->recv, ci->mid, ci->argc, argv, ex); goto success; @@ -214,11 +213,8 @@ vm_call0_body(rb_thread_t* th, rb_call_i https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L213 goto again; } case VM_METHOD_TYPE_ALIAS: - { - ci->me = ci->me->def->body.alias.original_me; - ci->defined_class = find_defined_class_by_owner(ci->defined_class, ci->me->klass); - goto again; - } + ci->me = aliased_callable_method_entry(ci->me); + goto again; case VM_METHOD_TYPE_MISSING: { VALUE new_args = rb_ary_new4(ci->argc, argv); @@ -258,10 +254,9 @@ vm_call0_body(rb_thread_t* th, rb_call_i https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L254 } VALUE -rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc, const VALUE *argv, - const rb_method_entry_t *me, VALUE defined_class) +rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me) { - return vm_call0(th, recv, id, argc, argv, me, defined_class); + return vm_call0(th, recv, id, argc, argv, me); } static inline VALUE @@ -270,22 +265,24 @@ vm_call_super(rb_thread_t *th, int argc, https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L265 VALUE recv = th->cfp->self; VALUE klass; ID id; - rb_method_entry_t *me; rb_control_frame_t *cfp = th->cfp; + const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp); - if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq) || NIL_P(cfp->klass)) { + if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { rb_bug("vm_call_super: should not be reached"); } - klass = RCLASS_ORIGIN(cfp->klass); + klass = RCLASS_ORIGIN(me->defined_class); klass = RCLASS_SUPER(klass); - id = rb_vm_frame_method_entry(cfp)->def->original_id; - me = rb_method_entry(klass, id, &klass); + id = me->def->original_id; + me = rb_callable_method_entry(klass, id); + if (!me) { return method_missing(recv, id, argc, argv, MISSING_SUPER); } - - return vm_call0(th, recv, id, argc, argv, me, klass); + else { + return vm_call0(th, recv, id, argc, argv, me); + } } VALUE @@ -316,9 +313,8 @@ stack_check(void) https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L313 } } -static inline rb_method_entry_t * - rb_search_method_entry(VALUE recv, ID mid, VALUE *defined_class_ptr); -static inline enum method_missing_reason rb_method_call_status(rb_thread_t *th, const rb_method_entry_t *me, call_type scope, VALUE se (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/