diff options
author | Takashi Kokubun <[email protected]> | 2020-04-13 20:32:59 -0700 |
---|---|---|
committer | GitHub <[email protected]> | 2020-04-13 20:32:59 -0700 |
commit | 310ef9f40b350957a1a6d6236ce453ff9f73e81d (patch) | |
tree | 50d581463e2fdb371beac3eee97a0f25ed74e8b5 /tool/ruby_vm | |
parent | b9d3ceee8f8e4fade1eddc0c18abee59f9c1eee7 (diff) |
Make vm_call_cfunc_with_frame a fastpath (#3027)
when there's no need to call CALLER_SETUP_ARG and CALLER_REMOVE_EMPTY_KW_SPLAT
(i.e. !rb_splat_or_kwargs_p(ci) && !calling->kw_splat).
Micro benchmark:
```
$ benchmark-driver -v --rbenv 'before;after' benchmark/vm_send_cfunc.yml --repeat-count=4
before: ruby 2.8.0dev (2020-04-13T23:45:05Z master b9d3ceee8f) [x86_64-linux]
after: ruby 2.8.0dev (2020-04-14T00:48:52Z no-splat-fastpath 418d363722) [x86_64-linux]
Calculating -------------------------------------
before after
vm_send_cfunc 69.585M 88.724M i/s - 100.000M times in 1.437097s 1.127096s
Comparison:
vm_send_cfunc
after: 88723605.2 i/s
before: 69584737.1 i/s - 1.28x slower
```
Optcarrot:
```
$ benchmark-driver -v --rbenv 'before;after' benchmark.yml --repeat-count=12 --output=all
before: ruby 2.8.0dev (2020-04-13T23:45:05Z master b9d3ceee8f) [x86_64-linux]
after: ruby 2.8.0dev (2020-04-14T00:48:52Z no-splat-fastpath 418d363722) [x86_64-linux]
Calculating -------------------------------------
before after
Optcarrot Lan_Master.nes 50.76119601545175 42.73858236484051 fps
50.76388649761503 51.04211379912850
50.80930672252514 51.39455790755538
50.90236000778749 51.75656936556145
51.01744746340430 51.86875277356489
51.06495279015112 51.88692482485558
51.07785337168974 51.93429603190578
51.20163525187862 51.95768145071314
51.34671771913112 52.45577266040274
51.35918340835583 52.53163888762858
51.46641337418146 52.62172484121034
51.50835463462257 52.85064021113239
```
Notes
Notes:
Merged-By: k0kubun <[email protected]>
Diffstat (limited to 'tool/ruby_vm')
-rw-r--r-- | tool/ruby_vm/views/_mjit_compile_send.erb | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/tool/ruby_vm/views/_mjit_compile_send.erb b/tool/ruby_vm/views/_mjit_compile_send.erb index 255648bc2d..2b1ecdb2f3 100644 --- a/tool/ruby_vm/views/_mjit_compile_send.erb +++ b/tool/ruby_vm/views/_mjit_compile_send.erb @@ -18,9 +18,12 @@ % # compiler: Inline send insn where some supported fastpath is used. const rb_iseq_t *iseq = NULL; const CALL_INFO ci = cd->ci; + int kw_splat = IS_ARGS_KW_SPLAT(ci) > 0; + extern bool rb_splat_or_kwargs_p(const struct rb_callinfo *restrict ci); if (!status->compile_info->disable_send_cache && has_valid_method_type(captured_cc) && ( -% # `CC_SET_FASTPATH(cc, vm_call_cfunc, TRUE)` in `vm_call_method_each_type` - vm_cc_cme(captured_cc)->def->type == VM_METHOD_TYPE_CFUNC +% # `CC_SET_FASTPATH(cd->cc, vm_call_cfunc_with_frame, ...)` in `vm_call_cfunc` + (vm_cc_cme(captured_cc)->def->type == VM_METHOD_TYPE_CFUNC + && !rb_splat_or_kwargs_p(ci) && !kw_splat) % # `CC_SET_FASTPATH(cc, vm_call_iseq_setup_func(...), vm_call_iseq_optimizable_p(...))` in `vm_callee_setup_arg`, % # and support only non-VM_CALL_TAILCALL path inside it || (vm_cc_cme(captured_cc)->def->type == VM_METHOD_TYPE_ISEQ @@ -61,14 +64,14 @@ % else fprintf(f, " calling.block_handler = VM_BLOCK_HANDLER_NONE;\n"); % end - fprintf(f, " calling.kw_splat = %d;\n", IS_ARGS_KW_SPLAT(ci) > 0); + fprintf(f, " calling.kw_splat = %d;\n", kw_splat); fprintf(f, " calling.recv = stack[%d];\n", b->stack_size + sp_inc - 1); fprintf(f, " calling.argc = %d;\n", vm_ci_argc(ci)); if (vm_cc_cme(captured_cc)->def->type == VM_METHOD_TYPE_CFUNC) { % # TODO: optimize this more fprintf(f, " CALL_DATA cd = (CALL_DATA)0x%"PRIxVALUE";\n", operands[0]); - fprintf(f, " val = vm_call_cfunc(ec, reg_cfp, &calling, cd);\n"); + fprintf(f, " val = vm_call_cfunc_with_frame(ec, reg_cfp, &calling, cd);\n"); } else { // VM_METHOD_TYPE_ISEQ % # fastpath_applied_iseq_p checks rb_simple_iseq_p, which ensures has_opt == FALSE |