ruby-changes:39566
From: nobu <ko1@a...>
Date: Thu, 20 Aug 2015 22:19:45 +0900 (JST)
Subject: [ruby-changes:39566] nobu:r51647 (trunk): vm_eval.c: redefined respond_to_missing?
nobu 2015-08-20 22:19:21 +0900 (Thu, 20 Aug 2015) New Revision: 51647 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=51647 Log: vm_eval.c: redefined respond_to_missing? * vm_method.c (basic_obj_respond_to): call respond_to_missing? only when redefined. [ruby-core:70460] [Bug #11465] Modified files: trunk/ChangeLog trunk/vm_method.c Index: ChangeLog =================================================================== --- ChangeLog (revision 51646) +++ ChangeLog (revision 51647) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Thu Aug 20 22:19:17 2015 Nobuyoshi Nakada <nobu@r...> + + * vm_method.c (basic_obj_respond_to): call respond_to_missing? + only when redefined. [ruby-core:70460] [Bug #11465] + Thu Aug 20 14:13:27 2015 Nobuyoshi Nakada <nobu@r...> * vm_eval.c (check_funcall_respond_to): share the behavior with Index: vm_method.c =================================================================== --- vm_method.c (revision 51646) +++ vm_method.c (revision 51647) @@ -1811,19 +1811,44 @@ rb_method_basic_definition_p(VALUE klass https://github.com/ruby/ruby/blob/trunk/vm_method.c#L1811 return (me && METHOD_ENTRY_BASIC(me)) ? TRUE : FALSE; } +static VALUE +call_method_entry(rb_thread_t *th, VALUE defined_class, VALUE obj, ID id, + const rb_method_entry_t *me, int argc, const VALUE *argv) +{ + const rb_callable_method_entry_t *cme = + prepare_callable_method_entry(defined_class, id, me); + const rb_block_t *passed_block = th->passed_block; + VALUE result = vm_call0(th, obj, id, argc, argv, cme); + th->passed_block = passed_block; + return result; +} + +static VALUE +basic_obj_respond_to_missing(rb_thread_t *th, VALUE klass, VALUE obj, + VALUE mid, VALUE priv) +{ + VALUE defined_class, args[2]; + const ID rtmid = idRespond_to_missing; + const rb_method_entry_t *const me = + method_entry_get(klass, rtmid, &defined_class); + + if (!me || METHOD_ENTRY_BASIC(me)) return Qfalse; + args[0] = mid; + args[1] = priv; + return call_method_entry(th, defined_class, obj, rtmid, me, 2, args); +} + static inline int -basic_obj_respond_to(VALUE obj, ID id, int pub) +basic_obj_respond_to(rb_thread_t *th, VALUE obj, ID id, int pub) { VALUE klass = CLASS_OF(obj); - VALUE args[2]; switch (rb_method_boundp(klass, id, pub|BOUND_RESPONDS)) { case 2: return FALSE; case 0: - args[0] = ID2SYM(id); - args[1] = pub ? Qfalse : Qtrue; - return RTEST(rb_funcall2(obj, idRespond_to_missing, 2, args)); + return RTEST(basic_obj_respond_to_missing(th, klass, obj, ID2SYM(id), + pub ? Qfalse : Qtrue)); default: return TRUE; } @@ -1837,16 +1862,14 @@ vm_respond_to(rb_thread_t *th, VALUE kla https://github.com/ruby/ruby/blob/trunk/vm_method.c#L1862 const rb_method_entry_t *const me = method_entry_get(klass, resid, &defined_class); - if (!me) return FALSE; + if (!me) return TRUE; if (METHOD_ENTRY_BASIC(me)) { - return basic_obj_respond_to(obj, id, !priv); + return basic_obj_respond_to(th, obj, id, !priv); } else { int argc = 1; VALUE args[2]; VALUE result; - const rb_callable_method_entry_t *cme; - const rb_block_t *passed_block = th->passed_block; args[0] = ID2SYM(id); args[1] = Qtrue; @@ -1877,9 +1900,7 @@ vm_respond_to(rb_thread_t *th, VALUE kla https://github.com/ruby/ruby/blob/trunk/vm_method.c#L1900 } } } - cme = prepare_callable_method_entry(defined_class, resid, me); - result = vm_call0(th, obj, resid, argc, args, cme); - th->passed_block = passed_block; + result = call_method_entry(th, defined_class, obj, resid, me, argc, args); return RTEST(result); } } @@ -1922,18 +1943,14 @@ obj_respond_to(int argc, VALUE *argv, VA https://github.com/ruby/ruby/blob/trunk/vm_method.c#L1943 { VALUE mid, priv; ID id; + rb_thread_t *th = GET_THREAD(); rb_scan_args(argc, argv, "11", &mid, &priv); if (!(id = rb_check_id(&mid))) { - if (!rb_method_basic_definition_p(CLASS_OF(obj), idRespond_to_missing)) { - VALUE args[2]; - args[0] = rb_to_symbol(mid); - args[1] = priv; - return rb_funcall2(obj, idRespond_to_missing, 2, args); - } - return Qfalse; + return basic_obj_respond_to_missing(th, CLASS_OF(obj), obj, + rb_to_symbol(mid), priv); } - if (basic_obj_respond_to(obj, id, !RTEST(priv))) + if (basic_obj_respond_to(th, obj, id, !RTEST(priv))) return Qtrue; return Qfalse; } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/