summaryrefslogtreecommitdiff
path: root/tool/ruby_vm
diff options
context:
space:
mode:
Diffstat (limited to 'tool/ruby_vm')
-rw-r--r--tool/ruby_vm/controllers/application_controller.rb1
-rw-r--r--tool/ruby_vm/helpers/c_escape.rb6
-rw-r--r--tool/ruby_vm/helpers/dumper.rb7
-rw-r--r--tool/ruby_vm/helpers/scanner.rb1
-rw-r--r--tool/ruby_vm/loaders/insns_def.rb1
-rw-r--r--tool/ruby_vm/loaders/opt_insn_unif_def.rb1
-rw-r--r--tool/ruby_vm/loaders/opt_operand_def.rb1
-rw-r--r--tool/ruby_vm/loaders/vm_opts_h.rb1
-rw-r--r--tool/ruby_vm/models/attribute.rb1
-rw-r--r--[-rwxr-xr-x]tool/ruby_vm/models/bare_instruction.rb (renamed from tool/ruby_vm/models/bare_instructions.rb)20
-rw-r--r--tool/ruby_vm/models/c_expr.rb1
-rw-r--r--tool/ruby_vm/models/instructions.rb19
-rw-r--r--tool/ruby_vm/models/instructions_unification.rb (renamed from tool/ruby_vm/models/instructions_unifications.rb)9
-rw-r--r--tool/ruby_vm/models/operands_unification.rb (renamed from tool/ruby_vm/models/operands_unifications.rb)11
-rw-r--r--tool/ruby_vm/models/trace_instruction.rb (renamed from tool/ruby_vm/models/trace_instructions.rb)13
-rw-r--r--tool/ruby_vm/models/typemap.rb1
-rw-r--r--tool/ruby_vm/models/zjit_instruction.rb56
-rw-r--r--tool/ruby_vm/scripts/insns2vm.rb1
-rw-r--r--tool/ruby_vm/tests/.gitkeep0
-rw-r--r--tool/ruby_vm/views/_comptime_insn_stack_increase.erb25
-rw-r--r--tool/ruby_vm/views/_insn_entry.erb5
-rw-r--r--tool/ruby_vm/views/_insn_leaf_info.erb18
-rw-r--r--tool/ruby_vm/views/_insn_len_info.erb12
-rw-r--r--tool/ruby_vm/views/_insn_name_info.erb33
-rw-r--r--tool/ruby_vm/views/_insn_operand_info.erb32
-rw-r--r--tool/ruby_vm/views/_insn_sp_pc_dependency.erb27
-rw-r--r--tool/ruby_vm/views/_leaf_helpers.erb31
-rw-r--r--tool/ruby_vm/views/_sp_inc_helpers.erb2
-rw-r--r--tool/ruby_vm/views/_zjit_helpers.erb31
-rw-r--r--tool/ruby_vm/views/_zjit_instruction.erb12
-rw-r--r--tool/ruby_vm/views/insns.inc.erb17
-rw-r--r--tool/ruby_vm/views/insns_info.inc.erb6
-rw-r--r--tool/ruby_vm/views/lib/ruby_vm/rjit/instruction.rb.erb2
-rw-r--r--tool/ruby_vm/views/optinsn.inc.erb4
-rw-r--r--tool/ruby_vm/views/optunifs.inc.erb5
-rw-r--r--tool/ruby_vm/views/vm.inc.erb12
-rw-r--r--tool/ruby_vm/views/vmtc.inc.erb10
37 files changed, 276 insertions, 159 deletions
diff --git a/tool/ruby_vm/controllers/application_controller.rb b/tool/ruby_vm/controllers/application_controller.rb
index e03e54e397..f6c0e39600 100644
--- a/tool/ruby_vm/controllers/application_controller.rb
+++ b/tool/ruby_vm/controllers/application_controller.rb
@@ -1,4 +1,3 @@
-#! /your/favourite/path/to/ruby
# -*- Ruby -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
diff --git a/tool/ruby_vm/helpers/c_escape.rb b/tool/ruby_vm/helpers/c_escape.rb
index 34fafd1e34..628cb0428b 100644
--- a/tool/ruby_vm/helpers/c_escape.rb
+++ b/tool/ruby_vm/helpers/c_escape.rb
@@ -1,4 +1,3 @@
-#! /your/favourite/path/to/ruby
# -*- Ruby -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
@@ -17,7 +16,10 @@ module RubyVM::CEscape
# generate comment, with escaps.
def commentify str
- return "/* #{str.b.gsub('*/', '*\\/').gsub('/*', '/\\*')} */"
+ unless str = str.dump[/\A"\K.*(?="\z)/]
+ raise Encoding::CompatibilityError, "must be ASCII-compatible (#{str.encoding})"
+ end
+ return "/* #{str.gsub('*/', '*\\/').gsub('/*', '/\\*')} */"
end
# Mimic gensym of CL.
diff --git a/tool/ruby_vm/helpers/dumper.rb b/tool/ruby_vm/helpers/dumper.rb
index c083dffa7a..f0758dd44f 100644
--- a/tool/ruby_vm/helpers/dumper.rb
+++ b/tool/ruby_vm/helpers/dumper.rb
@@ -1,4 +1,3 @@
-#! /your/favourite/path/to/ruby
# -*- Ruby -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
@@ -33,11 +32,7 @@ class RubyVM::Dumper
rescue Errno::ENOENT
raise "don't know how to generate #{path}"
else
- if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+
- erb = ERB.new(src, trim_mode: '%-')
- else
- erb = ERB.new(src, nil, '%-')
- end
+ erb = ERB.new(src, trim_mode: '%-')
erb.filename = path.to_path
return erb
end
diff --git a/tool/ruby_vm/helpers/scanner.rb b/tool/ruby_vm/helpers/scanner.rb
index ef6de8120e..8998abb2d3 100644
--- a/tool/ruby_vm/helpers/scanner.rb
+++ b/tool/ruby_vm/helpers/scanner.rb
@@ -1,4 +1,3 @@
-#! /your/favourite/path/to/ruby
# -*- Ruby -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
diff --git a/tool/ruby_vm/loaders/insns_def.rb b/tool/ruby_vm/loaders/insns_def.rb
index 034905f74e..d45d0ba83c 100644
--- a/tool/ruby_vm/loaders/insns_def.rb
+++ b/tool/ruby_vm/loaders/insns_def.rb
@@ -1,4 +1,3 @@
-#! /your/favourite/path/to/ruby
# -*- Ruby -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
diff --git a/tool/ruby_vm/loaders/opt_insn_unif_def.rb b/tool/ruby_vm/loaders/opt_insn_unif_def.rb
index aa6fd79e79..0750f1823a 100644
--- a/tool/ruby_vm/loaders/opt_insn_unif_def.rb
+++ b/tool/ruby_vm/loaders/opt_insn_unif_def.rb
@@ -1,4 +1,3 @@
-#! /your/favourite/path/to/ruby
# -*- Ruby -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
diff --git a/tool/ruby_vm/loaders/opt_operand_def.rb b/tool/ruby_vm/loaders/opt_operand_def.rb
index 29aef8a325..e08509a433 100644
--- a/tool/ruby_vm/loaders/opt_operand_def.rb
+++ b/tool/ruby_vm/loaders/opt_operand_def.rb
@@ -1,4 +1,3 @@
-#! /your/favourite/path/to/ruby
# -*- Ruby -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
diff --git a/tool/ruby_vm/loaders/vm_opts_h.rb b/tool/ruby_vm/loaders/vm_opts_h.rb
index 3f05c270ee..d626ea0296 100644
--- a/tool/ruby_vm/loaders/vm_opts_h.rb
+++ b/tool/ruby_vm/loaders/vm_opts_h.rb
@@ -1,4 +1,3 @@
-#! /your/favourite/path/to/ruby
# -*- Ruby -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
diff --git a/tool/ruby_vm/models/attribute.rb b/tool/ruby_vm/models/attribute.rb
index ac4122f3ac..177b701b92 100644
--- a/tool/ruby_vm/models/attribute.rb
+++ b/tool/ruby_vm/models/attribute.rb
@@ -1,4 +1,3 @@
-#! /your/favourite/path/to/ruby
# -*- Ruby -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
diff --git a/tool/ruby_vm/models/bare_instructions.rb b/tool/ruby_vm/models/bare_instruction.rb
index a810d89f3c..f87dd74179 100755..100644
--- a/tool/ruby_vm/models/bare_instructions.rb
+++ b/tool/ruby_vm/models/bare_instruction.rb
@@ -1,4 +1,3 @@
-#! /your/favourite/path/to/ruby
# -*- Ruby -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
@@ -15,7 +14,7 @@ require_relative 'c_expr'
require_relative 'typemap'
require_relative 'attribute'
-class RubyVM::BareInstructions
+class RubyVM::BareInstruction
attr_reader :template, :name, :operands, :pops, :rets, :decls, :expr
def initialize opts = {}
@@ -108,14 +107,6 @@ class RubyVM::BareInstructions
/\b(false|0)\b/ !~ @attrs.fetch('handles_sp').expr.expr
end
- def always_leaf?
- @attrs.fetch('leaf').expr.expr == 'true;'
- end
-
- def leaf_without_check_ints?
- @attrs.fetch('leaf').expr.expr == 'leafness_of_check_ints;'
- end
-
def handle_canary stmt
# Stack canary is basically a good thing that we want to add, however:
#
@@ -149,6 +140,10 @@ class RubyVM::BareInstructions
@variables.find { |_, var_info| var_info[:type] == 'CALL_DATA' }
end
+ def zjit_profile?
+ @attrs.fetch('zjit_profile').expr.expr != 'false;'
+ end
+
private
def check_attribute_consistency
@@ -187,6 +182,7 @@ class RubyVM::BareInstructions
generate_attribute 'rb_snum_t', 'sp_inc', rets.size - pops.size
generate_attribute 'bool', 'handles_sp', default_definition_of_handles_sp
generate_attribute 'bool', 'leaf', default_definition_of_leaf
+ generate_attribute 'bool', 'zjit_profile', false
end
def default_definition_of_handles_sp
@@ -228,13 +224,13 @@ class RubyVM::BareInstructions
new h.merge(:template => h)
}
- def self.fetch name
+ def self.find(name)
@instances.find do |insn|
insn.name == name
end or raise IndexError, "instruction not found: #{name}"
end
- def self.to_a
+ def self.all
@instances
end
end
diff --git a/tool/ruby_vm/models/c_expr.rb b/tool/ruby_vm/models/c_expr.rb
index 4b5aec58dd..095ff4f1d9 100644
--- a/tool/ruby_vm/models/c_expr.rb
+++ b/tool/ruby_vm/models/c_expr.rb
@@ -1,4 +1,3 @@
-#! /your/favourite/path/to/ruby
# -*- Ruby -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
diff --git a/tool/ruby_vm/models/instructions.rb b/tool/ruby_vm/models/instructions.rb
index 1198c7a4a6..7be7064b14 100644
--- a/tool/ruby_vm/models/instructions.rb
+++ b/tool/ruby_vm/models/instructions.rb
@@ -1,4 +1,3 @@
-#! /your/favourite/path/to/ruby
# -*- Ruby -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
@@ -10,13 +9,15 @@
# conditions mentioned in the file COPYING are met. Consult the file for
# details.
-require_relative 'bare_instructions'
-require_relative 'operands_unifications'
-require_relative 'instructions_unifications'
+require_relative 'bare_instruction'
+require_relative 'operands_unification'
+require_relative 'instructions_unification'
+require_relative 'trace_instruction'
+require_relative 'zjit_instruction'
-RubyVM::Instructions = RubyVM::BareInstructions.to_a + \
- RubyVM::OperandsUnifications.to_a + \
- RubyVM::InstructionsUnifications.to_a
-
-require_relative 'trace_instructions'
+RubyVM::Instructions = RubyVM::BareInstruction.all +
+ RubyVM::OperandsUnification.all +
+ RubyVM::InstructionsUnification.all +
+ RubyVM::TraceInstruction.all +
+ RubyVM::ZJITInstruction.all
RubyVM::Instructions.freeze
diff --git a/tool/ruby_vm/models/instructions_unifications.rb b/tool/ruby_vm/models/instructions_unification.rb
index 214ba5fcc2..5c798e6d54 100644
--- a/tool/ruby_vm/models/instructions_unifications.rb
+++ b/tool/ruby_vm/models/instructions_unification.rb
@@ -1,4 +1,3 @@
-#! /your/favourite/path/to/ruby
# -*- Ruby -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
@@ -12,9 +11,9 @@
require_relative '../helpers/c_escape'
require_relative '../loaders/opt_insn_unif_def'
-require_relative 'bare_instructions'
+require_relative 'bare_instruction'
-class RubyVM::InstructionsUnifications
+class RubyVM::InstructionsUnification
include RubyVM::CEscape
attr_reader :name
@@ -23,7 +22,7 @@ class RubyVM::InstructionsUnifications
@location = opts[:location]
@name = namegen opts[:signature]
@series = opts[:signature].map do |i|
- RubyVM::BareInstructions.fetch i # Misshit is fatal
+ RubyVM::BareInstruction.find(i) # Misshit is fatal
end
end
@@ -37,7 +36,7 @@ class RubyVM::InstructionsUnifications
new h
end
- def self.to_a
+ def self.all
@instances
end
end
diff --git a/tool/ruby_vm/models/operands_unifications.rb b/tool/ruby_vm/models/operands_unification.rb
index 10e5742897..ce118648ca 100644
--- a/tool/ruby_vm/models/operands_unifications.rb
+++ b/tool/ruby_vm/models/operands_unification.rb
@@ -1,4 +1,3 @@
-#! /your/favourite/path/to/ruby
# -*- Ruby -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
@@ -12,16 +11,16 @@
require_relative '../helpers/c_escape'
require_relative '../loaders/opt_operand_def'
-require_relative 'bare_instructions'
+require_relative 'bare_instruction'
-class RubyVM::OperandsUnifications < RubyVM::BareInstructions
+class RubyVM::OperandsUnification < RubyVM::BareInstruction
include RubyVM::CEscape
attr_reader :preamble, :original, :spec
def initialize opts = {}
name = opts[:signature][0]
- @original = RubyVM::BareInstructions.fetch name
+ @original = RubyVM::BareInstruction.find(name)
template = @original.template
parts = compose opts[:location], opts[:signature], template[:signature]
json = template.dup
@@ -130,12 +129,12 @@ class RubyVM::OperandsUnifications < RubyVM::BareInstructions
new h
end
- def self.to_a
+ def self.all
@instances
end
def self.each_group
- to_a.group_by(&:original).each_pair do |k, v|
+ all.group_by(&:original).each_pair do |k, v|
yield k, v
end
end
diff --git a/tool/ruby_vm/models/trace_instructions.rb b/tool/ruby_vm/models/trace_instruction.rb
index 4ed4c8cb42..6a3ad53c44 100644
--- a/tool/ruby_vm/models/trace_instructions.rb
+++ b/tool/ruby_vm/models/trace_instruction.rb
@@ -1,4 +1,3 @@
-#! /your/favourite/path/to/ruby
# -*- Ruby -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
@@ -11,9 +10,9 @@
# details.
require_relative '../helpers/c_escape'
-require_relative 'bare_instructions'
+require_relative 'bare_instruction'
-class RubyVM::TraceInstructions
+class RubyVM::TraceInstruction
include RubyVM::CEscape
attr_reader :name
@@ -61,11 +60,11 @@ class RubyVM::TraceInstructions
private
- @instances = RubyVM::Instructions.map {|i| new i }
+ @instances = (RubyVM::BareInstruction.all +
+ RubyVM::OperandsUnification.all +
+ RubyVM::InstructionsUnification.all).map {|i| new(i) }
- def self.to_a
+ def self.all
@instances
end
-
- RubyVM::Instructions.push(*to_a)
end
diff --git a/tool/ruby_vm/models/typemap.rb b/tool/ruby_vm/models/typemap.rb
index d762dd3321..68ef5a41a5 100644
--- a/tool/ruby_vm/models/typemap.rb
+++ b/tool/ruby_vm/models/typemap.rb
@@ -1,4 +1,3 @@
-#! /your/favourite/path/to/ruby
# -*- Ruby -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
diff --git a/tool/ruby_vm/models/zjit_instruction.rb b/tool/ruby_vm/models/zjit_instruction.rb
new file mode 100644
index 0000000000..04764e4c61
--- /dev/null
+++ b/tool/ruby_vm/models/zjit_instruction.rb
@@ -0,0 +1,56 @@
+require_relative '../helpers/c_escape'
+require_relative 'bare_instruction'
+
+# Profile YARV instructions to optimize code generated by ZJIT
+class RubyVM::ZJITInstruction
+ include RubyVM::CEscape
+
+ attr_reader :name
+
+ def initialize(orig)
+ @orig = orig
+ @name = as_tr_cpp "zjit @ #{@orig.name}"
+ end
+
+ def pretty_name
+ return sprintf "%s(...)(...)(...)", @name
+ end
+
+ def jump_destination
+ return @orig.name
+ end
+
+ def bin
+ return sprintf "BIN(%s)", @name
+ end
+
+ def width
+ return @orig.width
+ end
+
+ def operands_info
+ return @orig.operands_info
+ end
+
+ def rets
+ return ['...']
+ end
+
+ def pops
+ return ['...']
+ end
+
+ def attributes
+ return []
+ end
+
+ def has_attribute?(*)
+ return false
+ end
+
+ @instances = RubyVM::BareInstruction.all.filter(&:zjit_profile?).map {|i| new(i) }
+
+ def self.all
+ @instances
+ end
+end
diff --git a/tool/ruby_vm/scripts/insns2vm.rb b/tool/ruby_vm/scripts/insns2vm.rb
index 47d8da5513..ad8603b1a8 100644
--- a/tool/ruby_vm/scripts/insns2vm.rb
+++ b/tool/ruby_vm/scripts/insns2vm.rb
@@ -1,4 +1,3 @@
-#! /your/favourite/path/to/ruby
# -*- Ruby -*-
# -*- frozen_string_literal: true; -*-
# -*- warn_indent: true; -*-
diff --git a/tool/ruby_vm/tests/.gitkeep b/tool/ruby_vm/tests/.gitkeep
deleted file mode 100644
index e69de29bb2..0000000000
--- a/tool/ruby_vm/tests/.gitkeep
+++ /dev/null
diff --git a/tool/ruby_vm/views/_comptime_insn_stack_increase.erb b/tool/ruby_vm/views/_comptime_insn_stack_increase.erb
index cb895815ce..8bb28db1c1 100644
--- a/tool/ruby_vm/views/_comptime_insn_stack_increase.erb
+++ b/tool/ruby_vm/views/_comptime_insn_stack_increase.erb
@@ -6,6 +6,16 @@
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
%#
+%
+% stack_increase = proc do |i|
+% if i.has_attribute?('sp_inc')
+% '-127'
+% else
+% sprintf("%4d", i.rets.size - i.pops.size)
+% end
+% end
+% zjit_insns, insns = RubyVM::Instructions.partition { |i| i.name.start_with?('zjit_') }
+%
PUREFUNC(MAYBE_UNUSED(static int comptime_insn_stack_increase(int depth, int insn, const VALUE *opes)));
PUREFUNC(static rb_snum_t comptime_insn_stack_increase_dispatch(enum ruby_vminsn_type insn, const VALUE *opes));
@@ -13,15 +23,14 @@ rb_snum_t
comptime_insn_stack_increase_dispatch(enum ruby_vminsn_type insn, const VALUE *opes)
{
static const signed char t[] = {
-% RubyVM::Instructions.each_slice 8 do |a|
- <%= a.map { |i|
- if i.has_attribute?('sp_inc')
- '-127'
- else
- sprintf("%4d", i.rets.size - i.pops.size)
- end
- }.join(', ') -%>,
+% insns.each_slice(8) do |row|
+ <%= row.map(&stack_increase).join(', ') -%>,
+% end
+#if USE_ZJIT
+% zjit_insns.each_slice(8) do |row|
+ <%= row.map(&stack_increase).join(', ') -%>,
% end
+#endif
};
signed char c = t[insn];
diff --git a/tool/ruby_vm/views/_insn_entry.erb b/tool/ruby_vm/views/_insn_entry.erb
index 32070c5f34..6ec33461c4 100644
--- a/tool/ruby_vm/views/_insn_entry.erb
+++ b/tool/ruby_vm/views/_insn_entry.erb
@@ -24,7 +24,7 @@ INSN_ENTRY(<%= insn.name %>)
<%= ope[:decl] %> = (<%= ope[:type] %>)GET_OPERAND(<%= i + 1 %>);
% end
# define INSN_ATTR(x) <%= insn.call_attribute(' ## x ## ') %>
- const bool leaf = INSN_ATTR(leaf);
+ const bool MAYBE_UNUSED(leaf) = INSN_ATTR(leaf);
% insn.pops.reverse_each.with_index.reverse_each do |pop, i|
<%= pop[:decl] %> = <%= insn.cast_from_VALUE pop, "TOPN(#{i})"%>;
% end
@@ -35,7 +35,7 @@ INSN_ENTRY(<%= insn.name %>)
% end
/* ### Instruction preambles. ### */
- if (! leaf) ADD_PC(INSN_ATTR(width));
+ ADD_PC(INSN_ATTR(width));
% if insn.handles_sp?
POPN(INSN_ATTR(popn));
% end
@@ -68,7 +68,6 @@ INSN_ENTRY(<%= insn.name %>)
VM_ASSERT(!RB_TYPE_P(TOPN(<%= i %>), T_MOVED));
% end
% end
- if (leaf) ADD_PC(INSN_ATTR(width));
# undef INSN_ATTR
/* ### Leave the instruction. ### */
diff --git a/tool/ruby_vm/views/_insn_leaf_info.erb b/tool/ruby_vm/views/_insn_leaf_info.erb
new file mode 100644
index 0000000000..f30366ffda
--- /dev/null
+++ b/tool/ruby_vm/views/_insn_leaf_info.erb
@@ -0,0 +1,18 @@
+MAYBE_UNUSED(static bool insn_leaf(int insn, const VALUE *opes));
+static bool
+insn_leaf(int insn, const VALUE *opes)
+{
+ switch (insn) {
+% RubyVM::Instructions.each do |insn|
+% next if insn.is_a?(RubyVM::TraceInstruction) || insn.is_a?(RubyVM::ZJITInstruction)
+ case <%= insn.bin %>:
+ return attr_leaf_<%= insn.name %>(<%=
+ insn.operands.map.with_index do |ope, i|
+ "(#{ope[:type]})opes[#{i}]"
+ end.join(', ')
+ %>);
+% end
+ default:
+ return false;
+ }
+}
diff --git a/tool/ruby_vm/views/_insn_len_info.erb b/tool/ruby_vm/views/_insn_len_info.erb
index 569dca5845..b29a405918 100644
--- a/tool/ruby_vm/views/_insn_len_info.erb
+++ b/tool/ruby_vm/views/_insn_len_info.erb
@@ -5,6 +5,9 @@
%# 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.
+%
+% zjit_insns, insns = RubyVM::Instructions.partition { |i| i.name.start_with?('zjit_') }
+%
CONSTFUNC(MAYBE_UNUSED(static int insn_len(VALUE insn)));
RUBY_SYMBOL_EXPORT_BEGIN /* for debuggers */
@@ -13,9 +16,14 @@ RUBY_SYMBOL_EXPORT_END
#ifdef RUBY_VM_INSNS_INFO
const uint8_t rb_vm_insn_len_info[] = {
-% RubyVM::Instructions.each_slice 23 do |a|
- <%= a.map(&:width).join(', ') -%>,
+% insns.each_slice(23) do |row|
+ <%= row.map(&:width).join(', ') -%>,
% end
+#if USE_ZJIT
+% zjit_insns.each_slice(23) do |row|
+ <%= row.map(&:width).join(', ') -%>,
+% end
+#endif
};
ASSERT_VM_INSTRUCTION_SIZE(rb_vm_insn_len_info);
diff --git a/tool/ruby_vm/views/_insn_name_info.erb b/tool/ruby_vm/views/_insn_name_info.erb
index e7ded75e65..2862908631 100644
--- a/tool/ruby_vm/views/_insn_name_info.erb
+++ b/tool/ruby_vm/views/_insn_name_info.erb
@@ -6,10 +6,14 @@
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
%
-% a = RubyVM::Instructions.map {|i| i.name }
-% b = (0...a.size)
-% c = a.inject([0]) {|r, i| r << (r[-1] + i.length + 1) }
-% c.pop
+% zjit_insns, insns = RubyVM::Instructions.partition { |i| i.name.start_with?('zjit_') }
+%
+% next_offset = 0
+% name_offset = proc do |i|
+% offset = sprintf("%4d", next_offset)
+% next_offset += i.name.length + 1 # insn.name + \0
+% offset
+% end
%
CONSTFUNC(MAYBE_UNUSED(static const char *insn_name(VALUE insn)));
@@ -20,18 +24,29 @@ extern const unsigned short rb_vm_insn_name_offset[VM_INSTRUCTION_SIZE];
RUBY_SYMBOL_EXPORT_END
#ifdef RUBY_VM_INSNS_INFO
-const int rb_vm_max_insn_name_size = <%= a.map(&:size).max %>;
+%# "trace_" is longer than "zjit_", so USE_ZJIT doesn't impact the max name size.
+const int rb_vm_max_insn_name_size = <%= RubyVM::Instructions.map { |i| i.name.size }.max %>;
const char rb_vm_insn_name_base[] =
-% a.each do |i|
- <%=cstr i%> "\0"
+% insns.each do |i|
+ <%= cstr i.name %> "\0"
+% end
+#if USE_ZJIT
+% zjit_insns.each do |i|
+ <%= cstr i.name %> "\0"
% end
+#endif
;
const unsigned short rb_vm_insn_name_offset[] = {
-% c.each_slice 12 do |d|
- <%= d.map {|i| sprintf("%4d", i) }.join(', ') %>,
+% insns.each_slice(12) do |row|
+ <%= row.map(&name_offset).join(', ') %>,
+% end
+#if USE_ZJIT
+% zjit_insns.each_slice(12) do |row|
+ <%= row.map(&name_offset).join(', ') %>,
% end
+#endif
};
ASSERT_VM_INSTRUCTION_SIZE(rb_vm_insn_name_offset);
diff --git a/tool/ruby_vm/views/_insn_operand_info.erb b/tool/ruby_vm/views/_insn_operand_info.erb
index 996c33e960..410869fcd3 100644
--- a/tool/ruby_vm/views/_insn_operand_info.erb
+++ b/tool/ruby_vm/views/_insn_operand_info.erb
@@ -6,10 +6,16 @@
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
%
-% a = RubyVM::Instructions.map {|i| i.operands_info }
-% b = (0...a.size)
-% c = a.inject([0]) {|r, i| r << (r[-1] + i.length + 1) }
-% c.pop
+% zjit_insns, insns = RubyVM::Instructions.partition { |i| i.name.start_with?('zjit_') }
+%
+% operands_info = proc { |i| sprintf("%-6s", cstr(i.operands_info)) }
+%
+% next_offset = 0
+% op_offset = proc do |i|
+% offset = sprintf("%3d", next_offset)
+% next_offset += i.operands_info.length + 1 # insn.operands_info + \0
+% offset
+% end
%
CONSTFUNC(MAYBE_UNUSED(static const char *insn_op_types(VALUE insn)));
CONSTFUNC(MAYBE_UNUSED(static int insn_op_type(VALUE insn, long pos)));
@@ -21,15 +27,25 @@ RUBY_SYMBOL_EXPORT_END
#ifdef RUBY_VM_INSNS_INFO
const char rb_vm_insn_op_base[] =
-% a.each_slice 5 do |d|
- <%= d.map {|i| sprintf("%-6s", cstr(i)) }.join(' "\0" ') %> "\0"
+% insns.each_slice(5) do |row|
+ <%= row.map(&operands_info).join(' "\0" ') %> "\0"
+% end
+#if USE_ZJIT
+% zjit_insns.each_slice(5) do |row|
+ <%= row.map(&operands_info).join(' "\0" ') %> "\0"
% end
+#endif
;
const unsigned short rb_vm_insn_op_offset[] = {
-% c.each_slice 12 do |d|
- <%= d.map {|i| sprintf("%3d", i) }.join(', ') %>,
+% insns.each_slice(12) do |row|
+ <%= row.map(&op_offset).join(', ') %>,
+% end
+#if USE_ZJIT
+% zjit_insns.each_slice(12) do |row|
+ <%= row.map(&op_offset).join(', ') %>,
% end
+#endif
};
ASSERT_VM_INSTRUCTION_SIZE(rb_vm_insn_op_offset);
diff --git a/tool/ruby_vm/views/_insn_sp_pc_dependency.erb b/tool/ruby_vm/views/_insn_sp_pc_dependency.erb
deleted file mode 100644
index 95528fbbf4..0000000000
--- a/tool/ruby_vm/views/_insn_sp_pc_dependency.erb
+++ /dev/null
@@ -1,27 +0,0 @@
-%# -*- C -*-
-%# Copyright (c) 2019 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.
-%#
-PUREFUNC(MAYBE_UNUSED(static bool insn_may_depend_on_sp_or_pc(int insn, const VALUE *opes)));
-
-static bool
-insn_may_depend_on_sp_or_pc(int insn, const VALUE *opes)
-{
- switch (insn) {
-% RubyVM::Instructions.each do |insn|
-% # handles_sp?: If true, it requires to move sp in JIT
-% # always_leaf?: If false, it may call an arbitrary method. pc should be moved
-% # before the call, and the method may refer to caller's pc (lineno).
-% unless !insn.is_a?(RubyVM::TraceInstructions) && !insn.handles_sp? && insn.always_leaf?
- case <%= insn.bin %>:
-% end
-% end
- return true;
- default:
- return false;
- }
-}
diff --git a/tool/ruby_vm/views/_leaf_helpers.erb b/tool/ruby_vm/views/_leaf_helpers.erb
index ac35df64f4..2756fa2dec 100644
--- a/tool/ruby_vm/views/_leaf_helpers.erb
+++ b/tool/ruby_vm/views/_leaf_helpers.erb
@@ -10,35 +10,6 @@
#include "iseq.h"
-extern const bool rb_vm_insn_leaf_p[];
-
-#ifdef RUBY_VM_INSNS_INFO
-const bool rb_vm_insn_leaf_p[] = {
-% RubyVM::Instructions.each_slice(20) do |insns|
- <%= insns.map do |insn|
- if insn.is_a?(RubyVM::BareInstructions)
- insn.always_leaf? ? '1' : '0'
- else
- '0'
- end
- end.join(', ')
- %>,
-% end
-};
-#endif
-
-CONSTFUNC(MAYBE_UNUSED(static bool insn_leaf_p(VALUE insn)));
-
-bool
-insn_leaf_p(VALUE insn)
-{
- return rb_vm_insn_leaf_p[insn];
-}
-
-// This is used to tell RJIT that this insn would be leaf if CHECK_INTS didn't exist.
-// It should be used only when RUBY_VM_CHECK_INTS is directly written in insns.def.
-static bool leafness_of_check_ints = false;
-
static bool
leafness_of_defined(rb_num_t op_type)
{
@@ -50,7 +21,7 @@ leafness_of_defined(rb_num_t op_type)
case DEFINED_YIELD:
case DEFINED_REF:
case DEFINED_ZSUPER:
- return false;
+ return true;
case DEFINED_CONST:
case DEFINED_CONST_FROM:
/* has rb_autoload_load(); */
diff --git a/tool/ruby_vm/views/_sp_inc_helpers.erb b/tool/ruby_vm/views/_sp_inc_helpers.erb
index d0b0bd79ef..740fe10142 100644
--- a/tool/ruby_vm/views/_sp_inc_helpers.erb
+++ b/tool/ruby_vm/views/_sp_inc_helpers.erb
@@ -18,7 +18,7 @@ sp_inc_of_sendish(const struct rb_callinfo *ci)
* 3. Pop receiver.
* 4. Push return value.
*/
- const int argb = (vm_ci_flag(ci) & VM_CALL_ARGS_BLOCKARG) ? 1 : 0;
+ const int argb = (vm_ci_flag(ci) & (VM_CALL_ARGS_BLOCKARG | VM_CALL_FORWARDING)) ? 1 : 0;
const int argc = vm_ci_argc(ci);
const int recv = 1;
const int retn = 1;
diff --git a/tool/ruby_vm/views/_zjit_helpers.erb b/tool/ruby_vm/views/_zjit_helpers.erb
new file mode 100644
index 0000000000..1185dbd9d8
--- /dev/null
+++ b/tool/ruby_vm/views/_zjit_helpers.erb
@@ -0,0 +1,31 @@
+#if USE_ZJIT
+
+MAYBE_UNUSED(static int vm_bare_insn_to_zjit_insn(int insn));
+static int
+vm_bare_insn_to_zjit_insn(int insn)
+{
+ switch (insn) {
+% RubyVM::ZJITInstruction.all.each do |insn|
+ case BIN(<%= insn.jump_destination %>):
+ return <%= insn.bin %>;
+% end
+ default:
+ return insn;
+ }
+}
+
+MAYBE_UNUSED(static int vm_zjit_insn_to_bare_insn(int insn));
+static int
+vm_zjit_insn_to_bare_insn(int insn)
+{
+ switch (insn) {
+% RubyVM::ZJITInstruction.all.each do |insn|
+ case <%= insn.bin %>:
+ return BIN(<%= insn.jump_destination %>);
+% end
+ default:
+ return insn;
+ }
+}
+
+#endif
diff --git a/tool/ruby_vm/views/_zjit_instruction.erb b/tool/ruby_vm/views/_zjit_instruction.erb
new file mode 100644
index 0000000000..7fd657697c
--- /dev/null
+++ b/tool/ruby_vm/views/_zjit_instruction.erb
@@ -0,0 +1,12 @@
+#if USE_ZJIT
+
+/* insn <%= insn.pretty_name %> */
+INSN_ENTRY(<%= insn.name %>)
+{
+ START_OF_ORIGINAL_INSN(<%= insn.name %>);
+ rb_zjit_profile_insn(BIN(<%= insn.jump_destination %>), ec);
+ DISPATCH_ORIGINAL_INSN(<%= insn.jump_destination %>);
+ END_INSN(<%= insn.name %>);
+}
+
+#endif
diff --git a/tool/ruby_vm/views/insns.inc.erb b/tool/ruby_vm/views/insns.inc.erb
index 29981a8a2d..6521a89b8a 100644
--- a/tool/ruby_vm/views/insns.inc.erb
+++ b/tool/ruby_vm/views/insns.inc.erb
@@ -6,21 +6,36 @@
%# 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.
+%
+% zjit_insns, insns = RubyVM::Instructions.partition { |i| i.name.start_with?('zjit_') }
+%
<%= render 'copyright' %>
<%= render 'notice', locals: {
this_file: 'contains YARV instruction list',
edit: __FILE__,
} -%>
+#ifndef INSNS_INC
+#define INSNS_INC 1
+
/* BIN : Basic Instruction Name */
#define BIN(n) YARVINSN_##n
enum ruby_vminsn_type {
-% RubyVM::Instructions.each do |i|
+% insns.each do |i|
+ <%= i.bin %>,
+% end
+#if USE_ZJIT
+% zjit_insns.each do |i|
<%= i.bin %>,
% end
+#endif
VM_INSTRUCTION_SIZE
};
+#define VM_BARE_INSTRUCTION_SIZE <%= RubyVM::Instructions.count { |i| i.name !~ /\A(trace|zjit)_/ } %>
+
#define ASSERT_VM_INSTRUCTION_SIZE(array) \
STATIC_ASSERT(numberof_##array, numberof(array) == VM_INSTRUCTION_SIZE)
+
+#endif
diff --git a/tool/ruby_vm/views/insns_info.inc.erb b/tool/ruby_vm/views/insns_info.inc.erb
index 2ca5aca7cf..48dd0e8832 100644
--- a/tool/ruby_vm/views/insns_info.inc.erb
+++ b/tool/ruby_vm/views/insns_info.inc.erb
@@ -11,12 +11,16 @@
this_file: 'contains instruction information for yarv instruction sequence.',
edit: __FILE__,
} %>
+#ifndef INSNS_INFO_INC
+#define INSNS_INFO_INC 1
<%= render 'insn_type_chars' %>
<%= render 'insn_name_info' %>
<%= render 'insn_len_info' %>
<%= render 'insn_operand_info' %>
<%= render 'leaf_helpers' %>
<%= render 'sp_inc_helpers' %>
+<%= render 'zjit_helpers' %>
<%= render 'attributes' %>
+<%= render 'insn_leaf_info' %>
<%= render 'comptime_insn_stack_increase' %>
-<%= render 'insn_sp_pc_dependency' %>
+#endif
diff --git a/tool/ruby_vm/views/lib/ruby_vm/rjit/instruction.rb.erb b/tool/ruby_vm/views/lib/ruby_vm/rjit/instruction.rb.erb
index 4f08524a77..793528af5d 100644
--- a/tool/ruby_vm/views/lib/ruby_vm/rjit/instruction.rb.erb
+++ b/tool/ruby_vm/views/lib/ruby_vm/rjit/instruction.rb.erb
@@ -7,7 +7,7 @@ module RubyVM::RJIT # :nodoc: all
name: :<%= insn.name %>,
bin: <%= i %>, # BIN(<%= insn.name %>)
len: <%= insn.width %>, # insn_len
- operands: <%= (insn.operands unless insn.name.start_with?('trace_')).inspect %>,
+ operands: <%= (insn.operands unless insn.name.start_with?(/trace_|zjit_/)).inspect %>,
),
% end
}
diff --git a/tool/ruby_vm/views/optinsn.inc.erb b/tool/ruby_vm/views/optinsn.inc.erb
index de7bb210ea..9d9cf0a43a 100644
--- a/tool/ruby_vm/views/optinsn.inc.erb
+++ b/tool/ruby_vm/views/optinsn.inc.erb
@@ -23,7 +23,7 @@ insn_operands_unification(INSN *iobj)
/* do nothing */;
break;
-% RubyVM::OperandsUnifications.each_group do |orig, unifs|
+% RubyVM::OperandsUnification.each_group do |orig, unifs|
case <%= orig.bin %>:
% unifs.each do |insn|
@@ -56,7 +56,7 @@ rb_insn_unified_local_var_level(VALUE insn)
switch (insn) {
default:
return -1; /* do nothing */;
-% RubyVM::OperandsUnifications.each_group do |orig, unifs|
+% RubyVM::OperandsUnification.each_group do |orig, unifs|
% unifs.each do|insn|
case <%= insn.bin %>:
% insn.spec.map{|(var,val)|val}.reject{|i| i == '*' }.each do |val|
diff --git a/tool/ruby_vm/views/optunifs.inc.erb b/tool/ruby_vm/views/optunifs.inc.erb
index e92a95beff..c096712936 100644
--- a/tool/ruby_vm/views/optunifs.inc.erb
+++ b/tool/ruby_vm/views/optunifs.inc.erb
@@ -7,7 +7,6 @@
%# conditions mentioned in the file COPYING are met. Consult the file for
%# details.
% raise ':FIXME:TBW' if RubyVM::VmOptsH['INSTRUCTIONS_UNIFICATION']
-% n = RubyVM::Instructions.size
<%= render 'copyright' %>
<%= render 'notice', locals: {
this_file: 'is for threaded code',
@@ -16,6 +15,4 @@
/* Let .bss section automatically initialize this variable */
/* cf. Section 6.7.8 of ISO/IEC 9899:1999 */
-static const int *const *const unified_insns_data[<%= n %>];
-
-ASSERT_VM_INSTRUCTION_SIZE(unified_insns_data);
+static const int *const *const unified_insns_data[VM_INSTRUCTION_SIZE];
diff --git a/tool/ruby_vm/views/vm.inc.erb b/tool/ruby_vm/views/vm.inc.erb
index c1a3faf60a..38bf5f05ae 100644
--- a/tool/ruby_vm/views/vm.inc.erb
+++ b/tool/ruby_vm/views/vm.inc.erb
@@ -13,18 +13,22 @@
} -%>
#include "vm_insnhelper.h"
-% RubyVM::BareInstructions.to_a.each do |insn|
+% RubyVM::BareInstruction.all.each do |insn|
<%= render 'insn_entry', locals: { insn: insn } -%>
% end
%
-% RubyVM::OperandsUnifications.to_a.each do |insn|
+% RubyVM::OperandsUnification.all.each do |insn|
<%= render 'insn_entry', locals: { insn: insn } -%>
% end
%
-% RubyVM::InstructionsUnifications.to_a.each do |insn|
+% RubyVM::InstructionsUnification.all.each do |insn|
<%= render 'insn_entry', locals: { insn: insn } -%>
% end
%
-% RubyVM::TraceInstructions.to_a.each do |insn|
+% RubyVM::ZJITInstruction.all.each do |insn|
+<%= render 'zjit_instruction', locals: { insn: insn } -%>
+% end
+%
+% RubyVM::TraceInstruction.all.each do |insn|
<%= render 'trace_instruction', locals: { insn: insn } -%>
% end
diff --git a/tool/ruby_vm/views/vmtc.inc.erb b/tool/ruby_vm/views/vmtc.inc.erb
index 99cbd92614..39dc8bfa6b 100644
--- a/tool/ruby_vm/views/vmtc.inc.erb
+++ b/tool/ruby_vm/views/vmtc.inc.erb
@@ -6,6 +6,9 @@
%# 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.
+%
+% zjit_insns, insns = RubyVM::Instructions.partition { |i| i.name.start_with?('zjit_') }
+%
<%= render 'copyright' -%>
<%= render 'notice', locals: {
this_file: 'is for threaded code',
@@ -13,9 +16,14 @@
} -%>
static const void *const insns_address_table[] = {
-% RubyVM::Instructions.each do |i|
+% insns.each do |i|
LABEL_PTR(<%= i.name %>),
% end
+#if USE_ZJIT
+% zjit_insns.each do |i|
+ LABEL_PTR(<%= i.name %>),
+% end
+#endif
};
ASSERT_VM_INSTRUCTION_SIZE(insns_address_table);