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

ruby-changes:13775

From: nobu <ko1@a...>
Date: Fri, 30 Oct 2009 16:43:30 +0900 (JST)
Subject: [ruby-changes:13775] Ruby:r25572 (trunk): * vm_eval.c (rb_search_method_emtry, rb_method_call_status): split

nobu	2009-10-30 16:42:04 +0900 (Fri, 30 Oct 2009)

  New Revision: 25572

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=25572

  Log:
    * vm_eval.c (rb_search_method_emtry, rb_method_call_status): split
      from rb_call0().
    
    * vm_eval.c (rb_check_funcall): get rid of raising exceptions and
      hiding further exceptions.  [ruby-dev:39584]
    
    * vm_eval.c (rb_funcall_no_recursive): ditto.

  Modified files:
    trunk/ChangeLog
    trunk/test/ruby/test_array.rb
    trunk/test/ruby/test_rubyoptions.rb
    trunk/test/ruby/test_string.rb
    trunk/vm_eval.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 25571)
+++ ChangeLog	(revision 25572)
@@ -1,3 +1,13 @@
+Fri Oct 30 16:42:03 2009  Nobuyoshi Nakada  <nobu@r...>
+
+	* vm_eval.c (rb_search_method_emtry, rb_method_call_status): spli
+	  from rb_call0().
+
+	* vm_eval.c (rb_check_funcall): get rid of raising exceptions and
+	  hiding further exceptions.  [ruby-dev:39584]
+
+	* vm_eval.c (rb_funcall_no_recursive): ditto.
+
 Fri Oct 30 13:36:39 2009  Nobuyoshi Nakada  <nobu@r...>
 
 	* thread.c (rb_thread_blocking_region): reverted r25566, and added
Index: vm_eval.c
===================================================================
--- vm_eval.c	(revision 25571)
+++ vm_eval.c	(revision 25572)
@@ -199,6 +199,10 @@
     }
 }
 
+static inline rb_method_entry_t *rb_search_method_emtry(VALUE recv, ID mid);
+static inline int rb_method_call_status(rb_thread_t *th, rb_method_entry_t *me, call_type scope, VALUE self);
+#define NOEX_OK NOEX_NOSUPER
+
 /*!
  * \internal
  * calls the specified method.
@@ -217,13 +221,55 @@
 rb_call0(VALUE recv, ID mid, int argc, const VALUE *argv,
 	 call_type scope, VALUE self)
 {
-    VALUE klass = CLASS_OF(recv);
-    rb_method_entry_t *me;
-    struct cache_entry *ent;
+    rb_method_entry_t *me = rb_search_method_emtry(recv, mid);
     rb_thread_t *th = GET_THREAD();
-    ID oid;
-    int noex;
+    int call_status = rb_method_call_status(th, me, scope, self);
 
+    if (call_status != NOEX_OK) {
+	return method_missing(recv, mid, argc, argv, call_status);
+    }
+    stack_check();
+    return vm_call0(th, recv, mid, argc, argv, me);
+}
+
+VALUE
+rb_check_funcall(VALUE recv, ID mid, int argc, VALUE *argv)
+{
+    rb_method_entry_t *me = rb_search_method_emtry(recv, mid);
+    rb_thread_t *th = GET_THREAD();
+    int call_status = rb_method_call_status(th, me, CALL_FCALL, Qundef);
+
+    if (call_status != NOEX_OK) {
+	return Qundef;
+    }
+    stack_check();
+    return vm_call0(th, recv, mid, argc, argv, me);
+}
+
+VALUE
+rb_funcall_no_recursive(VALUE recv, ID mid, int argc, VALUE *argv, VALUE (*func)())
+{
+    rb_method_entry_t *me = rb_search_method_emtry(recv, mid);
+    rb_thread_t *th = GET_THREAD();
+    int call_status;
+
+    if (!me) return Qundef;
+    if (me->def && me->def->type == VM_METHOD_TYPE_CFUNC &&
+	me->def->body.cfunc.func == func)
+	return Qundef;
+    call_status = rb_method_call_status(th, me, CALL_FCALL, Qundef);
+    if (call_status != NOEX_OK) {
+	return Qundef;
+    }
+    stack_check();
+    return vm_call0(th, recv, mid, argc, argv, me);
+}
+
+static inline rb_method_entry_t *
+rb_search_method_emtry(VALUE recv, ID mid)
+{
+    VALUE klass = CLASS_OF(recv);
+
     if (!klass) {
         const char *adj = "terminated";
         if (!IMMEDIATE_P(recv) && RBASIC(recv)->flags != 0)
@@ -232,29 +278,20 @@
 		 "method `%s' called on %s object (%p)",
 		 rb_id2name(mid), adj, (void *)recv);
     }
+    return rb_method_entry(klass, mid);
+}
 
-    /* is it in the method cache? */
-    ent = cache + EXPR1(klass, mid);
+static inline int
+rb_method_call_status(rb_thread_t *th, rb_method_entry_t *me, call_type scope, VALUE self)
+{
+    VALUE klass;
+    ID oid;
+    int noex;
 
-    if (ent->mid == mid && ent->klass == klass) {
-	me = ent->me;
-	if (UNDEFINED_METHOD_ENTRY_P(me)) {
-	    return method_missing(recv, mid, argc, argv,
-				  scope == CALL_VCALL ? NOEX_VCALL : 0);
-	}
-	klass = me->klass;
+    if (UNDEFINED_METHOD_ENTRY_P(me)) {
+	return scope == CALL_VCALL ? NOEX_VCALL : 0;
     }
-    else if ((me = rb_method_entry_without_cache(klass, mid)) != 0 && me->def) {
-	klass = me->klass;
-    }
-    else {
-	if (scope == 3) {
-	    return method_missing(recv, mid, argc, argv, NOEX_SUPER);
-	}
-	return method_missing(recv, mid, argc, argv,
-			      scope == CALL_VCALL ? NOEX_VCALL : 0);
-    }
-
+    klass = me->klass;
     oid = me->def->original_id;
     noex = me->flag;
 
@@ -262,7 +299,7 @@
 	/* receiver specified form for private method */
 	if (UNLIKELY(noex)) {
 	    if (((noex & NOEX_MASK) & NOEX_PRIVATE) && scope == CALL_PUBLIC) {
-		return method_missing(recv, mid, argc, argv, NOEX_PRIVATE);
+		return NOEX_PRIVATE;
 	    }
 
 	    /* self must be kind of a specified form for protected method */
@@ -277,18 +314,17 @@
 		    self = th->cfp->self;
 		}
 		if (!rb_obj_is_kind_of(self, rb_class_real(defined_class))) {
-		    return method_missing(recv, mid, argc, argv, NOEX_PROTECTED);
+		    return NOEX_PROTECTED;
 		}
 	    }
 
 	    if (NOEX_SAFE(noex) > th->safe_level) {
-		rb_raise(rb_eSecurityError, "calling insecure method: %s", rb_id2name(mid));
+		rb_raise(rb_eSecurityError, "calling insecure method: %s",
+			 rb_id2name(me->called_id));
 	    }
 	}
     }
