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

ruby-changes:25179

From: ko1 <ko1@a...>
Date: Wed, 17 Oct 2012 06:20:25 +0900 (JST)
Subject: [ruby-changes:25179] ko1:r37231 (trunk): * vm_insnhelper.c (vm_call_iseq_setup_2): separate tailcall and normal

ko1	2012-10-17 06:20:11 +0900 (Wed, 17 Oct 2012)

  New Revision: 37231

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

  Log:
    * vm_insnhelper.c (vm_call_iseq_setup_2): separate tailcall and normal
      method frame setup functions.
      Add checking interrupts at the tailcall setup function.

  Modified files:
    trunk/ChangeLog
    trunk/vm_insnhelper.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 37230)
+++ ChangeLog	(revision 37231)
@@ -1,3 +1,9 @@
+Wed Oct 17 06:17:44 2012  Koichi Sasada  <ko1@a...>
+
+	* vm_insnhelper.c (vm_call_iseq_setup_2): separate tailcall and normal
+	  method frame setup functions.
+	  Add checking interrupts at the tailcall setup function.
+
 Wed Oct 17 05:35:37 2012  Koichi Sasada  <ko1@a...>
 
 	* benchmark/bm_vm1_yield.rb: add a benchmark to measure `yield'
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 37230)
+++ vm_insnhelper.c	(revision 37231)
@@ -1199,6 +1199,8 @@
 }
 
 static VALUE vm_call_iseq_setup_2(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci);
+static VALUE vm_call_iseq_setup_normal(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci);
+static VALUE vm_call_iseq_setup_tailcall(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci);
 
 #define VM_CALLEE_SETUP_ARG(th, ci, iseq, argv, is_lambda) \
     if (LIKELY((iseq)->arg_simple & 0x01)) { \
@@ -1207,7 +1209,7 @@
 	    argument_error((iseq), ((ci)->argc), (iseq)->argc, (iseq)->argc); \
 	} \
 	(ci)->aux.opt_pc = 0; \
-	CI_SET_FASTPATH((ci), vm_call_iseq_setup_2, !(is_lambda) && !((ci)->me->flag & NOEX_PROTECTED)); \
+	CI_SET_FASTPATH((ci), UNLIKELY((ci)->flag & VM_CALL_TAILCALL) ? vm_call_iseq_setup_tailcall : vm_call_iseq_setup_normal, !(is_lambda) && !((ci)->me->flag & NOEX_PROTECTED)); \
     } \
     else { \
 	(ci)->aux.opt_pc = vm_callee_setup_arg_complex((th), (ci), (iseq), (argv)); \
@@ -1223,56 +1225,73 @@
 static VALUE
 vm_call_iseq_setup_2(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
 {
+    if (LIKELY(!(ci->flag & VM_CALL_TAILCALL))) {
+	return vm_call_iseq_setup_normal(th, cfp, ci);
+    }
+    else {
+	return vm_call_iseq_setup_tailcall(th, cfp, ci);
+    }
+}
+
+static VALUE
+vm_call_iseq_setup_normal(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
+{
     int i;
     VALUE *argv = cfp->sp - ci->argc;
     rb_iseq_t *iseq = ci->me->def->body.iseq;
+    VALUE *sp = argv + iseq->arg_size;
 
-    /* stack overflow check */
     CHECK_STACK_OVERFLOW(cfp, iseq->stack_max);
 
-    if (LIKELY(!(ci->flag & VM_CALL_TAILCALL))) {
-	VALUE *sp = argv + iseq->arg_size;
+    /* clear local variables */
+    for (i = 0; i < iseq->local_size - iseq->arg_size; i++) {
+	*sp++ = Qnil;
+    }
 
-	/* clear local variables */
-	for (i = 0; i < iseq->local_size - iseq->arg_size; i++) {
-	    *sp++ = Qnil;
-	}
+    vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, ci->recv, ci->defined_class,
+		  VM_ENVVAL_BLOCK_PTR(ci->blockptr),
+		  iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, ci->me);
 
-	vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, ci->recv, ci->defined_class,
-		      VM_ENVVAL_BLOCK_PTR(ci->blockptr),
-		      iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, ci->me);
+    cfp->sp = argv - 1 /* recv */;
+    return Qundef;
+}
 
-	cfp->sp = argv - 1 /* recv */;
-    }
-    else {
-	VALUE *src_argv = argv;
-	VALUE *sp_orig, *sp;
-	VALUE finish_flag = VM_FRAME_TYPE_FINISH_P(cfp) ? VM_FRAME_FLAG_FINISH : 0;
+static VALUE
+vm_call_iseq_setup_tailcall(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
+{
+    int i;
+    VALUE *argv = cfp->sp - ci->argc;
+    rb_iseq_t *iseq = ci->me->def->body.iseq;
+    VALUE *src_argv = argv;
+    VALUE *sp_orig, *sp;
+    VALUE finish_flag = VM_FRAME_TYPE_FINISH_P(cfp) ? VM_FRAME_FLAG_FINISH : 0;
 
-	cfp = th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); /* pop cf */
-	sp_orig = sp = cfp->sp;
+    cfp = th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); /* pop cf */
 
-	/* push self */
-	sp[0] = ci->recv;
-	sp++;
+    CHECK_STACK_OVERFLOW(cfp, iseq->stack_max);
+    RUBY_VM_CHECK_INTS(th);
 
-	/* copy arguments */
-	for (i=0; i < iseq->arg_size; i++) {
-	    *sp++ = src_argv[i];
-	}
+    sp_orig = sp = cfp->sp;
 
-	/* clear local variables */
-	for (i = 0; i < iseq->local_size - iseq->arg_size; i++) {
-	    *sp++ = Qnil;
-	}
+    /* push self */
+    sp[0] = ci->recv;
+    sp++;
 
-	vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD | finish_flag,
-		      ci->recv, ci->defined_class, VM_ENVVAL_BLOCK_PTR(ci->blockptr),
-		      iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, ci->me);
+    /* copy arguments */
+    for (i=0; i < iseq->arg_size; i++) {
+	*sp++ = src_argv[i];
+    }
 
-	cfp->sp = sp_orig;
+    /* clear local variables */
+    for (i = 0; i < iseq->local_size - iseq->arg_size; i++) {
+	*sp++ = Qnil;
     }
 
+    vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD | finish_flag,
+		  ci->recv, ci->defined_class, VM_ENVVAL_BLOCK_PTR(ci->blockptr),
+		  iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, ci->me);
+
+    cfp->sp = sp_orig;
     return Qundef;
 }
 

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

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