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/