ruby-changes:51143
From: k0kubun <ko1@a...>
Date: Tue, 8 May 2018 01:17:04 +0900 (JST)
Subject: [ruby-changes:51143] k0kubun:r63350 (trunk): _mjit_compile_send.erb: inline recursive call
k0kubun 2018-05-08 01:16:59 +0900 (Tue, 08 May 2018) New Revision: 63350 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=63350 Log: _mjit_compile_send.erb: inline recursive call mjit_compile.c: propagate funcname to compile_insn test_jit.rb: add test covering this behavior * Benchmark ``` require 'benchmark_driver' Benchmark.driver(runner: :time, repeat_count: 4) do |x| x.prelude %{ def fib(x) return x if x == 0 || x == 1 fib(x-1) + fib(x-2) end } x.report 'fib(40)' x.loop_count 1 x.rbenv( 'before,--jit', 'before', 'after,--jit', 'after', ) x.verbose end ``` ``` before,--jit: ruby 2.6.0dev (2018-05-08 trunk 63349) +JIT [x86_64-linux] before: ruby 2.6.0dev (2018-05-08 trunk 63349) [x86_64-linux] after,--jit: ruby 2.6.0dev (2018-05-08 trunk 63349) +JIT [x86_64-linux] last_commit=_mjit_compile_send.erb: inline recursive call after: ruby 2.6.0dev (2018-05-08 trunk 63349) [x86_64-linux] last_commit=_mjit_compile_send.erb: inline recursive call Calculating ------------------------------------- before,--jit before after,--jit after fib(40) 2.886 8.685 2.562 8.800 s - 1.000 times Comparison: fib(40) after,--jit: 2.6 s before,--jit: 2.9 s - 1.13x slower before: 8.7 s - 3.39x slower after: 8.8 s - 3.44x slower ``` Modified files: trunk/mjit_compile.c trunk/test/ruby/test_jit.rb trunk/tool/ruby_vm/views/_mjit_compile_send.erb Index: mjit_compile.c =================================================================== --- mjit_compile.c (revision 63349) +++ mjit_compile.c (revision 63350) @@ -27,6 +27,7 @@ struct compile_status { https://github.com/ruby/ruby/blob/trunk/mjit_compile.c#L27 /* If TRUE, JIT-ed code will use local variables to store pushed values instead of using VM's stack and moving stack pointer. */ int local_stack_p; + const char *funcname; /* the method name which is being compiled */ }; /* Storage to keep data which is consistent in each conditional branch. @@ -193,6 +194,7 @@ mjit_compile(FILE *f, const struct rb_is https://github.com/ruby/ruby/blob/trunk/mjit_compile.c#L194 status.success = TRUE; status.local_stack_p = !body->catch_except_p; status.stack_size_for_pos = ALLOC_N(int, body->iseq_size); + status.funcname = funcname; memset(status.stack_size_for_pos, NOT_COMPILED_STACK_SIZE, sizeof(int) * body->iseq_size); /* For performance, we verify stack size only on compilation time (mjit_compile.inc.erb) without --jit-debug */ Index: tool/ruby_vm/views/_mjit_compile_send.erb =================================================================== --- tool/ruby_vm/views/_mjit_compile_send.erb (revision 63349) +++ tool/ruby_vm/views/_mjit_compile_send.erb (revision 63350) @@ -58,6 +58,9 @@ https://github.com/ruby/ruby/blob/trunk/tool/ruby_vm/views/_mjit_compile_send.erb#L58 fprintf(f, " VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);\n"); fprintf(f, " v = vm_exec(ec, TRUE);\n"); } + else if (body == iseq->body) { /* inline recursive call */ + fprintf(f, " v = %s(ec, ec->cfp);\n", status->funcname); + } else { fprintf(f, " if ((v = mjit_exec(ec)) == Qundef) {\n"); fprintf(f, " VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);\n"); /* This is vm_call0_body's code after vm_call_iseq_setup */ Index: test/ruby/test_jit.rb =================================================================== --- test/ruby/test_jit.rb (revision 63349) +++ test/ruby/test_jit.rb (revision 63350) @@ -322,6 +322,16 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L322 def test_compile_insn_opt_send_without_block assert_compile_once('print', result_inspect: 'nil', insns: %i[opt_send_without_block]) + + # recursive inline + assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '120', success_count: 1, min_calls: 2) + begin; + def fact(i) + return i if i <= 1 + i * fact(i - 1) + end + print fact(5) + end; end def test_compile_insn_invokesuper -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/