mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00

if catch_except_p is FALSE. If catch_except_p is TRUE, stack values should be on VM's stack when exception is thrown and the JIT-ed frame is re-executed by VM's exception handler. If it's FALSE, the JIT-ed frame won't be re-executed and don't need to keep values on VM's stack. Using local variables allows us to reduce cfp->sp motion. Moving cfp->sp is needed only for insns whose handles_frame? is false. So it improves performance. _mjit_compile_insn.erb: Prepare `stack_size` variable for GET_SP, STACK_ADDR_FROM_TOP, TOPN macros. Share pc and sp motion partial view. Use cancel handler created in mjit_compile.c. _mjit_compile_send.erb: ditto. Also, when iseq->body->catch_except_p is TRUE, this stops to call mjit_exec directly. I described the reason in vm_insnhelper.h's comment for EXEC_EC_CFP. _mjit_compile_pc_and_sp.erb: Shared logic for moving sp and pc. As you can see from thsi file, when status->local_stack_p is TRUE and insn.handles_frame? is false, moving sp is skipped. But if insn.handles_frame? is true, values should be rolled back to VM's stack. common.mk: add dependency for the file _mjit_compile_insn_body.erb: Set sp value before canceling JIT on DISPATCH_ORIGINAL_INSN. Replace GET_SP, STACK_ADDR_FROM_TOP, TOPN macros for the case ocal_stack_p is TRUE and insn.handles_frame? is false. In that case, values are not available on VM's stack and those macros should be replaced. mjit_compile.inc.erb: updated comments of macros which are supported by JIT compiler. All references to `cfp->sp` should be replaced and thus INC_SP, SET_SV, PUSH are no longer supported for now, because they are not used now. vm_exec.h: moved EXEC_EC_CFP definition to vm_insnhelper.h because it's tighly coupled to CALL_METHOD. vm_insnhelper.h: Have revised EXEC_EC_CFP definition moved from vm_exec.h. Now it triggers mjit_exec for VM, and has the guard for catch_except_p on JIT-ed code. See comments for details. CALL_METHOD delegates triggering mjit_exec to EXEC_EC_CFP. insns.def: Stopped using EXEC_EC_CFP for the case we don't want to trigger mjit_exec. Those insns (defineclass, opt_call_c_function) are not supported by JIT and it's safe to use RESTORE_REGS(), NEXT_INSN(). expandarray is changed to pass GET_SP() to replace the macro in _mjit_compile_insn_body.erb. vm_insnhelper.c: change to take sp for the above reason. [close https://github.com/ruby/ruby/pull/1828] This patch resurrects the performance which was attached in [Feature #14235]. * Benchmark Optcarrot (with configuration for benchmark_driver.gem) https://github.com/benchmark-driver/optcarrot $ benchmark-driver benchmark.yml --verbose 1 --rbenv 'before;before+JIT::before,--jit;after;after+JIT::after,--jit' --repeat-count 10 before: ruby 2.6.0dev (2018-03-04 trunk 62652) [x86_64-linux] before+JIT: ruby 2.6.0dev (2018-03-04 trunk 62652) +JIT [x86_64-linux] after: ruby 2.6.0dev (2018-03-04 local-variable.. 62652) [x86_64-linux] last_commit=mjit_compile.c: use local variables for stack after+JIT: ruby 2.6.0dev (2018-03-04 local-variable.. 62652) +JIT [x86_64-linux] last_commit=mjit_compile.c: use local variables for stack Calculating ------------------------------------- before before+JIT after after+JIT optcarrot 53.552 59.680 53.697 63.358 fps Comparison: optcarrot after+JIT: 63.4 fps before+JIT: 59.7 fps - 1.06x slower after: 53.7 fps - 1.18x slower before: 53.6 fps - 1.18x slower git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62655 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
68 lines
3.1 KiB
Text
68 lines
3.1 KiB
Text
/* -*- mode:c; style:ruby; coding: utf-8; indent-tabs-mode: nil -*- */
|
|
|
|
% # Copyright (c) 2018 Takashi Kokubun. All rights reserved.
|
|
% #
|
|
% # This file is a part of the programming language Ruby. Permission is hereby
|
|
% # granted, to either redistribute and/or modify this file, provided that the
|
|
% # conditions mentioned in the file COPYING are met. Consult the file for
|
|
% # details.
|
|
<%= render 'copyright' %>
|
|
%
|
|
% # This is an ERB template that generates Ruby code that generates C code that
|
|
% # generates JIT-ed C code.
|
|
<%= render 'notice', locals: {
|
|
this_file: 'is the main part of compile_insn() in mjit_compile.c',
|
|
edit: __FILE__,
|
|
} -%>
|
|
%
|
|
% unsupported_insns = [
|
|
% 'getblockparamproxy', # TODO: support this
|
|
% 'defineclass', # low priority
|
|
% 'opt_call_c_function', # low priority
|
|
% ]
|
|
%
|
|
% opt_send_without_block = RubyVM::Instructions.find { |i| i.name == 'opt_send_without_block' }
|
|
% if opt_send_without_block.nil?
|
|
% raise 'opt_send_without_block not found'
|
|
% end
|
|
%
|
|
% # Available variables and macros in JIT-ed function:
|
|
% # ec: the first argument of _mjitXXX
|
|
% # reg_cfp: the second argument of _mjitXXX
|
|
% # GET_CFP(): refers to `reg_cfp`
|
|
% # GET_EP(): refers to `reg_cfp->ep`
|
|
% # GET_SP(): refers to `reg_cfp->sp`, or `(stack + stack_size)` if local_stack_p
|
|
% # GET_SELF(): refers to `reg_cfp->self`
|
|
% # GET_LEP(): refers to `VM_EP_LEP(reg_cfp->ep)`
|
|
% # EXEC_EC_CFP(): refers to `val = vm_exec(ec, TRUE)` with frame setup
|
|
% # CALL_METHOD(): using `GET_CFP()` and `EXEC_EC_CFP()`
|
|
% # TOPN(): refers to `reg_cfp->sp`, or `*(stack + (stack_size - num - 1))` if local_stack_p
|
|
% # STACK_ADDR_FROM_TOP(): refers to `reg_cfp->sp`, or `stack + (stack_size - num)` if local_stack_p
|
|
% # DISPATCH_ORIGINAL_INSN(): expanded in _mjit_compile_insn.erb
|
|
% # THROW_EXCEPTION(): specially defined for JIT
|
|
% # RESTORE_REGS(): specially defined for `leave`
|
|
|
|
switch (insn) {
|
|
% (RubyVM::BareInstructions.to_a + RubyVM::OperandsUnifications.to_a).each do |insn|
|
|
% next if unsupported_insns.include?(insn.name)
|
|
case BIN(<%= insn.name %>):
|
|
% if %w[opt_send_without_block send].include?(insn.name)
|
|
<%= render 'mjit_compile_send', locals: { insn: insn } -%>
|
|
% elsif %w[opt_aref].include?(insn.name) # experimental. TODO: increase insns and make the list automatically by finding DISPATCH_ORIGINAL_INSN
|
|
<%= render 'mjit_compile_send', locals: { insn: opt_send_without_block } -%>
|
|
% end
|
|
<%= render 'mjit_compile_insn', locals: { insn: insn, dispatched: false } -%>
|
|
break;
|
|
% end
|
|
% # We don't support InstructionsUnifications yet because it's not used for now.
|
|
% # We don't support TraceInstructions yet. There is no blocker for it but it's just not implemented.
|
|
default:
|
|
if (mjit_opts.warnings || mjit_opts.verbose)
|
|
fprintf(stderr, "MJIT warning: Skipped to compile unsupported instruction: %s\n", insn_name(insn));
|
|
status->success = FALSE;
|
|
break;
|
|
}
|
|
|
|
/* if next_pos is already compiled, next instruction won't be compiled in C code and needs `goto`. */
|
|
if ((next_pos < body->iseq_size && status->compiled_for_pos[next_pos]))
|
|
fprintf(f, "goto label_%d;\n", next_pos);
|