aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--method.h1
-rw-r--r--proc.c6
-rw-r--r--vm_method.c17
4 files changed, 21 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index bda3d75a66..2baa5eba62 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Thu Aug 20 08:53:09 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * vm_method.c (rb_obj_respond_to): reuse found method entry
+ instead of searching same entry repeatedly.
+
Thu Aug 20 08:31:17 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
* dir.c (replace_real_basename), win32/win32.c (opendir_internal):
diff --git a/method.h b/method.h
index 71dc2c088b..982b1e3b7d 100644
--- a/method.h
+++ b/method.h
@@ -197,6 +197,7 @@ 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);
st_index_t rb_hash_method_entry(st_index_t hash, const rb_method_entry_t *me);
+VALUE rb_method_entry_location(const rb_method_entry_t *me);
VALUE rb_mod_method_location(VALUE mod, ID id);
VALUE rb_obj_method_location(VALUE obj, ID id);
diff --git a/proc.c b/proc.c
index 0d8ae11f09..1ca975193b 100644
--- a/proc.c
+++ b/proc.c
@@ -2249,8 +2249,8 @@ method_def_location(const rb_method_definition_t *def)
return iseq_location(method_def_iseq(def));
}
-static VALUE
-method_entry_location(const rb_method_entry_t *me)
+VALUE
+rb_method_entry_location(const rb_method_entry_t *me)
{
if (!me) return Qnil;
return method_def_location(me->def);
@@ -2260,7 +2260,7 @@ VALUE
rb_mod_method_location(VALUE mod, ID id)
{
const rb_method_entry_t *me = original_method_entry(mod, id);
- return method_entry_location(me);
+ return rb_method_entry_location(me);
}
VALUE
diff --git a/vm_method.c b/vm_method.c
index f03d312d97..fd000fa95a 100644
--- a/vm_method.c
+++ b/vm_method.c
@@ -1833,22 +1833,28 @@ int
rb_obj_respond_to(VALUE obj, ID id, int priv)
{
VALUE klass = CLASS_OF(obj);
+ VALUE defined_class;
+ const ID resid = idRespond_to;
+ const rb_method_entry_t *const me =
+ method_entry_get(klass, resid, &defined_class);
- if (rb_method_basic_definition_p(klass, idRespond_to)) {
+ if (!me) return FALSE;
+ if (METHOD_ENTRY_BASIC(me)) {
return basic_obj_respond_to(obj, id, !priv);
}
else {
int argc = 1;
VALUE args[2];
+ const rb_callable_method_entry_t *cme;
+
args[0] = ID2SYM(id);
args[1] = Qtrue;
if (priv) {
- if (rb_obj_method_arity(obj, idRespond_to) != 1) {
+ if (rb_method_entry_arity(me) != 1) {
argc = 2;
}
else if (!NIL_P(ruby_verbose)) {
- VALUE klass = CLASS_OF(obj);
- VALUE location = rb_mod_method_location(klass, idRespond_to);
+ VALUE location = rb_method_entry_location(me);
rb_warn("%"PRIsVALUE"%c""respond_to?(:%"PRIsVALUE") is"
" old fashion which takes only one parameter",
(FL_TEST(klass, FL_SINGLETON) ? obj : klass),
@@ -1864,7 +1870,8 @@ rb_obj_respond_to(VALUE obj, ID id, int priv)
}
}
}
- return RTEST(rb_funcall2(obj, idRespond_to, argc, args));
+ cme = prepare_callable_method_entry(defined_class, resid, me);
+ return RTEST(vm_call0(GET_THREAD(), obj, resid, argc, args, cme));
}
}