aboutsummaryrefslogtreecommitdiffstats
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
authorwanabe <s.wanabe@gmail.com>2019-10-06 16:52:09 +0900
committerKoichi Sasada <ko1@atdot.net>2019-10-06 16:52:09 +0900
commitf62f90367fc3bce6714e7c34cbd040e14e43fe07 (patch)
tree3aefe411a803886588329f0ed6d728fac26ff734 /vm_insnhelper.c
parent6525d3bcc7d0be65e2ff97d6785d9f36b5e4988a (diff)
downloadruby-f62f90367fc3bce6714e7c34cbd040e14e43fe07.tar.gz
tailcall optimization again (#2528)
This is follow up of r67315.
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c37
1 files changed, 34 insertions, 3 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index f9c825c272..8e4e02ee90 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1872,6 +1872,30 @@ vm_call_iseq_setup_normal_opt_start(rb_execution_context_t *ec, rb_control_frame
return vm_call_iseq_setup_normal(ec, cfp, calling, cc->me, opt_pc, param - delta, local);
}
+static VALUE
+vm_call_iseq_setup_tailcall_opt_start(rb_execution_context_t *ec, rb_control_frame_t *cfp,
+ struct rb_calling_info *calling,
+ const struct rb_call_info *ci, struct rb_call_cache *cc)
+{
+ const rb_iseq_t *iseq = def_iseq_ptr(cc->me->def);
+ const int lead_num = iseq->body->param.lead_num;
+ const int opt = calling->argc - lead_num;
+ const int opt_pc = (int)iseq->body->param.opt_table[opt];
+
+ RB_DEBUG_COUNTER_INC(ccf_iseq_opt);
+
+#if USE_OPT_HIST
+ if (opt_pc < OPT_HIST_MAX) {
+ opt_hist[opt]++;
+ }
+ else {
+ opt_hist[OPT_HIST_MAX]++;
+ }
+#endif
+
+ return vm_call_iseq_setup_tailcall(ec, cfp, calling, ci, cc, opt_pc);
+}
+
static void
args_setup_kw_parameters(rb_execution_context_t *const ec, const rb_iseq_t *const iseq,
VALUE *const passed_values, const int passed_keyword_len, const VALUE *const passed_keywords,
@@ -1958,9 +1982,16 @@ vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling,
argument_arity_error(ec, iseq, argc, lead_num, lead_num + opt_num);
}
- CC_SET_FASTPATH(cc, vm_call_iseq_setup_normal_opt_start,
- !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) &&
- !(METHOD_ENTRY_VISI(cc->me) == METHOD_VISI_PROTECTED));
+ if (LIKELY(!(ci->flag & VM_CALL_TAILCALL))) {
+ CC_SET_FASTPATH(cc, vm_call_iseq_setup_normal_opt_start,
+ !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) &&
+ !(METHOD_ENTRY_VISI(cc->me) == METHOD_VISI_PROTECTED));
+ }
+ else {
+ CC_SET_FASTPATH(cc, vm_call_iseq_setup_tailcall_opt_start,
+ !IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) &&
+ !(METHOD_ENTRY_VISI(cc->me) == METHOD_VISI_PROTECTED));
+ }
/* initialize opt vars for self-references */
VM_ASSERT((int)iseq->body->param.size == lead_num + opt_num);