mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
7d0144e055
for leaf_without_check_ints insns.
$ benchmark-driver -v --rbenv 'before --jit;after --jit' --repeat-count=12 --alternate --output=all benchmark.yml
before --jit: ruby 3.0.0dev (2020-12-20T05:02:18Z master 02b3555874
) +JIT [x86_64-linux]
after --jit: ruby 3.0.0dev (2020-12-20T05:36:00Z master 3f58de4eab) +JIT [x86_64-linux]
last_commit=Check mjit_call_p only when interrupted
Calculating -------------------------------------
before --jit after --jit
Optcarrot Lan_Master.nes 84.50647332260259 85.85057800433144 fps
91.17796644338372 92.09930605656054
91.29346683444497 93.01336611323687
91.50322318568884 93.07234029037433
91.66560903214686 93.22773241529644
91.82315142636172 93.37032901061119
92.15066379608260 93.83701526141679
92.37897097456643 93.86032792681507
92.53049815524908 93.91211970920320
92.78414507914283 94.09109196967890
92.90299756525958 94.40107239595325
93.70279428858790 95.01326369371263
129 lines
5.9 KiB
Text
129 lines
5.9 KiB
Text
% # -*- C -*-
|
|
% # 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.
|
|
%
|
|
% to_cstr = lambda do |line|
|
|
% normalized = line.gsub(/\t/, ' ' * 8)
|
|
% indented = normalized.sub(/\A(?!#)/, ' ') # avoid indenting preprocessor
|
|
% rstring2cstr(indented.rstrip).sub(/"\z/, '\\n"')
|
|
% end
|
|
%
|
|
% #
|
|
% # Expand simple macro, which doesn't require dynamic C code.
|
|
% #
|
|
% expand_simple_macros = lambda do |arg_expr|
|
|
% arg_expr.dup.tap do |expr|
|
|
% # For `leave`. We can't proceed next ISeq in the same JIT function.
|
|
% expr.gsub!(/^(?<indent>\s*)RESTORE_REGS\(\);\n/) do
|
|
% indent = Regexp.last_match[:indent]
|
|
% <<-end.gsub(/^ +/, '')
|
|
% #if OPT_CALL_THREADED_CODE
|
|
% #{indent}rb_ec_thread_ptr(ec)->retval = val;
|
|
% #{indent}return 0;
|
|
% #else
|
|
% #{indent}return val;
|
|
% #endif
|
|
% end
|
|
% end
|
|
% expr.gsub!(/^(?<indent>\s*)NEXT_INSN\(\);\n/) do
|
|
% indent = Regexp.last_match[:indent]
|
|
% <<-end.gsub(/^ +/, '')
|
|
% #{indent}UNREACHABLE_RETURN(Qundef);
|
|
% end
|
|
% end
|
|
% end
|
|
% end
|
|
%
|
|
% #
|
|
% # Print a body of insn, but with macro expansion.
|
|
% #
|
|
% expand_simple_macros.call(insn.expr.expr).each_line do |line|
|
|
% #
|
|
% # Expand dynamic macro here (only JUMP for now)
|
|
% #
|
|
% # TODO: support combination of following macros in the same line
|
|
% case line
|
|
% when /\A\s+RUBY_VM_CHECK_INTS\(ec\);\s+\z/
|
|
% if insn.leaf_without_check_ints? # lazily move PC and optionalize mjit_call_p here
|
|
fprintf(f, " if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(ec))) {\n");
|
|
fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", next_pos); /* ADD_PC(INSN_ATTR(width)); */
|
|
fprintf(f, " rb_threadptr_execute_interrupts(rb_ec_thread_ptr(ec), 0);\n");
|
|
fprintf(f, " if (UNLIKELY(!mjit_call_p)) {\n");
|
|
fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size);
|
|
fprintf(f, " RB_DEBUG_COUNTER_INC(mjit_cancel_invalidate_all);\n");
|
|
fprintf(f, " goto cancel;\n");
|
|
fprintf(f, " }\n");
|
|
fprintf(f, " }\n");
|
|
% else
|
|
fprintf(f, <%= to_cstr.call(line) %>);
|
|
% end
|
|
% when /\A\s+JUMP\((?<dest>[^)]+)\);\s+\z/
|
|
% dest = Regexp.last_match[:dest]
|
|
%
|
|
% if insn.name == 'opt_case_dispatch' # special case... TODO: use another macro to avoid checking name
|
|
{
|
|
struct case_dispatch_var arg;
|
|
arg.f = f;
|
|
arg.base_pos = pos + insn_len(insn);
|
|
arg.last_value = Qundef;
|
|
|
|
fprintf(f, " switch (<%= dest %>) {\n");
|
|
st_foreach(RHASH_TBL_RAW(hash), compile_case_dispatch_each, (VALUE)&arg);
|
|
fprintf(f, " case %lu:\n", else_offset);
|
|
fprintf(f, " goto label_%lu;\n", arg.base_pos + else_offset);
|
|
fprintf(f, " }\n");
|
|
}
|
|
% else
|
|
% # Before we `goto` next insn, we need to set return values, especially for getinlinecache
|
|
% insn.rets.reverse_each.with_index do |ret, i|
|
|
% # TOPN(n) = ...
|
|
fprintf(f, " stack[%d] = <%= ret.fetch(:name) %>;\n", b->stack_size + (int)<%= insn.call_attribute('sp_inc') %> - <%= i + 1 %>);
|
|
% end
|
|
%
|
|
next_pos = pos + insn_len(insn) + (unsigned int)<%= dest %>;
|
|
fprintf(f, " goto label_%d;\n", next_pos);
|
|
% end
|
|
% when /\A\s+CALL_SIMPLE_METHOD\(\);\s+\z/
|
|
% # For `opt_xxx`'s fallbacks.
|
|
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, " RB_DEBUG_COUNTER_INC(mjit_cancel_opt_insn);\n");
|
|
fprintf(f, " goto cancel;\n");
|
|
% when /\A(?<prefix>.+\b)INSN_LABEL\((?<name>[^)]+)\)(?<suffix>.+)\z/m
|
|
% prefix, name, suffix = Regexp.last_match[:prefix], Regexp.last_match[:name], Regexp.last_match[:suffix]
|
|
fprintf(f, " <%= prefix.gsub(/\t/, ' ' * 8) %>INSN_LABEL(<%= name %>_%d)<%= suffix.sub(/\n/, '\n') %>", pos);
|
|
% else
|
|
% if insn.handles_sp?
|
|
% # If insn.handles_sp? is true, cfp->sp might be changed inside insns (like vm_caller_setup_arg_block)
|
|
% # and thus we need to use cfp->sp, even when local_stack_p is TRUE. When insn.handles_sp? is true,
|
|
% # cfp->sp should be available too because _mjit_compile_pc_and_sp.erb sets it.
|
|
fprintf(f, <%= to_cstr.call(line) %>);
|
|
% else
|
|
% # If local_stack_p is TRUE and insn.handles_sp? is false, stack values are only available in local variables
|
|
% # for stack. So we need to replace those macros if local_stack_p is TRUE here.
|
|
% case line
|
|
% when /\bGET_SP\(\)/
|
|
% # reg_cfp->sp
|
|
fprintf(f, <%= to_cstr.call(line.sub(/\bGET_SP\(\)/, '%s')) %>, (status->local_stack_p ? "(stack + stack_size)" : "GET_SP()"));
|
|
% when /\bSTACK_ADDR_FROM_TOP\((?<num>[^)]+)\)/
|
|
% # #define STACK_ADDR_FROM_TOP(n) (GET_SP()-(n))
|
|
% num = Regexp.last_match[:num]
|
|
fprintf(f, <%= to_cstr.call(line.sub(/\bSTACK_ADDR_FROM_TOP\(([^)]+)\)/, '%s')) %>,
|
|
(status->local_stack_p ? "(stack + (stack_size - (<%= num %>)))" : "STACK_ADDR_FROM_TOP(<%= num %>)"));
|
|
% when /\bTOPN\((?<num>[^)]+)\)/
|
|
% # #define TOPN(n) (*(GET_SP()-(n)-1))
|
|
% num = Regexp.last_match[:num]
|
|
fprintf(f, <%= to_cstr.call(line.sub(/\bTOPN\(([^)]+)\)/, '%s')) %>,
|
|
(status->local_stack_p ? "*(stack + (stack_size - (<%= num %>) - 1))" : "TOPN(<%= num %>)"));
|
|
% else
|
|
fprintf(f, <%= to_cstr.call(line) %>);
|
|
% end
|
|
% end
|
|
% end
|
|
% end
|