ruby-changes:58140
From: wanabe <ko1@a...>
Date: Sun, 6 Oct 2019 16:52:30 +0900 (JST)
Subject: [ruby-changes:58140] f62f90367f (master): tailcall optimization again (#2528)
https://git.ruby-lang.org/ruby.git/commit/?id=f62f90367f From f62f90367fc3bce6714e7c34cbd040e14e43fe07 Mon Sep 17 00:00:00 2001 From: wanabe <s.wanabe@g...> Date: Sun, 6 Oct 2019 16:52:09 +0900 Subject: tailcall optimization again (#2528) This is follow up of r67315. diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb index 6a9e960..0d4f692 100644 --- a/test/ruby/test_optimization.rb +++ b/test/ruby/test_optimization.rb @@ -451,6 +451,19 @@ class TestRubyOptimization < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_optimization.rb#L451 } end + def test_tailcall_not_to_grow_stack + bug16161 = '[ruby-core:94881]' + + tailcall("#{<<-"begin;"}\n#{<<~"end;"}") + begin; + def sum(n, s = 0) + return s if n < 1 + sum(n - 1, n + s) + end + end; + assert_equal(0, sum(1_000_000).to_s.size, message(bug16161) {disasm(:fact_helper)}) + end + class Bug10557 def [](_) block_given? diff --git a/vm_insnhelper.c b/vm_insnhelper.c index f9c825c..8e4e02e 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 https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1872 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, https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1982 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); -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/