aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2020-03-31 21:58:01 -0700
committerTakashi Kokubun <takashikkbn@gmail.com>2020-03-31 22:10:16 -0700
commit151f8be40d385ada2ebf7feb84210ed7db7ef4df (patch)
tree80dce1c63a4afdc84217a1495423b7e931b0fc96
parent5a81562dfed2d5839e28b654d4f0f69de632aa8e (diff)
downloadruby-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.yml7
-rw-r--r--tool/ruby_vm/views/mjit_compile.inc.erb20
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