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

ruby-changes:25146

From: ko1 <ko1@a...>
Date: Tue, 16 Oct 2012 06:24:22 +0900 (JST)
Subject: [ruby-changes:25146] ko1:r37198 (trunk): * method.h: introduce new method type VM_METHOD_TYPE_CFUNC_FAST.

ko1	2012-10-16 06:24:08 +0900 (Tue, 16 Oct 2012)

  New Revision: 37198

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

  Log:
    * method.h: introduce new method type VM_METHOD_TYPE_CFUNC_FAST.
      This method is similar to VM_METHOD_TYPE_CFUNC methods, but
      called cfunc without building new frame (does not push new control
      frame). If error is occured in cfunc, the backtrace only shows
      caller frame and upper.
      This kind of methods can be added by rb_define_method_fast().
      This feature is similar to specialized instructions (opt_plus, etc),
      but more flexible (but a bit slower).
    * class.c (rb_define_method_fast): added.
      Maybe it will be renamed soon.
    * vm_insnhelper.c (vm_call_method): support method type
      VM_METHOD_TYPE_CFUNC_FAST.
    * proc.c (rb_method_entry_arity): catch up new method type.
    * vm_method.c (rb_add_method_cfunc_fast): added.

  Modified files:
    trunk/ChangeLog
    trunk/class.c
    trunk/method.h
    trunk/proc.c
    trunk/vm_insnhelper.c
    trunk/vm_method.c

Index: method.h
===================================================================
--- method.h	(revision 37197)
+++ method.h	(revision 37198)
@@ -41,7 +41,8 @@
     VM_METHOD_TYPE_UNDEF,
     VM_METHOD_TYPE_NOTIMPLEMENTED,
     VM_METHOD_TYPE_OPTIMIZED, /* Kernel#send, Proc#call, etc */
-    VM_METHOD_TYPE_MISSING   /* wrapper for method_missing(id) */
+    VM_METHOD_TYPE_MISSING,   /* wrapper for method_missing(id) */
+    VM_METHOD_TYPE_CFUNC_FAST
 } rb_method_type_t;
 
 typedef struct rb_method_cfunc_struct {
@@ -66,7 +67,7 @@
 	VALUE proc;                 /* should be mark */
 	enum method_optimized_type {
 	    OPTIMIZED_METHOD_TYPE_SEND,
-	    OPTIMIZED_METHOD_TYPE_CALL
+	    OPTIMIZED_METHOD_TYPE_CALL,
 	} optimize_type;
     } body;
     int alias_count;
@@ -88,6 +89,7 @@
 #define UNDEFINED_METHOD_ENTRY_P(me) (!(me) || !(me)->def || (me)->def->type == VM_METHOD_TYPE_UNDEF)
 
 void rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex);
