diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-10-16 21:20:11 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-10-16 21:20:11 +0000 |
commit | ddb6408f6ef338310065a87cd32b9ed3afbe9c46 (patch) | |
tree | 3066053886011dcddbf31b2b96be6d08bbf1b75c /vm_insnhelper.c | |
parent | db3898fe905cf19a65ba8edfe13774a3613943fc (diff) |
* vm_insnhelper.c (vm_call_iseq_setup_2): separate tailcall and normal
method frame setup functions.
Add checking interrupts at the tailcall setup function.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37231 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r-- | vm_insnhelper.c | 87 |
1 files changed, 53 insertions, 34 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 072f446f95..2786399ad0 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1199,6 +1199,8 @@ vm_callee_setup_arg_complex(rb_thread_t *th, rb_call_info_t *ci, const rb_iseq_t } 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 @@ static VALUE vm_call_iseq_setup_2(rb_thread_t *th, rb_control_frame_t *cfp, rb_c 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 @@ vm_call_iseq_setup(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci) 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; } |