aboutsummaryrefslogtreecommitdiffstats
path: root/vm_method.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-08-22 06:43:14 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-08-22 06:43:14 +0000
commit2f8a4d317f70f58e3008b2aa814e48a45c6427f6 (patch)
tree64a820e245dd16ff0aa32c4412a666ef0e585ffe /vm_method.c
parent1f557eaea15d96b4b16ac1d25ea98ee58d062912 (diff)
downloadruby-2f8a4d317f70f58e3008b2aa814e48a45c6427f6.tar.gz
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
Diffstat (limited to 'vm_method.c')
-rw-r--r--vm_method.c22
1 files changed, 15 insertions, 7 deletions
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;