summaryrefslogtreecommitdiff
path: root/tool/ruby_vm
diff options
context:
space:
mode:
authorTakashi Kokubun <[email protected]>2025-03-03 13:46:53 -0800
committerTakashi Kokubun <[email protected]>2025-04-18 21:52:59 +0900
commit0a543daf15e995ad12b0884bf89ea89b6b480dd2 (patch)
tree8cadafeccd9da51ea8c11014c3b2ab8701848387 /tool/ruby_vm
parent30db473389ca5bb6c68bec72de49330a72a2541c (diff)
Add zjit_* instructions to profile the interpreter (https://github.com/Shopify/zjit/pull/16)
* Add zjit_* instructions to profile the interpreter * Rename FixnumPlus to FixnumAdd * Update a comment about Invalidate * Rename Guard to GuardType * Rename Invalidate to PatchPoint * Drop unneeded debug!() * Plan on profiling the types * Use the output of GuardType as type refined outputs
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/13131
Diffstat (limited to 'tool/ruby_vm')
-rw-r--r--tool/ruby_vm/models/bare_instructions.rb5
-rw-r--r--tool/ruby_vm/models/instructions.rb1
-rw-r--r--tool/ruby_vm/models/zjit_instructions.rb58
-rw-r--r--tool/ruby_vm/views/_insn_sp_pc_dependency.erb27
-rw-r--r--tool/ruby_vm/views/_zjit_helpers.erb14
-rw-r--r--tool/ruby_vm/views/_zjit_instruction.erb8
-rw-r--r--tool/ruby_vm/views/insns.inc.erb5
-rw-r--r--tool/ruby_vm/views/insns_info.inc.erb1
-rw-r--r--tool/ruby_vm/views/lib/ruby_vm/rjit/instruction.rb.erb14
-rw-r--r--tool/ruby_vm/views/vm.inc.erb4
10 files changed, 137 insertions, 0 deletions
diff --git a/tool/ruby_vm/models/bare_instructions.rb b/tool/ruby_vm/models/bare_instructions.rb
index f813760cb6..491e3eaaa6 100644
--- a/tool/ruby_vm/models/bare_instructions.rb
+++ b/tool/ruby_vm/models/bare_instructions.rb
@@ -148,6 +148,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
@@ -186,6 +190,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
diff --git a/tool/ruby_vm/models/instructions.rb b/tool/ruby_vm/models/instructions.rb
index d243ffa49b..8856c49834 100644
--- a/tool/ruby_vm/models/instructions.rb
+++ b/tool/ruby_vm/models/instructions.rb
@@ -17,5 +17,6 @@ RubyVM::Instructions = RubyVM::BareInstructions.to_a + \
RubyVM::OperandsUnifications.to_a + \
RubyVM::InstructionsUnifications.to_a
+require_relative 'zjit_instructions'
require_relative 'trace_instructions'
RubyVM::Instructions.freeze
diff --git a/tool/ruby_vm/models/zjit_instructions.rb b/tool/ruby_vm/models/zjit_instructions.rb
new file mode 100644
index 0000000000..2bf190e3f7
--- /dev/null
+++ b/tool/ruby_vm/models/zjit_instructions.rb
@@ -0,0 +1,58 @@
+require_relative '../helpers/c_escape'
+require_relative 'bare_instructions'
+
+# Profile YARV instructions to optimize code generated by ZJIT
+class RubyVM::ZJITInstructions
+ 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::Instructions.filter(&:zjit_profile?).map {|i| new(i) }
+
+ def self.to_a
+ @instances
+ end
+
+ RubyVM::Instructions.push(*to_a)
+end
diff --git a/tool/ruby_vm/views/_insn_sp_pc_dependency.erb b/tool/ruby_vm/views/_insn_sp_pc_dependency.erb
new file mode 100644
index 0000000000..7e7d5ade11
--- /dev/null
+++ b/tool/ruby_vm/views/_insn_sp_pc_dependency.erb
@@ -0,0 +1,27 @@
+%# -*- 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.is_a?(RubyVM::ZJITInstructions) && !insn.handles_sp? && insn.always_leaf?
+ case <%= insn.bin %>:
+% end
+% end
+ return true;
+ default:
+ return false;
+ }
+}
diff --git a/tool/ruby_vm/views/_zjit_helpers.erb b/tool/ruby_vm/views/_zjit_helpers.erb
new file mode 100644
index 0000000000..0e4e8166e4
--- /dev/null
+++ b/tool/ruby_vm/views/_zjit_helpers.erb
@@ -0,0 +1,14 @@
+MAYBE_UNUSED(static int vm_insn_to_zjit_insn(int insn));
+
+static int
+vm_insn_to_zjit_insn(int insn)
+{
+ switch (insn) {
+% RubyVM::ZJITInstructions.to_a.each do |insn|
+ case BIN(<%= insn.jump_destination %>):
+ return <%= insn.bin %>;
+% end
+ default:
+ return insn;
+ }
+}
diff --git a/tool/ruby_vm/views/_zjit_instruction.erb b/tool/ruby_vm/views/_zjit_instruction.erb
new file mode 100644
index 0000000000..45800f8c63
--- /dev/null
+++ b/tool/ruby_vm/views/_zjit_instruction.erb
@@ -0,0 +1,8 @@
+/* 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 %>);
+}
diff --git a/tool/ruby_vm/views/insns.inc.erb b/tool/ruby_vm/views/insns.inc.erb
index 29981a8a2d..cf34489279 100644
--- a/tool/ruby_vm/views/insns.inc.erb
+++ b/tool/ruby_vm/views/insns.inc.erb
@@ -12,6 +12,9 @@
edit: __FILE__,
} -%>
+#ifndef INSNS_INC
+#define INSNS_INC 1
+
/* BIN : Basic Instruction Name */
#define BIN(n) YARVINSN_##n
@@ -24,3 +27,5 @@ enum ruby_vminsn_type {
#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 110d9dfae5..6ba12a856e 100644
--- a/tool/ruby_vm/views/insns_info.inc.erb
+++ b/tool/ruby_vm/views/insns_info.inc.erb
@@ -17,5 +17,6 @@
<%= render 'insn_operand_info' %>
<%= render 'leaf_helpers' %>
<%= render 'sp_inc_helpers' %>
+<%= render 'zjit_helpers' %>
<%= render 'attributes' %>
<%= render 'comptime_insn_stack_increase' %>
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
new file mode 100644
index 0000000000..793528af5d
--- /dev/null
+++ b/tool/ruby_vm/views/lib/ruby_vm/rjit/instruction.rb.erb
@@ -0,0 +1,14 @@
+module RubyVM::RJIT # :nodoc: all
+ Instruction = Data.define(:name, :bin, :len, :operands)
+
+ INSNS = {
+% RubyVM::Instructions.each_with_index do |insn, i|
+ <%= i %> => Instruction.new(
+ name: :<%= insn.name %>,
+ bin: <%= i %>, # BIN(<%= insn.name %>)
+ len: <%= insn.width %>, # insn_len
+ operands: <%= (insn.operands unless insn.name.start_with?(/trace_|zjit_/)).inspect %>,
+ ),
+% end
+ }
+end
diff --git a/tool/ruby_vm/views/vm.inc.erb b/tool/ruby_vm/views/vm.inc.erb
index c1a3faf60a..b92d6d31bc 100644
--- a/tool/ruby_vm/views/vm.inc.erb
+++ b/tool/ruby_vm/views/vm.inc.erb
@@ -25,6 +25,10 @@
<%= render 'insn_entry', locals: { insn: insn } -%>
% end
%
+% RubyVM::ZJITInstructions.to_a.each do |insn|
+<%= render 'zjit_instruction', locals: { insn: insn } -%>
+% end
+%
% RubyVM::TraceInstructions.to_a.each do |insn|
<%= render 'trace_instruction', locals: { insn: insn } -%>
% end