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

ruby-changes:25191

From: ko1 <ko1@a...>
Date: Wed, 17 Oct 2012 16:13:11 +0900 (JST)
Subject: [ruby-changes:25191] ko1:r37243 (trunk): * vm_insnhelper.c (vm_call_method_missing): make a refactoring

ko1	2012-10-17 16:12:40 +0900 (Wed, 17 Oct 2012)

  New Revision: 37243

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

  Log:
    * vm_insnhelper.c (vm_call_method_missing): make a refactoring
      about method_missing process. Use `vm_call_method()' to invoke
      `method_missing' method instead of `rb_funcall2()'.
      In `vm_call_method()', set fastpath to `vm_call_method_missing()'
      if it can be cached.
    * vm_core.h (rb_call_info_t): add new field
      `rb_call_info_t::aux::missing_reasion' to pass the reason to
      `vm_call_method_missing()'.

  Modified files:
    trunk/ChangeLog
    trunk/vm_core.h
    trunk/vm_insnhelper.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 37242)
+++ ChangeLog	(revision 37243)
@@ -1,3 +1,15 @@
+Wed Oct 17 16:03:54 2012  Koichi Sasada  <ko1@a...>
+
+	* vm_insnhelper.c (vm_call_method_missing): make a refactoring
+	  about method_missing process. Use `vm_call_method()' to invoke
+	  `method_missing' method instead of `rb_funcall2()'.
+	  In `vm_call_method()', set fastpath to `vm_call_method_missing()'
+	  if it can be cached.
+
+	* vm_core.h (rb_call_info_t): add new field
+	  `rb_call_info_t::aux::missing_reasion' to pass the reason to
+	  `vm_call_method_missing()'.
+
 Wed Oct 17 15:33:12 2012  Nobuyoshi Nakada  <nobu@r...>
 
 	* configure.in (opt-dir): allow multiple directories separated by
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 37242)
+++ vm_core.h	(revision 37243)
@@ -165,6 +165,7 @@
     union {
 	int opt_pc; /* used by iseq */
 	long index; /* used by ivar */
+	int missing_reason; /* used by method_missing */
     } aux;
 
     VALUE (*call)(struct rb_thread_struct *th, struct rb_control_frame_struct *cfp, struct rb_call_info_struct *ci);
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 37242)
+++ vm_insnhelper.c	(revision 37243)
@@ -1478,6 +1478,7 @@
 	}
 	ci->mid = rb_to_id(sym);
     }
+
     /* shift arguments */
     if (i > 0) {
 	MEMMOVE(&TOPN(i), &TOPN(i-1), VALUE, i);
@@ -1486,7 +1487,7 @@
     ci->argc -= 1;
     DEC_SP(1);
 
-    ci->flag |= VM_CALL_FCALL | VM_CALL_OPT_SEND;
+    ci->flag = VM_CALL_FCALL | VM_CALL_OPT_SEND;
 
     return vm_call_method(th, reg_cfp, ci);
 }
@@ -1520,27 +1521,28 @@
 }
 
 static VALUE
-vm_call_missing(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
+vm_call_method_missing(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci)
 {
-    VALUE *argv = ALLOCA_N(VALUE, ci->argc+1);
-    argv[0] = ID2SYM(ci->me->def->original_id);
-    MEMCPY(argv+1, cfp->sp - ci->argc, VALUE, ci->argc);
-    cfp->sp += - ci->argc - 1;
-    th->passed_block = ci->blockptr;
-    return rb_funcall2(ci->recv, rb_intern("method_missing"), ci->argc+1, argv);
-}
+    VALUE *argv = STACK_ADDR_FROM_TOP(ci->argc);
+    rb_call_info_t ci_entry;
 
-static VALUE
-vm_method_missing(rb_thread_t *th, rb_control_frame_t *const reg_cfp, rb_call_info_t *ci, int opt)
-{
-    VALUE ret, *argv = STACK_ADDR_FROM_TOP(ci->argc + 1);
+    ci_entry.flag = VM_CALL_FCALL | VM_CALL_OPT_SEND;
+    ci_entry.argc = ci->argc+1;
+    ci_entry.mid = idMethodMissing;
+    ci_entry.blockptr = ci->blockptr;
+    ci_entry.recv = ci->recv;
+    ci_entry.me = rb_method_entry(CLASS_OF(ci_entry.recv), idMethodMissing, &ci_entry.defined_class);
 
-    th->method_missing_reason = opt;
-    th->passed_block = ci->blockptr;
+    /* shift arguments: m(a, b, c) #=> method_missing(:m, a, b, c) */
+    CHECK_STACK_OVERFLOW(reg_cfp, 1);
+    if (ci->argc > 0) {
+	MEMMOVE(argv+1, argv, VALUE, ci->argc);
+    }
     argv[0] = ID2SYM(ci->mid);
-    ret = rb_funcall2(ci->recv, idMethodMissing, ci->argc + 1, argv);
-    POPN(ci->argc + 1);
-    return ret;
+    INC_SP(1);
+
+    th->method_missing_reason = ci->aux.missing_reason;
+    return vm_call_method(th, reg_cfp, &ci_entry);
 }
 
 static VALUE
@@ -1575,8 +1577,9 @@
 		return vm_call_ivar(th, cfp, ci);
 	      }
 	      case VM_METHOD_TYPE_MISSING:{
-		CI_SET_FASTPATH(ci, vm_call_missing, enable_fastpath);
-		return vm_call_missing(th, cfp, ci);
+		ci->aux.missing_reason = 0;
+		CI_SET_FASTPATH(ci, vm_call_method_missing, enable_fastpath);
+		return vm_call_method_missing(th, cfp, ci);
 	      }
 	      case VM_METHOD_TYPE_BMETHOD:{
 		CI_SET_FASTPATH(ci, vm_call_bmethod, enable_fastpath);
@@ -1638,12 +1641,15 @@
 		if (ci->flag & VM_CALL_VCALL) {
 		    stat |= NOEX_VCALL;
 		}
-		return vm_method_missing(th, cfp, ci, stat);
+		ci->aux.missing_reason = stat;
+		CI_SET_FASTPATH(ci, vm_call_method_missing, 1);
+		return vm_call_method_missing(th, cfp, ci);
 	    }
 	    else if (!(ci->flag & VM_CALL_OPT_SEND) && (ci->me->flag & NOEX_MASK) & NOEX_PROTECTED) {
 		enable_fastpath = 0;
 		if (!rb_obj_is_kind_of(cfp->self, ci->defined_class)) {
-		    return vm_method_missing(th, cfp, ci, NOEX_PROTECTED);
+		    ci->aux.missing_reason = NOEX_PROTECTED;
+		    return vm_call_method_missing(th, cfp, ci);
 		}
 		else {
 		    goto normal_method_dispatch;
@@ -1672,7 +1678,9 @@
 	    rb_raise_method_missing(th, ci->argc, argv, ci->recv, stat);
 	}
 	else {
-	    return vm_method_missing(th, cfp, ci, stat);
+	    ci->aux.missing_reason = stat;
+	    CI_SET_FASTPATH(ci, vm_call_method_missing, 1);
+	    return vm_call_method_missing(th, cfp, ci);
 	}
     }
 

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

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