[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]