-
-    stack_check();
-    return vm_call0(th, recv, mid, argc, argv, me);
+    return NOEX_OK;
 }
 
 
@@ -536,49 +572,7 @@
     return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
 }
 
-struct rescue_funcall_args {
-    VALUE obj;
-    ID id;
-    int argc;
-    VALUE *argv;
-};
-
 static VALUE
-check_funcall(struct rescue_funcall_args *args)
-{
-    return rb_funcall2(args->obj, args->id, args->argc, args->argv);
-}
-
-static VALUE
-check_failed(VALUE data)
-{
-    return data;
-}
-
-VALUE
-rb_check_funcall(VALUE obj, ID id, int argc, VALUE *argv)
-{
-    struct rescue_funcall_args args;
-
-    args.obj = obj;
-    args.id = id;
-    args.argc = argc;
-    args.argv = argv;
-    return rb_rescue2(check_funcall, (VALUE)&args, check_failed, Qundef,
-		      rb_eNoMethodError, (VALUE)0);
-}
-
-VALUE
-rb_funcall_no_recursive(VALUE obj, ID id, int argc, VALUE *argv, VALUE (*func)())
-{
-    const rb_method_entry_t *me = rb_method_entry(CLASS_OF(obj), id);
-    if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC &&
-	me->def->body.cfunc.func == func)
-	return Qundef;
-    return rb_check_funcall(obj, id, argc, argv);
-}
-
-static VALUE
 send_internal(int argc, const VALUE *argv, VALUE recv, int scope)
 {
     VALUE vid;
Index: test/ruby/test_array.rb
===================================================================
--- test/ruby/test_array.rb	(revision 25571)
+++ test/ruby/test_array.rb	(revision 25572)
@@ -1224,6 +1224,18 @@
     if (@cls == Array)
       assert_equal(a_id, a.to_ary.__id__)
     end
+
+    o = Object.new
+    def o.to_ary
+      [4, 5]
+    end
+    assert_equal([1, 2, 3, 4, 5], a.concat(o))
+
+    o = Object.new
+    def o.to_ary
+      foo_bar()
+    end
+    assert_match(/foo_bar/, assert_raise(NoMethodError) {a.concat(o)}.message)
   end
 
   def test_to_s
Index: test/ruby/test_string.rb
===================================================================
--- test/ruby/test_string.rb	(revision 25571)
+++ test/ruby/test_string.rb	(revision 25572)
@@ -1408,6 +1408,18 @@
     a = S("me")
     assert_equal("me", a.to_s)
     assert_equal(a.__id__, a.to_s.__id__) if @cls == String
+
+    o = Object.new
+    def o.to_str
+      "at"
+    end
+    assert_equal("meat", a.concat(o))
+
+    o = Object.new
+    def o.to_str
+      foo_bar()
+    end
+    assert_match(/foo_bar/, assert_raise(NoMethodError) {a.concat(o)}.message)
   end
 
   def test_tr
Index: test/ruby/test_rubyoptions.rb
===================================================================
--- test/ruby/test_rubyoptions.rb	(revision 25571)
+++ test/ruby/test_rubyoptions.rb	(revision 25572)
@@ -53,9 +53,9 @@
   end
 
   def test_debug
-    assert_in_out_err(%w(-de) + ["p $DEBUG"], "", %w(true), //)
+    assert_in_out_err(%w(-de) + ["p $DEBUG"], "", %w(true), [])
 
-    assert_in_out_err(%w(--debug -e) + ["p $DEBUG"], "", %w(true), //)
+    assert_in_out_err(%w(--debug -e) + ["p $DEBUG"], "", %w(true), [])
   end
 
   def test_verbose

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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