From 2f8a4d317f70f58e3008b2aa814e48a45c6427f6 Mon Sep 17 00:00:00 2001 From: nobu Date: Sat, 22 Aug 2015 06:43:14 +0000 Subject: vm_eval.c: cache results * vm_eval.c (check_funcall_failed, check_funcall_missing): cache results of respond_to? and respond_to_missing?, and search a pulibc method only for compatibility with rb_respond_to. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51665 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- vm_method.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'vm_method.c') diff --git a/vm_method.c b/vm_method.c index 50935ea740..9b9dd13751 100644 --- a/vm_method.c +++ b/vm_method.c @@ -1832,7 +1832,7 @@ basic_obj_respond_to_missing(rb_thread_t *th, VALUE klass, VALUE obj, const rb_method_entry_t *const me = method_entry_get(klass, rtmid, &defined_class); - if (!me || METHOD_ENTRY_BASIC(me)) return Qfalse; + if (!me || METHOD_ENTRY_BASIC(me)) return Qundef; args[0] = mid; args[1] = priv; return call_method_entry(th, defined_class, obj, rtmid, me, 2, args); @@ -1842,13 +1842,15 @@ static inline int basic_obj_respond_to(rb_thread_t *th, VALUE obj, ID id, int pub) { VALUE klass = CLASS_OF(obj); + VALUE ret; switch (rb_method_boundp(klass, id, pub|BOUND_RESPONDS)) { case 2: return FALSE; case 0: - return RTEST(basic_obj_respond_to_missing(th, klass, obj, ID2SYM(id), - pub ? Qfalse : Qtrue)); + ret = basic_obj_respond_to_missing(th, klass, obj, ID2SYM(id), + pub ? Qfalse : Qtrue); + return RTEST(ret) && ret != Qundef; default: return TRUE; } @@ -1864,7 +1866,7 @@ vm_respond_to(rb_thread_t *th, VALUE klass, VALUE obj, ID id, int priv) if (!me) return TRUE; if (METHOD_ENTRY_BASIC(me)) { - return basic_obj_respond_to(th, obj, id, !priv); + return -1; } else { int argc = 1; @@ -1908,7 +1910,11 @@ vm_respond_to(rb_thread_t *th, VALUE klass, VALUE obj, ID id, int priv) int rb_obj_respond_to(VALUE obj, ID id, int priv) { - return vm_respond_to(GET_THREAD(), CLASS_OF(obj), obj, id, priv); + rb_thread_t *th = GET_THREAD(); + VALUE klass = CLASS_OF(obj); + int ret = vm_respond_to(th, klass, obj, id, priv); + if (ret == -1) ret = basic_obj_respond_to(th, obj, id, !priv); + return ret; } int @@ -1947,8 +1953,10 @@ obj_respond_to(int argc, VALUE *argv, VALUE obj) rb_scan_args(argc, argv, "11", &mid, &priv); if (!(id = rb_check_id(&mid))) { - return basic_obj_respond_to_missing(th, CLASS_OF(obj), obj, - rb_to_symbol(mid), priv); + VALUE ret = basic_obj_respond_to_missing(th, CLASS_OF(obj), obj, + rb_to_symbol(mid), priv); + if (ret == Qundef) ret = Qfalse; + return ret; } if (basic_obj_respond_to(th, obj, id, !RTEST(priv))) return Qtrue; -- cgit v1.2.3