mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
d71b78575b
for ISeq including only leaf and no-handles_sp insns except leaf. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67574 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
94 lines
4.1 KiB
Text
94 lines
4.1 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.
|
|
<%= 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
|
|
%
|
|
% send_compatible_opt_insns = RubyVM::BareInstructions.to_a.select do |insn|
|
|
% insn.name.start_with?('opt_') && opt_send_without_block.opes == insn.opes &&
|
|
% insn.expr.expr.lines.any? { |l| l.match(/\A\s+CALL_SIMPLE_METHOD\(\);\s+\z/) }
|
|
% end.map(&:name)
|
|
%
|
|
% # 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 %>):
|
|
% # Instruction-specific behavior in JIT
|
|
% case insn.name
|
|
% when 'opt_send_without_block', 'send'
|
|
<%= render 'mjit_compile_send', locals: { insn: insn } -%>
|
|
% when *send_compatible_opt_insns
|
|
% # To avoid cancel, just emit `opt_send_without_block` instead of `opt_*` insn if call cache is populated.
|
|
% cc_index = insn.opes.index { |o| o.fetch(:type) == 'CALL_CACHE' }
|
|
if (has_valid_method_type(status->cc_entries + ((CALL_CACHE)operands[<%= cc_index %>] - body->cc_entries))) {
|
|
<%= render 'mjit_compile_send', locals: { insn: opt_send_without_block } -%>
|
|
<%= render 'mjit_compile_insn', locals: { insn: opt_send_without_block } -%>
|
|
break;
|
|
}
|
|
% when 'getinstancevariable', 'setinstancevariable'
|
|
<%= render 'mjit_compile_ivar', locals: { insn: insn } -%>
|
|
% when 'leave'
|
|
if (b->stack_size != 1) {
|
|
if (mjit_opts.warnings || mjit_opts.verbose)
|
|
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;
|
|
}
|
|
% end
|
|
%
|
|
% # Main insn implementation generated by insns.def
|
|
<%= render 'mjit_compile_insn', locals: { insn: insn } -%>
|
|
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;
|
|
}
|