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

ruby-changes:13804

From: matz <ko1@a...>
Date: Sun, 1 Nov 2009 00:32:40 +0900 (JST)
Subject: [ruby-changes:13804] Ruby:r25601 (trunk): * vm_eval.c (check_funcall): logic updated according to

matz	2009-11-01 00:32:22 +0900 (Sun, 01 Nov 2009)

  New Revision: 25601

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

  Log:
    * vm_eval.c (check_funcall): logic updated according to
      [ruby-dev:39594].  search method entry, call if it exists;
      otherwise check method_missing, call if it was overridden,
      protecting exceptions; if NoMethodError happens, check method
      name.
    
    * vm_eval.c (vm_call0): use idMethodMissing.
    
    * vm_eval.c (rb_search_method_entry): typo fixed.

  Modified files:
    trunk/ChangeLog
    trunk/vm_eval.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 25600)
+++ ChangeLog	(revision 25601)
@@ -1,3 +1,15 @@
+Sat Oct 31 23:28:49 2009  Yukihiro Matsumoto  <matz@r...>
+
+	* vm_eval.c (check_funcall): logic updated according to
+	  [ruby-dev:39594].  search method entry, call if it exists;
+	  otherwise check method_missing, call if it was overridden,
+	  protecting exceptions; if NoMethodError happens, check method
+	  name.
+
+	* vm_eval.c (vm_call0): use idMethodMissing.
+
+	* vm_eval.c (rb_search_method_entry): typo fixed.
+
 Sat Oct 31 17:19:28 2009  NAKAMURA, Hiroshi  <nahi@r...>
 
 	* lib/net/http.rb (Net::HTTPResponse#each_response_header):
Index: vm_eval.c
===================================================================
--- vm_eval.c	(revision 25600)
+++ vm_eval.c	(revision 25601)
@@ -117,7 +117,7 @@
 
 	RB_GC_GUARD(new_args);
 	rb_ary_unshift(new_args, ID2SYM(id));
-	return rb_funcall2(recv, rb_intern("method_missing"),
+	return rb_funcall2(recv, idMethodMissing,
 			   argc+1, RARRAY_PTR(new_args));
       }
       case VM_METHOD_TYPE_OPTIMIZED: {
@@ -201,7 +201,7 @@
     }
 }
 
-static inline rb_method_entry_t *rb_search_method_emtry(VALUE recv, ID mid);
+static inline rb_method_entry_t *rb_search_method_entry(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
 
@@ -223,7 +223,7 @@
 rb_call0(VALUE recv, ID mid, int argc, const VALUE *argv,
 	 call_type scope, VALUE self)
 {
-    rb_method_entry_t *me = rb_search_method_emtry(recv, mid);
+    rb_method_entry_t *me = rb_search_method_entry(recv, mid);
     rb_thread_t *th = GET_THREAD();
     int call_status = rb_method_call_status(th, me, scope, self);
 
@@ -234,41 +234,81 @@
     return vm_call0(th, recv, mid, argc, argv, me);
 }
 
-VALUE
-rb_check_funcall(VALUE recv, ID mid, int argc, VALUE *argv)
+struct rescue_funcall_args {
+    VALUE recv;
+    VALUE sym;
+    int argc;
+    VALUE *argv;
+};
+
+static VALUE
+check_funcall_exec(struct rescue_funcall_args *args)
 {
-    rb_method_entry_t *me = rb_search_method_emtry(recv, mid);
+    VALUE new_args = rb_ary_new4(args->argc, args->argv);
+
+    RB_GC_GUARD(new_args);
+    rb_ary_unshift(new_args, args->sym);
+    return rb_funcall2(args->recv, idMethodMissing,
+		       args->argc+1, RARRAY_PTR(new_args));
+}
+
+static VALUE
+check_funcall_failed(struct rescue_funcall_args *args, VALUE e)
+{
+    VALUE sym = rb_funcall(e, rb_intern("name"), 0, 0);
+
+    if (args->sym != sym)
+	rb_exc_raise(e);
+    return Qundef;
+}
+
+static VALUE
+check_funcall(rb_method_entry_t *me, VALUE recv, ID mid, int argc, VALUE *argv)
+{
     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;
+	if (rb_method_basic_definition_p(CLASS_OF(recv), idMethodMissing)) {
+	    return Qundef;
+	}
+	else {
+	    struct rescue_funcall_args args;
+
+	    args.recv = recv;
+	    args.sym = ID2SYM(mid);
+	    args.argc = argc;
+	    args.argv = argv;
+	    return rb_rescue2(check_funcall_exec, (VALUE)&args,
+			      check_funcall_failed, (VALUE)&args,
+			      rb_eNoMethodError, (VALUE)0);
+	}
     }
     stack_check();
     return vm_call0(th, recv, mid, argc, argv, me);
 }
 
 VALUE
+rb_check_funcall(VALUE recv, ID mid, int argc, VALUE *argv)
+{
+    return check_funcall(rb_search_method_entry(recv, mid), recv, mid, argc, argv);
+}
+
+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();
+    rb_method_entry_t *me = rb_search_method_entry(recv, mid);
     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);
+    return check_funcall(me, recv, mid, argc, argv);
 }
 
 static inline rb_method_entry_t *
-rb_search_method_emtry(VALUE recv, ID mid)
+rb_search_method_entry(VALUE recv, ID mid)
 {
     VALUE klass = CLASS_OF(recv);
 

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

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