+void rb_add_method_cfunc_fast(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex);
 rb_method_entry_t *rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_flag_t noex);
 rb_method_entry_t *rb_method_entry(VALUE klass, ID id, VALUE *define_class_ptr);
 
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 37197)
+++ ChangeLog	(revision 37198)
@@ -1,3 +1,24 @@
+Tue Oct 16 06:15:44 2012  Koichi Sasada  <ko1@a...>
+
+	* method.h: introduce new method type VM_METHOD_TYPE_CFUNC_FAST.
+	  This method is similar to VM_METHOD_TYPE_CFUNC methods, but
+	  called cfunc without building new frame (does not push new control
+	  frame). If error is occured in cfunc, the backtrace only shows
+	  caller frame and upper.
+	  This kind of methods can be added by rb_define_method_fast().
+	  This feature is similar to specialized instructions (opt_plus, etc),
+	  but more flexible (but a bit slower).
+
+	* class.c (rb_define_method_fast): added.
+	  Maybe it will be renamed soon.
+
+	* vm_insnhelper.c (vm_call_method): support method type
+	  VM_METHOD_TYPE_CFUNC_FAST.
+
+	* proc.c (rb_method_entry_arity): catch up new method type.
+
+	* vm_method.c (rb_add_method_cfunc_fast): added.
+
 Tue Oct 16 02:32:29 2012  Koichi Sasada  <ko1@a...>
 
 	* vm_insnhelper.h (CI_SET_FASTPATH): add new parameter `enabled'.
Index: proc.c
===================================================================
--- proc.c	(revision 37197)
+++ proc.c	(revision 37198)
@@ -1656,6 +1656,7 @@
     const rb_method_definition_t *def = me->def;
     if (!def) return 0;
     switch (def->type) {
+      case VM_METHOD_TYPE_CFUNC_FAST:
       case VM_METHOD_TYPE_CFUNC:
 	if (def->body.cfunc.argc < 0)
 	    return -1;
Index: vm_method.c
===================================================================
--- vm_method.c	(revision 37197)
+++ vm_method.c	(revision 37198)
@@ -96,6 +96,20 @@
 }
 
 void
+rb_add_method_cfunc_fast(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex)
+{
+    if (func != rb_f_notimplement) {
+	rb_method_cfunc_t opt;
+	opt.func = func;
+	opt.argc = argc;
+	rb_add_method(klass, mid, VM_METHOD_TYPE_CFUNC_FAST, &opt, noex);
+    }
+    else {
+	rb_define_notimplement_method_id(klass, mid, noex);
+    }
+}
+
+void
 rb_unlink_method_entry(rb_method_entry_t *me)
 {
     struct unlinked_method_entry_list_entry *ume = ALLOC(struct unlinked_method_entry_list_entry);
@@ -304,6 +318,7 @@
 	def->body.iseq = (rb_iseq_t *)opts;
 	break;
       case VM_METHOD_TYPE_CFUNC:
+      case VM_METHOD_TYPE_CFUNC_FAST:
 	def->body.cfunc = *(rb_method_cfunc_t *)opts;
 	break;
       case VM_METHOD_TYPE_ATTRSET:
Index: class.c
===================================================================
--- class.c	(revision 37197)
+++ class.c	(revision 37198)
@@ -1254,6 +1254,12 @@
 }
 
 void
+rb_define_method_fast(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
+{
+    rb_add_method_cfunc_fast(klass, rb_intern(name), func, argc, NOEX_PUBLIC);
+}
+
+void
 rb_define_protected_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
 {
     rb_add_method_cfunc(klass, rb_intern(name), func, argc, NOEX_PROTECTED);
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 37197)
+++ vm_insnhelper.c	(revision 37198)
@@ -1462,6 +1462,21 @@
 }
 
 static VALUE
+vm_call_cfunc_fast_unary(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
+{
+    cfp->sp -= 1;
+    return (*ci->me->def->body.cfunc.func)(ci->recv);
+}
+
+static VALUE
+vm_call_cfunc_fast_binary(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
+{
+    VALUE obj = *cfp->sp;
+    cfp->sp -= 2;
+    return (*ci->me->def->body.cfunc.func)(ci->recv, obj);
+}
+
+static VALUE
 vm_call_missing(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
 {
     VALUE *argv = ALLOCA_N(VALUE, ci->argc+1);
@@ -1544,24 +1559,38 @@
 	      }
 	      case VM_METHOD_TYPE_OPTIMIZED:{
 		switch (ci->me->def->body.optimize_type) {
-		  case OPTIMIZED_METHOD_TYPE_SEND: {
+		  case OPTIMIZED_METHOD_TYPE_SEND:
 		    CI_SET_FASTPATH(ci, vm_call_opt_send, enable_fastpath);
 		    val = vm_call_opt_send(th, cfp, ci);
 		    break;
-		  }
-		  case OPTIMIZED_METHOD_TYPE_CALL: {
+		  case OPTIMIZED_METHOD_TYPE_CALL:
 		    CI_SET_FASTPATH(ci, vm_call_opt_call, enable_fastpath);
 		    val = vm_call_opt_call(th, cfp, ci);
 		    break;
-		  }
 		  default:
-		    rb_bug("eval_invoke_method: unsupported optimized method type (%d)",
+		    rb_bug("vm_call_method: unsupported optimized method type (%d)",
 			   ci->me->def->body.optimize_type);
 		}
 		break;
 	      }
+	      case VM_METHOD_TYPE_CFUNC_FAST:
+		switch (ci->me->def->body.cfunc.argc) {
+		  case 0:
+		    rb_check_arity(ci->argc, 0, 0);
+		    CI_SET_FASTPATH(ci, vm_call_cfunc_fast_unary, enable_fastpath);
+		    val = vm_call_cfunc_fast_unary(th, cfp, ci);
+		    break;
+		  case 1:
+		    rb_check_arity(ci->argc, 0, 1);
+		    CI_SET_FASTPATH(ci, vm_call_cfunc_fast_binary, enable_fastpath);
+		    val = vm_call_cfunc_fast_binary(th, cfp, ci);
+		    break;
+		  default:
+		    rb_bug("vm_call_method: unsupported cfunc_fast argc (%d)", ci->me->def->body.cfunc.argc);
+		}
+		break;
 	      default:{
-		rb_bug("eval_invoke_method: unsupported method type (%d)", ci->me->def->type);
+		rb_bug("vm_call_method: unsupported method type (%d)", ci->me->def->type);
 		break;
 	      }
 	    }

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

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