diff options
author | nagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-03-20 15:53:38 +0000 |
---|---|---|
committer | nagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-03-20 15:53:38 +0000 |
commit | 9e7b5784180e29b258c99fd36639b5221d427287 (patch) | |
tree | e055f4d1e6d183fd14d11d20fd49bd3ce17f09f5 /proc.c | |
parent | ab2e7357bd27b5139415bf823c2780bc8273eb83 (diff) |
merge revision(s) 58245,60127: [Backport #13973]
Refactored using Method#owner.
proc.c: super_method of included method
* proc.c (method_super_method): search the next super method along
the included ancestor chain. [ruby-core:83114] [Bug #13973]
* vm_method.c (rb_callable_method_entry_without_refinements):
return the defined class.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_4@62865 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'proc.c')
-rw-r--r-- | proc.c | 37 |
1 files changed, 20 insertions, 17 deletions
@@ -29,6 +29,7 @@ const rb_cref_t *rb_vm_cref_in_context(VALUE self, VALUE cbase); struct METHOD { const VALUE recv; const VALUE klass; + const VALUE iclass; const rb_method_entry_t * const me; /* for bound methods, `me' should be rb_callable_method_entry_t * */ }; @@ -1326,6 +1327,7 @@ bm_mark(void *ptr) struct METHOD *data = ptr; rb_gc_mark(data->recv); rb_gc_mark(data->klass); + rb_gc_mark(data->iclass); rb_gc_mark((VALUE)data->me); } @@ -1393,7 +1395,7 @@ mnew_missing(VALUE klass, VALUE obj, ID id, VALUE mclass) } static VALUE -mnew_internal(const rb_method_entry_t *me, VALUE klass, +mnew_internal(const rb_method_entry_t *me, VALUE klass, VALUE iclass, VALUE obj, ID id, VALUE mclass, int scope, int error) { struct METHOD *data; @@ -1419,24 +1421,21 @@ mnew_internal(const rb_method_entry_t *me, VALUE klass, if (me->defined_class) { VALUE klass = RCLASS_SUPER(RCLASS_ORIGIN(me->defined_class)); id = me->def->original_id; - me = (rb_method_entry_t *)rb_callable_method_entry_without_refinements(klass, id); + me = (rb_method_entry_t *)rb_callable_method_entry_without_refinements(klass, id, &iclass); } else { VALUE klass = RCLASS_SUPER(me->owner); id = me->def->original_id; - me = rb_method_entry_without_refinements(klass, id); + me = rb_method_entry_without_refinements(klass, id, &iclass); } goto again; } - while (klass != me->owner && (FL_TEST(klass, FL_SINGLETON) || RB_TYPE_P(klass, T_ICLASS))) { - klass = RCLASS_SUPER(klass); - } - method = TypedData_Make_Struct(mclass, struct METHOD, &method_data_type, data); RB_OBJ_WRITE(method, &data->recv, obj); RB_OBJ_WRITE(method, &data->klass, klass); + RB_OBJ_WRITE(method, &data->iclass, iclass); RB_OBJ_WRITE(method, &data->me, me); OBJ_INFECT(method, klass); @@ -1444,24 +1443,25 @@ mnew_internal(const rb_method_entry_t *me, VALUE klass, } static VALUE -mnew_from_me(const rb_method_entry_t *me, VALUE klass, +mnew_from_me(const rb_method_entry_t *me, VALUE klass, VALUE iclass, VALUE obj, ID id, VALUE mclass, int scope) { - return mnew_internal(me, klass, obj, id, mclass, scope, TRUE); + return mnew_internal(me, klass, iclass, obj, id, mclass, scope, TRUE); } static VALUE mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope) { const rb_method_entry_t *me; + VALUE iclass = Qnil; if (obj == Qundef) { /* UnboundMethod */ - me = rb_method_entry_without_refinements(klass, id); + me = rb_method_entry_without_refinements(klass, id, &iclass); } else { - me = (rb_method_entry_t *)rb_callable_method_entry_without_refinements(klass, id); + me = (rb_method_entry_t *)rb_callable_method_entry_without_refinements(klass, id, &iclass); } - return mnew_from_me(me, klass, obj, id, mclass, scope); + return mnew_from_me(me, klass, iclass, obj, id, mclass, scope); } static inline VALUE @@ -1785,7 +1785,7 @@ rb_obj_singleton_method(VALUE obj, VALUE vid) vid = ID2SYM(id); goto undef; } - return mnew_from_me(me, klass, obj, id, rb_cMethod, FALSE); + return mnew_from_me(me, klass, klass, obj, id, rb_cMethod, FALSE); } /* @@ -2706,15 +2706,18 @@ static VALUE method_super_method(VALUE method) { const struct METHOD *data; - VALUE super_class; + VALUE super_class, iclass; + ID mid; const rb_method_entry_t *me; TypedData_Get_Struct(method, struct METHOD, &method_data_type, data); - super_class = RCLASS_SUPER(RCLASS_ORIGIN(method_entry_defined_class(data->me))); + iclass = data->iclass; + super_class = RCLASS_SUPER(RCLASS_ORIGIN(iclass)); + mid = data->me->called_id; if (!super_class) return Qnil; - me = (rb_method_entry_t *)rb_callable_method_entry_without_refinements(super_class, data->me->called_id); + me = (rb_method_entry_t *)rb_callable_method_entry_without_refinements(super_class, mid, &iclass); if (!me) return Qnil; - return mnew_internal(me, super_class, data->recv, data->me->called_id, rb_obj_class(method), FALSE, FALSE); + return mnew_internal(me, me->owner, iclass, data->recv, mid, rb_obj_class(method), FALSE, FALSE); } /* |