diff options
author | Takashi Kokubun <takashikkbn@gmail.com> | 2020-03-31 21:58:01 -0700 |
---|---|---|
committer | Takashi Kokubun <takashikkbn@gmail.com> | 2020-03-31 22:10:16 -0700 |
commit | 151f8be40d385ada2ebf7feb84210ed7db7ef4df (patch) | |
tree | 80dce1c63a4afdc84217a1495423b7e931b0fc96 | |
parent | 5a81562dfed2d5839e28b654d4f0f69de632aa8e (diff) | |
download | ruby-151f8be40d385ada2ebf7feb84210ed7db7ef4df.tar.gz |
Make JIT-ed leave insn leaf
to eliminate sp / pc moves by cancelling JIT execution on interrupts.
$ benchmark-driver benchmark.yml -v --rbenv 'before --jit;after --jit' --repeat-count=12 --output=all
before --jit: ruby 2.8.0dev (2020-04-01T03:48:56Z master 5a81562dfe) +JIT [x86_64-linux]
after --jit: ruby 2.8.0dev (2020-04-01T04:58:01Z master 39beb26a27) +JIT [x86_64-linux]
Calculating -------------------------------------
before --jit after --jit
Optcarrot Lan_Master.nes 75.06409603894944 76.06422026555558 fps
75.12025067279242 78.48161731616810
77.42020273492177 79.78958240950033
79.07253675128945 79.88645902325614
79.99179109732327 80.33743931749331
80.07633091008627 80.53790081529166
80.15450942667547 80.99048270668010
80.48372803283709 81.70497146081003
80.57410149187352 82.79494539467382
81.80449157081202 82.85797792223954
82.24629397834902 83.00603891515506
82.63708148686703 83.23221006969828
$ benchmark-driver -v --rbenv 'before;before --jit;after --jit' benchmark/mjit_leave.yml --repeat-count=4
before: ruby 2.8.0dev (2020-04-01T03:48:56Z master 5a81562dfe) [x86_64-linux]
before --jit: ruby 2.8.0dev (2020-04-01T03:48:56Z master 5a81562dfe) +JIT [x86_64-linux]
after --jit: ruby 2.8.0dev (2020-04-01T04:58:01Z master 39beb26a27) +JIT [x86_64-linux]
Calculating -------------------------------------
before before --jit after --jit
mjit_leave 106.656M 82.786M 91.635M i/s - 200.000M times in 1.875183s 2.415881s 2.182569s
Comparison:
mjit_leave
before: 106656239.9 i/s
after --jit: 91635143.7 i/s - 1.16x slower
before --jit: 82785537.2 i/s - 1.29x slower
-rw-r--r-- | benchmark/mjit_leave.yml | 7 | ||||
-rw-r--r-- | tool/ruby_vm/views/mjit_compile.inc.erb | 20 |
2 files changed, 22 insertions, 5 deletions
diff --git a/benchmark/mjit_leave.yml b/benchmark/mjit_leave.yml new file mode 100644 index 0000000000..292d6ef041 --- /dev/null +++ b/benchmark/mjit_leave.yml @@ -0,0 +1,7 @@ +prelude: | + def leave + nil + end +benchmark: + mjit_leave: leave +loop_count: 200000000 diff --git a/tool/ruby_vm/views/mjit_compile.inc.erb b/tool/ruby_vm/views/mjit_compile.inc.erb index b51e777cb8..500a4fcf2c 100644 --- a/tool/ruby_vm/views/mjit_compile.inc.erb +++ b/tool/ruby_vm/views/mjit_compile.inc.erb @@ -70,12 +70,22 @@ switch (insn) { fprintf(stderr, "MJIT warning: Unexpected JIT stack_size on leave: %d\n", b->stack_size); status->success = false; } -% # Special leave for an inlined call. - if (status->inlined_iseqs == NULL) { // the current ISeq is being inlined - fprintf(f, " return stack[0];\n"); - b->stack_size += <%= insn.call_attribute('sp_inc') %>; - break; +% # Skip vm_pop_frame for inlined call + if (status->inlined_iseqs != NULL) { // the current ISeq is NOT being inlined +% # Cancel on interrupts to make leave insn leaf + fprintf(f, " if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(ec))) {\n"); + if (status->local_stack_p) { + fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size); + } + fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", pos); + fprintf(f, " goto cancel;\n"); + fprintf(f, " }\n"); + fprintf(f, " ec->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(reg_cfp);\n"); // vm_pop_frame } + fprintf(f, " return stack[0];\n"); + b->stack_size += <%= insn.call_attribute('sp_inc') %>; + b->finish_p = TRUE; + break; % end % % # Main insn implementation generated by insns.def |