diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index f19629ec0e4e85..e9ce905e2c7073 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -5535,3 +5535,23 @@ def compiled_method
# Resume the fiber — compiled_method's iseq must still be valid
fiber.resume.to_s
}
+
+# regression test for register mapping of methods with over 256 locals
+# [Bug #22074]
+assert_equal "ok", %q{
+ source = +"def many_locals\n"
+ source << " total = 0\n"
+
+ 128.times do |i|
+ source << " y#{i} = 1\n"
+ source << " x#{i} = Object.new\n"
+ end
+
+ source << " total += 1\n"
+ source << " raise total.inspect unless total == 1\n"
+ source << "end\n"
+
+ eval(source)
+ many_locals
+ "ok"
+}
diff --git a/pathname_builtin.rb b/pathname_builtin.rb
index 51b6fd6a071d14..63426812204082 100644
--- a/pathname_builtin.rb
+++ b/pathname_builtin.rb
@@ -589,17 +589,17 @@ def each_filename # :yield: filename
# ```ruby
# # Absolute path.
# Pathname('/path/to/some/file.rb').descend {|pn| p pn }
- # #
- # #
- # #
- # #
- # #
+ # # #
+ # # #
+ # # #
+ # # #
+ # # #
# # Relative path.
# Pathname('path/to/some/file.rb').descend {|pn| p pn }
- # #
- # #
- # #
- # #
+ # # #
+ # # #
+ # # #
+ # # #
# ```
#
# With no block given, returns a new Enumerator.
@@ -811,42 +811,39 @@ def children(with_directory=true)
result
end
- # Iterates over the children of the directory
- # (files and subdirectories, not recursive).
- #
- # It yields Pathname object for each child.
+ # :markup: markdown
#
- # By default, the yielded pathnames will have enough information to access
- # the files.
+ # call-seq:
+ # each_child(with_dirnames = true) {|entry| ... } -> array_of_pathnames
+ # each_child(with_dirnames = true) -> new_enumerator
#
- # If you set +with_directory+ to +false+, then the returned pathnames will
- # contain the filename only.
+ # With a block given and `with_dirnames` given as `true` (the default),
+ # yields a new pathname for each child
+ # of the entry represented by `self`;
+ # returns an array of those pathnames:
#
- # Pathname("/usr/local").each_child {|f| p f }
- # #=> #
- # # #
- # # #
- # # #
- # # #
- # # #
- # # #
- # # #
+ # ```ruby
+ # Pathname('include').each_child {|child| p child }
+ # # #
+ # # #
+ # # => [#, #]
+ # ```
#
- # Pathname("/usr/local").each_child(false) {|f| p f }
- # #=> #
- # # #
- # # #
- # # #
- # # #
- # # #
- # # #
- # # #
+ # With a block given and `with_dirnames` given as `false`,
+ # yields a new pathname for each child
+ # of the entry represented by `self` with its dirname omitted;
+ # returns an array of those pathnames:
#
- # Note that the results never contain the entries +.+ and +..+ in
- # the directory because they are not children.
+ # ```ruby
+ # Pathname('include').each_child(false) {|child| p child }
+ # # #
+ # # #
+ # # => [#, #]
+ # ```
#
- # See Pathname#children
+ # Note that entries `'.'` and `'..'` are not children.
#
+ # With no block given, returns a new Enumerator.
def each_child(with_directory=true, &b)
children(with_directory).each(&b)
end
@@ -1639,10 +1636,27 @@ class << self
# Pathname object.
def entries() Dir.entries(@path).map {|f| self.class.new(f) } end
- # Iterates over the entries (files and subdirectories) in the directory. It
- # yields a Pathname object for each entry.
+ # :markup: markdown
#
- # This method has existed since 1.8.1.
+ # call-seq:
+ # each_entry {|entry| ... } -> nil
+ # each_entry -> new_enumerator
+ #
+ # With a block given,
+ # yields a new pathname for each entry
+ # in the entry represented by `self`;
+ # returns `nil`:
+ #
+ # ```ruby
+ # Pathname('include').each_entry {|entry| p entry }
+ # # #
+ # # #
+ # # #
+ # # #
+ # # => nil
+ # ```
+ #
+ # With no block given, returns a new Enumerator.
def each_entry(&block) # :yield: pathname
return to_enum(__method__) unless block_given?
Dir.foreach(@path) {|f| yield self.class.new(f) }
@@ -1661,8 +1675,24 @@ def opendir(&block) # :yield: dir
end
class Pathname # * mixed *
- # Removes a file or directory, using File.unlink or
- # Dir.unlink as necessary.
+ #
+ # :markup: markdown
+ #
+ # call-seq:
+ # unlink -> 1 or 0
+ #
+ # Removes the file or directory represented by `self`, using:
+ #
+ # - File.unlink, if `self` represents a file; returns `1`.
+ # - Dir.unlink, if `self` represents a directory; returns `0`.
+ #
+ # Examples:
+ #
+ # ```ruby
+ # Pathname(Tempfile.create).unlink # => 1
+ # Pathname(Pathname.mktmpdir).unlink # => 0
+ # ```
+ #
def unlink()
Dir.unlink @path
rescue Errno::ENOTDIR
diff --git a/yjit/src/backend/ir.rs b/yjit/src/backend/ir.rs
index 3fb67bc7cc1584..e14f3f9cb28e95 100644
--- a/yjit/src/backend/ir.rs
+++ b/yjit/src/backend/ir.rs
@@ -6,7 +6,7 @@ use crate::codegen::{gen_counted_exit, gen_outlined_exit};
use crate::cruby::{vm_stack_canary, SIZEOF_VALUE_I32, VALUE, VM_ENV_DATA_SIZE};
use crate::virtualmem::CodePtr;
use crate::asm::{CodeBlock, OutlinedCb};
-use crate::core::{Context, RegMapping, RegOpnd, MAX_CTX_TEMPS};
+use crate::core::{Context, RegMapping, RegOpnd, MAX_CTX_LOCALS, MAX_CTX_TEMPS};
use crate::options::*;
use crate::stats::*;
@@ -242,7 +242,9 @@ impl Opnd
let last_idx = stack_size as i32 + VM_ENV_DATA_SIZE as i32 - 1;
assert!(last_idx <= idx, "Local index {} must be >= last local index {}", idx, last_idx);
assert!(idx <= last_idx + num_locals as i32, "Local index {} must be < last local index {} + local size {}", idx, last_idx, num_locals);
- RegOpnd::Local((last_idx + num_locals as i32 - idx) as u8)
+ // Indices that don't fit in u8 are capped to MAX_CTX_LOCALS, which is untrackable.
+ let local_idx = last_idx + num_locals as i32 - idx;
+ RegOpnd::Local(local_idx.try_into().unwrap_or(MAX_CTX_LOCALS as u8))
} else {
assert!(idx < stack_size as i32);
RegOpnd::Stack((stack_size as i32 - idx - 1) as u8)
diff --git a/yjit/src/core.rs b/yjit/src/core.rs
index edb7db3acc5455..d08cd1fb26fac3 100644
--- a/yjit/src/core.rs
+++ b/yjit/src/core.rs
@@ -34,7 +34,7 @@ use crate::invariants::*;
pub const MAX_CTX_TEMPS: usize = 8;
// Maximum number of local variable types or registers we keep track of
-const MAX_CTX_LOCALS: usize = 8;
+pub const MAX_CTX_LOCALS: usize = 8;
/// An index into `ISEQ_BODY(iseq)->iseq_encoded`. Points
/// to a YARV instruction or an instruction operand.
diff --git a/zjit/src/backend/lir.rs b/zjit/src/backend/lir.rs
index 467cd5b4de5624..975c46529a2af8 100644
--- a/zjit/src/backend/lir.rs
+++ b/zjit/src/backend/lir.rs
@@ -2661,24 +2661,8 @@ impl Assembler
asm.cret(Opnd::UImm(Qundef.as_u64()));
}
- /// Compile the main side-exit code. This function takes only SideExit so
- /// that it can be safely deduplicated by using SideExit as a dedup key.
- fn compile_exit(asm: &mut Assembler, exit: &SideExit) {
- compile_exit_save_state(asm, exit);
- // If this side exit should trigger recompilation, call the recompile
- // function after saving VM state. The ccall must happen after
- // compile_exit_save_state because it clobbers caller-saved registers
- // that may hold stack/local operands we need to save.
+ fn compile_exit_recompile(asm: &mut Assembler, exit: &SideExit) {
if let Some(recompile) = &exit.recompile {
- if cfg!(feature = "runtime_checks") {
- // Clear jit_return to fully materialize the frame. This must happen
- // before any C call in the exit path (e.g. exit_recompile)
- // because that C call can trigger GC, which walks the stack and would
- // hit the CFP_JIT_RETURN assertion if jit_return still holds the
- // runtime_checks poison value (JIT_RETURN_POISON).
- asm_comment!(asm, "clear cfp->jit_return");
- asm.store(Opnd::mem(64, CFP, RUBY_OFFSET_CFP_JIT_RETURN), 0.into());
- }
use crate::codegen::exit_recompile;
asm_comment!(asm, "profile and maybe recompile");
@@ -2692,6 +2676,38 @@ impl Assembler
})
);
}
+ }
+
+ /// Compile the main side-exit code. The side exit will optionally record a traced exit
+ /// stack, optionally trigger recompilation, and then return to the interpreter. Shared
+ /// exits pass no trace reason so they can still be deduplicated by SideExit.
+ /// IOW, we should never pass a trace reason if we expect the exit to be
+ /// deduplicated.
+ fn compile_exit(asm: &mut Assembler, exit: &SideExit, trace_reason: Option) {
+ // Save VM state before the ccall so that
+ // rb_profile_frames sees valid cfp->pc and the
+ // ccall doesn't clobber caller-saved registers
+ // holding stack/local operands.
+ compile_exit_save_state(asm, exit);
+ if trace_reason.is_some() || exit.recompile.is_some() {
+ if cfg!(feature = "runtime_checks") {
+ // Clear jit_return to fully materialize the frame. This must happen
+ // before any C call in the exit path because that C call can trigger
+ // GC, which walks the stack and would hit the CFP_JIT_RETURN assertion
+ // if jit_return still holds the runtime_checks poison value
+ // (JIT_RETURN_POISON).
+ asm_comment!(asm, "clear cfp->jit_return");
+ asm.store(Opnd::mem(64, CFP, RUBY_OFFSET_CFP_JIT_RETURN), 0.into());
+ }
+ }
+ if let Some(reason) = trace_reason {
+ // Leak a CString with the reason so it's available at runtime
+ let reason_cstr = std::ffi::CString::new(reason.to_string())
+ .unwrap_or_else(|_| std::ffi::CString::new("unknown").unwrap());
+ let reason_ptr = reason_cstr.into_raw() as *const u8;
+ asm_ccall!(asm, rb_zjit_record_exit_stack, Opnd::const_ptr(reason_ptr));
+ }
+ compile_exit_recompile(asm, exit);
compile_exit_return(asm);
}
@@ -2768,17 +2784,7 @@ impl Assembler
}
if should_record_exit {
- // Save VM state before the ccall so that
- // rb_profile_frames sees valid cfp->pc and the
- // ccall doesn't clobber caller-saved registers
- // holding stack/local operands.
- compile_exit_save_state(self, &exit);
- // Leak a CString with the reason so it's available at runtime
- let reason_cstr = std::ffi::CString::new(reason.to_string())
- .unwrap_or_else(|_| std::ffi::CString::new("unknown").unwrap());
- let reason_ptr = reason_cstr.into_raw() as *const u8;
- asm_ccall!(self, rb_zjit_record_exit_stack, Opnd::const_ptr(reason_ptr));
- compile_exit_return(self);
+ compile_exit(self, &exit, Some(reason));
} else {
// If the side exit has already been compiled, jump to it.
// Otherwise, let it fall through and compile the exit next.
@@ -2798,7 +2804,7 @@ impl Assembler
let new_exit = self.new_label("side_exit");
self.write_label(new_exit.clone());
asm_comment!(self, "Exit: {pc}");
- compile_exit(self, &exit);
+ compile_exit(self, &exit, None);
compiled_exits.insert(exit, new_exit.unwrap_label());
new_exit
};
diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs
index f4d62fc7bcef43..7d7aca1c83d44c 100644
--- a/zjit/src/codegen.rs
+++ b/zjit/src/codegen.rs
@@ -679,7 +679,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
&Insn::GuardBitEquals { val, expected, reason, state, recompile } => gen_guard_bit_equals(jit, asm, opnd!(val), expected, reason, recompile, &function.frame_state(state)),
&Insn::GuardAnyBitSet { val, mask, reason, state, .. } => gen_guard_any_bit_set(jit, asm, opnd!(val), mask, reason, &function.frame_state(state)),
&Insn::GuardNoBitsSet { val, mask, reason, state, .. } => gen_guard_no_bits_set(jit, asm, opnd!(val), mask, reason, &function.frame_state(state)),
- &Insn::GuardLess { left, right, state } => gen_guard_less(jit, asm, opnd!(left), opnd!(right), &function.frame_state(state)),
+ &Insn::GuardLess { left, right, reason, state } => gen_guard_less(jit, asm, opnd!(left), opnd!(right), reason, &function.frame_state(state)),
&Insn::GuardGreaterEq { left, right, state, .. } => gen_guard_greater_eq(jit, asm, opnd!(left), opnd!(right), &function.frame_state(state)),
Insn::PatchPoint { invariant, state } => no_output!(gen_patch_point(jit, asm, invariant, &function.frame_state(*state))),
Insn::CCall { cfunc, recv, args, name, owner: _, return_type: _, elidable: _ } => gen_ccall(asm, *cfunc, *name, opnd!(recv), opnds!(args)),
@@ -885,9 +885,9 @@ fn gen_getblockparam(jit: &mut JITState, asm: &mut Assembler, ep_offset: u32, le
asm.load(Opnd::mem(VALUE_BITS, ep, offset))
}
-fn gen_guard_less(jit: &mut JITState, asm: &mut Assembler, left: Opnd, right: Opnd, state: &FrameState) -> Opnd {
+fn gen_guard_less(jit: &mut JITState, asm: &mut Assembler, left: Opnd, right: Opnd, reason: SideExitReason, state: &FrameState) -> Opnd {
asm.cmp(left, right);
- asm.jge(jit, side_exit(jit, state, SideExitReason::GuardLess));
+ asm.jge(jit, side_exit(jit, state, reason));
left
}
diff --git a/zjit/src/cruby.rs b/zjit/src/cruby.rs
index 6a5dd234bb56e3..14db7c57d75718 100644
--- a/zjit/src/cruby.rs
+++ b/zjit/src/cruby.rs
@@ -1471,6 +1471,19 @@ pub fn get_class_name(class: VALUE) -> String {
name
}
+// Return the module name for a given module or class. For anonymous modules, returns None since
+// rb_mod_name returns Qnil.
+pub fn get_module_name(module: VALUE) -> Option {
+ // type checks for rb_mod_name()
+ assert!(unsafe { RB_TYPE_P(module, RUBY_T_MODULE) || RB_TYPE_P(module, RUBY_T_CLASS) }, "Expected class or module");
+ let name = unsafe { rb_mod_name(module) };
+ if name == Qnil {
+ None
+ } else {
+ Some(ruby_str_to_rust_string(name))
+ }
+}
+
#[cfg(test)]
mod class_name_tests {
diff --git a/zjit/src/cruby_methods.rs b/zjit/src/cruby_methods.rs
index db0993072166ca..05b00550328f11 100644
--- a/zjit/src/cruby_methods.rs
+++ b/zjit/src/cruby_methods.rs
@@ -367,7 +367,7 @@ fn inline_array_aref(fun: &mut hir::Function, block: hir::BlockId, recv: hir::In
let index = fun.coerce_to(block, index, types::Fixnum, state);
let index = fun.push_insn(block, hir::Insn::UnboxFixnum { val: index });
let length = fun.push_insn(block, hir::Insn::ArrayLength { array: recv });
- let index = fun.push_insn(block, hir::Insn::GuardLess { left: index, right: length, state });
+ let index = fun.push_insn(block, hir::Insn::GuardLess { left: index, right: length, reason: SideExitReason::GuardLess, state });
let index = fun.push_insn(block, hir::Insn::AdjustBounds { index, length });
let zero = fun.push_insn(block, hir::Insn::Const { val: hir::Const::CInt64(0) });
use crate::hir::SideExitReason;
@@ -392,7 +392,7 @@ fn inline_array_aset(fun: &mut hir::Function, block: hir::BlockId, recv: hir::In
// Bounds check: unbox Fixnum index and guard 0 <= idx < length.
let index = fun.push_insn(block, hir::Insn::UnboxFixnum { val: index });
let length = fun.push_insn(block, hir::Insn::ArrayLength { array: recv });
- let index = fun.push_insn(block, hir::Insn::GuardLess { left: index, right: length, state });
+ let index = fun.push_insn(block, hir::Insn::GuardLess { left: index, right: length, reason: SideExitReason::GuardLess, state });
let index = fun.push_insn(block, hir::Insn::AdjustBounds { index, length });
let zero = fun.push_insn(block, hir::Insn::Const { val: hir::Const::CInt64(0) });
use crate::hir::SideExitReason;
@@ -492,7 +492,7 @@ fn inline_string_getbyte(fun: &mut hir::Function, block: hir::BlockId, recv: hir
// the data dependency is gone (say, the StringGetbyte is elided), they can also be elided.
//
// This is unlike most other guards.
- let unboxed_index = fun.push_insn(block, hir::Insn::GuardLess { left: unboxed_index, right: len, state });
+ let unboxed_index = fun.push_insn(block, hir::Insn::GuardLess { left: unboxed_index, right: len, reason: SideExitReason::GuardLess, state });
let unboxed_index = fun.push_insn(block, hir::Insn::AdjustBounds { index: unboxed_index, length: len });
let zero = fun.push_insn(block, hir::Insn::Const { val: hir::Const::CInt64(0) });
use crate::hir::SideExitReason;
@@ -516,7 +516,7 @@ fn inline_string_setbyte(fun: &mut hir::Function, block: hir::BlockId, recv: hir
offset: RUBY_OFFSET_RSTRING_LEN as i32,
return_type: types::CInt64,
});
- let unboxed_index = fun.push_insn(block, hir::Insn::GuardLess { left: unboxed_index, right: len, state });
+ let unboxed_index = fun.push_insn(block, hir::Insn::GuardLess { left: unboxed_index, right: len, reason: SideExitReason::GuardLess, state });
let unboxed_index = fun.push_insn(block, hir::Insn::AdjustBounds { index: unboxed_index, length: len });
let zero = fun.push_insn(block, hir::Insn::Const { val: hir::Const::CInt64(0) });
use crate::hir::SideExitReason;
diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs
index fdc82c9552e41f..93dbbec690ab2d 100644
--- a/zjit/src/hir.rs
+++ b/zjit/src/hir.rs
@@ -1157,7 +1157,7 @@ pub enum Insn {
/// Side-exit if left is not greater than or equal to right (both operands are C long).
GuardGreaterEq { left: InsnId, right: InsnId, reason: SideExitReason, state: InsnId },
/// Side-exit if left is not less than right (both operands are C long).
- GuardLess { left: InsnId, right: InsnId, state: InsnId },
+ GuardLess { left: InsnId, right: InsnId, reason: SideExitReason, state: InsnId },
/// Generate no code (or padding if necessary) and insert a patch point
/// that can be rewritten to a side exit when the Invariant is broken.
@@ -1311,7 +1311,7 @@ macro_rules! for_each_operand_impl {
$visit_one!(state);
}
Insn::GuardGreaterEq { left, right, state, .. }
- | Insn::GuardLess { left, right, state } => {
+ | Insn::GuardLess { left, right, state, .. } => {
$visit_one!(left);
$visit_one!(right);
$visit_one!(state);
@@ -2099,7 +2099,13 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
Insn::GuardType { val, guard_type, .. } => { write!(f, "GuardType {val}, {}", guard_type.print(self.ptr_map)) },
Insn::RefineType { val, new_type, .. } => { write!(f, "RefineType {val}, {}", new_type.print(self.ptr_map)) },
Insn::HasType { val, expected, .. } => { write!(f, "HasType {val}, {}", expected.print(self.ptr_map)) },
- Insn::GuardBitEquals { val, expected, .. } => { write!(f, "GuardBitEquals {val}, {}", expected.print(self.ptr_map)) },
+ Insn::GuardBitEquals { val, expected, recompile, .. } => {
+ write!(f, "GuardBitEquals {val}, {}", expected.print(self.ptr_map))?;
+ if recompile.is_some() {
+ write!(f, " recompile")?;
+ }
+ return Ok(())
+ },
Insn::GuardAnyBitSet { val, mask, mask_name: Some(name), .. } => { write!(f, "GuardAnyBitSet {val}, {name}={}", mask.print(self.ptr_map)) },
Insn::GuardAnyBitSet { val, mask, .. } => { write!(f, "GuardAnyBitSet {val}, {}", mask.print(self.ptr_map)) },
Insn::GuardNoBitsSet { val, mask, mask_name: Some(name), .. } => { write!(f, "GuardNoBitsSet {val}, {name}={}", mask.print(self.ptr_map)) },
@@ -3323,10 +3329,18 @@ impl Function {
/// - `StaticallyKnown` if the receiver's exact class is known at compile-time
/// - Result of [`Self::resolve_receiver_type_from_profile`] if we need to check profile data
fn resolve_receiver_type(&self, recv: InsnId, recv_type: Type, insn_idx: YarvInsnIdx) -> ReceiverTypeResolution {
- if let Some(class) = recv_type.runtime_exact_ruby_class() {
- return ReceiverTypeResolution::StaticallyKnown { class };
+ match self.resolve_receiver_type_from_profile(recv, insn_idx) {
+ ReceiverTypeResolution::NoProfile => {
+ // Use known type information as a fallback because it doesn't have shape
+ // information (and we can generally eliminate duplicate guards).
+ if let Some(class) = recv_type.runtime_exact_ruby_class() {
+ ReceiverTypeResolution::StaticallyKnown { class }
+ } else {
+ ReceiverTypeResolution::NoProfile
+ }
+ }
+ resolution => resolution,
}
- self.resolve_receiver_type_from_profile(recv, insn_idx)
}
fn polymorphic_summary(&self, profiles: &ProfileOracle, recv: InsnId, insn_idx: YarvInsnIdx) -> Option {
@@ -5088,6 +5102,15 @@ impl Function {
_ => insn_id,
}
}
+ Insn::ArrayLength { array } => {
+ match self.type_of(array).ruby_object() {
+ Some(array_obj) if array_obj.is_frozen() => {
+ let length = unsafe { rb_jit_array_len(array_obj) };
+ self.new_insn(Insn::Const { val: Const::CInt64(length) })
+ }
+ _ => insn_id,
+ }
+ }
Insn::UnboxFixnum { val } => {
let recv_type = self.type_of(val);
match recv_type.fixnum_value() {
@@ -5107,6 +5130,18 @@ impl Function {
_ => insn_id,
}
},
+ Insn::GuardLess { left, right, state, reason } => {
+ let left_num = self.type_of(left).cint64_value();
+ let right_num = self.type_of(right).cint64_value();
+ match (left_num, right_num) {
+ (Some(l), Some(r)) if l < r => {
+ self.make_equal_to(insn_id, left);
+ continue
+ },
+ (Some(_), Some(_)) => self.new_insn(Insn::SideExit { state, reason, recompile: None }),
+ _ => insn_id,
+ }
+ },
Insn::GuardBitEquals { val, expected, .. } => {
let recv_type = self.type_of(val);
if recv_type.has_value(expected) {
diff --git a/zjit/src/hir/opt_tests.rs b/zjit/src/hir/opt_tests.rs
index 3435347d338c21..4a83b40e38e5b9 100644
--- a/zjit/src/hir/opt_tests.rs
+++ b/zjit/src/hir/opt_tests.rs
@@ -222,13 +222,13 @@ mod hir_opt_tests {
bb3(v9:BasicObject, v10:BasicObject):
v14:Fixnum[0] = Const Value(0)
PatchPoint MethodRedefined(Integer@0x1008, *@0x1010, cme:0x1018)
- v35:Fixnum = GuardType v10, Fixnum
- v44:Fixnum[0] = Const Value(0)
- v45:Fixnum[0] = Const Value(0)
- PatchPoint MethodRedefined(Integer@0x1008, +@0x1040, cme:0x1048)
+ v36:Fixnum = GuardType v10, Fixnum
v46:Fixnum[0] = Const Value(0)
+ v47:Fixnum[0] = Const Value(0)
+ PatchPoint MethodRedefined(Integer@0x1008, +@0x1040, cme:0x1048)
+ v48:Fixnum[0] = Const Value(0)
CheckInterrupts
- Return v46
+ Return v48
");
}
@@ -608,9 +608,9 @@ mod hir_opt_tests {
v10:Fixnum[4] = Const Value(4)
v12:Fixnum[-7] = Const Value(-7)
PatchPoint MethodRedefined(Integer@0x1000, &@0x1008, cme:0x1010)
- v24:Fixnum[0] = Const Value(0)
+ v25:Fixnum[0] = Const Value(0)
CheckInterrupts
- Return v24
+ Return v25
");
}
@@ -637,9 +637,9 @@ mod hir_opt_tests {
v10:Fixnum[-4] = Const Value(-4)
v12:Fixnum[7] = Const Value(7)
PatchPoint MethodRedefined(Integer@0x1000, &@0x1008, cme:0x1010)
- v24:Fixnum[4] = Const Value(4)
+ v25:Fixnum[4] = Const Value(4)
CheckInterrupts
- Return v24
+ Return v25
");
}
@@ -666,9 +666,9 @@ mod hir_opt_tests {
v10:Fixnum[4] = Const Value(4)
v12:Fixnum[1] = Const Value(1)
PatchPoint MethodRedefined(Integer@0x1000, |@0x1008, cme:0x1010)
- v24:Fixnum[5] = Const Value(5)
+ v25:Fixnum[5] = Const Value(5)
CheckInterrupts
- Return v24
+ Return v25
");
}
@@ -695,9 +695,9 @@ mod hir_opt_tests {
v10:Fixnum[-4] = Const Value(-4)
v12:Fixnum[1] = Const Value(1)
PatchPoint MethodRedefined(Integer@0x1000, |@0x1008, cme:0x1010)
- v24:Fixnum[-3] = Const Value(-3)
+ v25:Fixnum[-3] = Const Value(-3)
CheckInterrupts
- Return v24
+ Return v25
");
}
@@ -724,9 +724,9 @@ mod hir_opt_tests {
v10:Fixnum[4] = Const Value(4)
v12:Fixnum[-1] = Const Value(-1)
PatchPoint MethodRedefined(Integer@0x1000, |@0x1008, cme:0x1010)
- v24:Fixnum[-1] = Const Value(-1)
+ v25:Fixnum[-1] = Const Value(-1)
CheckInterrupts
- Return v24
+ Return v25
");
}
@@ -1076,9 +1076,8 @@ mod hir_opt_tests {
PatchPoint NoSingletonClass(Array@0x1008)
PatchPoint MethodRedefined(Array@0x1008, []@0x1010, cme:0x1018)
v32:CInt64[-10] = Const CInt64(-10)
- v26:CInt64 = ArrayLength v11
- v27:CInt64[-10] = GuardLess v32, v26
- v28:CInt64 = AdjustBounds v27, v26
+ v33:CInt64[3] = Const CInt64(3)
+ v28:CInt64 = AdjustBounds v32, v33
v29:CInt64[0] = Const CInt64(0)
v30:CInt64 = GuardGreaterEq v28, v29
v31:BasicObject = ArrayAref v11, v30
@@ -1905,10 +1904,10 @@ mod hir_opt_tests {
bb3(v9:BasicObject, v10:BasicObject):
v14:Fixnum[1] = Const Value(1)
PatchPoint MethodRedefined(Integer@0x1008, +@0x1010, cme:0x1018)
- v26:Fixnum = GuardType v10, Fixnum
- v27:Fixnum = FixnumAdd v14, v26
+ v27:Fixnum = GuardType v10, Fixnum
+ v28:Fixnum = FixnumAdd v14, v27
CheckInterrupts
- Return v27
+ Return v28
");
}
@@ -2105,10 +2104,10 @@ mod hir_opt_tests {
bb3(v9:BasicObject, v10:BasicObject):
v14:Fixnum[1] = Const Value(1)
PatchPoint MethodRedefined(Integer@0x1008, <@0x1010, cme:0x1018)
- v26:Fixnum = GuardType v10, Fixnum
- v27:BoolExact = FixnumLt v14, v26
+ v27:Fixnum = GuardType v10, Fixnum
+ v28:BoolExact = FixnumLt v14, v27
CheckInterrupts
- Return v27
+ Return v28
");
}
@@ -3207,10 +3206,10 @@ mod hir_opt_tests {
bb3(v8:BasicObject, v9:NilClass):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, M)
- v29:ModuleExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
+ v29:ModuleExact[M@0x1008] = Const Value(VALUE(0x1008))
PatchPoint NoSingletonClass(Module@0x1010)
PatchPoint MethodRedefined(Module@0x1010, name@0x1018, cme:0x1020)
- v33:StringExact|NilClass = CCall v29, :Module#name@0x1048
+ v34:StringExact|NilClass = CCall v29, :Module#name@0x1048
PatchPoint NoEPEscape(test)
v21:Fixnum[1] = Const Value(1)
CheckInterrupts
@@ -3266,7 +3265,7 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, C)
- v18:Class[C@0x1008] = Const Value(VALUE(0x1008))
+ v18:ClassSubclass[C@0x1008] = Const Value(VALUE(0x1008))
CheckInterrupts
Return v18
");
@@ -3291,13 +3290,13 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, String)
- v26:Class[String@0x1008] = Const Value(VALUE(0x1008))
+ v26:ClassSubclass[String@0x1008] = Const Value(VALUE(0x1008))
PatchPoint StableConstantNames(0x1010, Class)
- v29:Class[Class@0x1018] = Const Value(VALUE(0x1018))
+ v29:ClassSubclass[Class@0x1018] = Const Value(VALUE(0x1018))
PatchPoint StableConstantNames(0x1020, Module)
- v32:Class[Module@0x1028] = Const Value(VALUE(0x1028))
+ v32:ClassSubclass[Module@0x1028] = Const Value(VALUE(0x1028))
PatchPoint StableConstantNames(0x1030, BasicObject)
- v35:Class[BasicObject@0x1038] = Const Value(VALUE(0x1038))
+ v35:ClassSubclass[BasicObject@0x1038] = Const Value(VALUE(0x1038))
v18:ArrayExact = NewArray v26, v29, v32, v35
CheckInterrupts
Return v18
@@ -3323,9 +3322,9 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, Enumerable)
- v22:ModuleExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
+ v22:ModuleExact[Enumerable@0x1008] = Const Value(VALUE(0x1008))
PatchPoint StableConstantNames(0x1010, Kernel)
- v25:ModuleExact[VALUE(0x1018)] = Const Value(VALUE(0x1018))
+ v25:ModuleSubclass[Kernel@0x1018] = Const Value(VALUE(0x1018))
v14:ArrayExact = NewArray v22, v25
CheckInterrupts
Return v14
@@ -3353,7 +3352,7 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, MY_MODULE)
- v18:ModuleSubclass[VALUE(0x1008)] = Const Value(VALUE(0x1008))
+ v18:ModuleSubclass[MY_MODULE@0x1008] = Const Value(VALUE(0x1008))
CheckInterrupts
Return v18
");
@@ -3575,12 +3574,12 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, M)
- v20:ModuleExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
+ v20:ModuleExact[M@0x1008] = Const Value(VALUE(0x1008))
PatchPoint NoSingletonClass(Module@0x1010)
PatchPoint MethodRedefined(Module@0x1010, class@0x1018, cme:0x1020)
- v25:Class[Module@0x1010] = Const Value(VALUE(0x1010))
+ v26:ClassSubclass[Module@0x1010] = Const Value(VALUE(0x1010))
CheckInterrupts
- Return v25
+ Return v26
");
}
@@ -4392,7 +4391,7 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, Kernel)
- v18:ModuleExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
+ v18:ModuleSubclass[Kernel@0x1008] = Const Value(VALUE(0x1008))
CheckInterrupts
Return v18
");
@@ -4423,7 +4422,7 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, Foo::Bar::C)
- v18:Class[Foo::Bar::C@0x1008] = Const Value(VALUE(0x1008))
+ v18:ClassSubclass[Foo::Bar::C@0x1008] = Const Value(VALUE(0x1008))
CheckInterrupts
Return v18
");
@@ -4449,13 +4448,13 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, C)
- v43:Class[C@0x1008] = Const Value(VALUE(0x1008))
+ v43:ClassSubclass[C@0x1008] = Const Value(VALUE(0x1008))
v12:NilClass = Const Value(nil)
PatchPoint MethodRedefined(C@0x1008, new@0x1009, cme:0x1010)
v46:ObjectSubclass[class_exact:C] = ObjectAllocClass C:VALUE(0x1008)
PatchPoint NoSingletonClass(C@0x1008)
PatchPoint MethodRedefined(C@0x1008, initialize@0x1038, cme:0x1040)
- v50:NilClass = Const Value(nil)
+ v51:NilClass = Const Value(nil)
CheckInterrupts
Return v46
");
@@ -4485,14 +4484,14 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, C)
- v46:Class[C@0x1008] = Const Value(VALUE(0x1008))
+ v46:ClassSubclass[C@0x1008] = Const Value(VALUE(0x1008))
v12:NilClass = Const Value(nil)
v15:Fixnum[1] = Const Value(1)
PatchPoint MethodRedefined(C@0x1008, new@0x1009, cme:0x1010)
v49:ObjectSubclass[class_exact:C] = ObjectAllocClass C:VALUE(0x1008)
PatchPoint NoSingletonClass(C@0x1008)
PatchPoint MethodRedefined(C@0x1008, initialize@0x1038, cme:0x1040)
- v52:BasicObject = SendDirect v49, 0x1068, :initialize (0x1078), v15
+ v53:BasicObject = SendDirect v49, 0x1068, :initialize (0x1078), v15
CheckInterrupts
Return v49
");
@@ -4517,13 +4516,13 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, Object)
- v43:Class[Object@0x1008] = Const Value(VALUE(0x1008))
+ v43:ClassSubclass[Object@0x1008] = Const Value(VALUE(0x1008))
v12:NilClass = Const Value(nil)
PatchPoint MethodRedefined(Object@0x1008, new@0x1009, cme:0x1010)
v46:ObjectExact = ObjectAllocClass Object:VALUE(0x1008)
PatchPoint NoSingletonClass(Object@0x1008)
PatchPoint MethodRedefined(Object@0x1008, initialize@0x1038, cme:0x1040)
- v50:NilClass = Const Value(nil)
+ v51:NilClass = Const Value(nil)
CheckInterrupts
Return v46
");
@@ -4548,13 +4547,13 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, BasicObject)
- v43:Class[BasicObject@0x1008] = Const Value(VALUE(0x1008))
+ v43:ClassSubclass[BasicObject@0x1008] = Const Value(VALUE(0x1008))
v12:NilClass = Const Value(nil)
PatchPoint MethodRedefined(BasicObject@0x1008, new@0x1009, cme:0x1010)
v46:BasicObjectExact = ObjectAllocClass BasicObject:VALUE(0x1008)
PatchPoint NoSingletonClass(BasicObject@0x1008)
PatchPoint MethodRedefined(BasicObject@0x1008, initialize@0x1038, cme:0x1040)
- v50:NilClass = Const Value(nil)
+ v51:NilClass = Const Value(nil)
CheckInterrupts
Return v46
");
@@ -4579,14 +4578,14 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, Hash)
- v43:Class[Hash@0x1008] = Const Value(VALUE(0x1008))
+ v43:ClassSubclass[Hash@0x1008] = Const Value(VALUE(0x1008))
v12:NilClass = Const Value(nil)
PatchPoint MethodRedefined(Hash@0x1008, new@0x1009, cme:0x1010)
v46:HashExact = ObjectAllocClass Hash:VALUE(0x1008)
v47:Fixnum[0] = Const Value(0)
PatchPoint NoSingletonClass(Hash@0x1008)
PatchPoint MethodRedefined(Hash@0x1008, initialize@0x1038, cme:0x1040)
- v51:BasicObject = SendDirect v46, 0x1068, :initialize (0x1078), v47
+ v52:BasicObject = SendDirect v46, 0x1068, :initialize (0x1078), v47
CheckInterrupts
Return v46
");
@@ -4612,14 +4611,14 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, Array)
- v46:Class[Array@0x1008] = Const Value(VALUE(0x1008))
+ v46:ClassSubclass[Array@0x1008] = Const Value(VALUE(0x1008))
v12:NilClass = Const Value(nil)
v15:Fixnum[1] = Const Value(1)
PatchPoint MethodRedefined(Array@0x1008, new@0x1009, cme:0x1010)
PatchPoint MethodRedefined(Class@0x1038, new@0x1009, cme:0x1010)
- v52:BasicObject = CCallVariadic v46, :Array.new@0x1040, v15
+ v53:BasicObject = CCallVariadic v46, :Array.new@0x1040, v15
CheckInterrupts
- Return v52
+ Return v53
");
}
@@ -4642,7 +4641,7 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, Set)
- v43:Class[Set@0x1008] = Const Value(VALUE(0x1008))
+ v43:ClassSubclass[Set@0x1008] = Const Value(VALUE(0x1008))
v12:NilClass = Const Value(nil)
PatchPoint MethodRedefined(Set@0x1008, new@0x1009, cme:0x1010)
v17:HeapBasicObject = ObjectAlloc v43
@@ -4674,13 +4673,13 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, String)
- v43:Class[String@0x1008] = Const Value(VALUE(0x1008))
+ v43:ClassSubclass[String@0x1008] = Const Value(VALUE(0x1008))
v12:NilClass = Const Value(nil)
PatchPoint MethodRedefined(String@0x1008, new@0x1009, cme:0x1010)
PatchPoint MethodRedefined(Class@0x1038, new@0x1009, cme:0x1010)
- v53:BasicObject = CCallVariadic v43, :String.new@0x1040
+ v54:BasicObject = CCallVariadic v43, :String.new@0x1040
CheckInterrupts
- Return v53
+ Return v54
");
}
@@ -4703,7 +4702,7 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, Regexp)
- v47:Class[Regexp@0x1008] = Const Value(VALUE(0x1008))
+ v47:ClassSubclass[Regexp@0x1008] = Const Value(VALUE(0x1008))
v12:NilClass = Const Value(nil)
v15:StringExact[VALUE(0x1010)] = Const Value(VALUE(0x1010))
v16:StringExact = StringCopy v15
@@ -4711,7 +4710,7 @@ mod hir_opt_tests {
v50:RegexpExact = ObjectAllocClass Regexp:VALUE(0x1008)
PatchPoint NoSingletonClass(Regexp@0x1008)
PatchPoint MethodRedefined(Regexp@0x1008, initialize@0x1048, cme:0x1050)
- v54:BasicObject = CCallVariadic v50, :Regexp#initialize@0x1078, v16
+ v55:BasicObject = CCallVariadic v50, :Regexp#initialize@0x1078, v16
CheckInterrupts
Return v50
");
@@ -4737,11 +4736,11 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, C)
- v20:Class[C@0x1008] = Const Value(VALUE(0x1008))
+ v20:ClassSubclass[C@0x1008] = Const Value(VALUE(0x1008))
PatchPoint MethodRedefined(Class@0x1010, allocate@0x1018, cme:0x1020)
- v23:ObjectSubclass[class_exact:C] = ObjectAllocClass C:VALUE(0x1008)
+ v24:ObjectSubclass[class_exact:C] = ObjectAllocClass C:VALUE(0x1008)
CheckInterrupts
- Return v23
+ Return v24
");
}
@@ -4767,7 +4766,7 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, C)
- v22:Class[C@0x1008] = Const Value(VALUE(0x1008))
+ v22:ClassSubclass[C@0x1008] = Const Value(VALUE(0x1008))
v12:Fixnum[1] = Const Value(1)
v14:BasicObject = Send v22, :allocate, v12 # SendFallbackReason: SendWithoutBlock: unsupported method type Cfunc
CheckInterrupts
@@ -4797,11 +4796,11 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, SC)
- v20:Class[Class@0x1008] = Const Value(VALUE(0x1008))
+ v20:ClassSubclass[Class@0x1008] = Const Value(VALUE(0x1008))
PatchPoint MethodRedefined(Class@0x1010, allocate@0x1018, cme:0x1020)
- v23:BasicObject = CCallWithFrame v20, :Class.allocate@0x1048
+ v24:BasicObject = CCallWithFrame v20, :Class.allocate@0x1048
CheckInterrupts
- Return v23
+ Return v24
");
}
@@ -5270,7 +5269,7 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
v16:HeapBasicObject = GuardType v6, HeapBasicObject
v17:CShape = LoadField v16, :shape_id@0x1000
- v18:CShape[0x1001] = GuardBitEquals v17, CShape(0x1001)
+ v18:CShape[0x1001] = GuardBitEquals v17, CShape(0x1001) recompile
v19:StringExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
CheckInterrupts
Return v19
@@ -5296,7 +5295,7 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
v16:HeapBasicObject = GuardType v6, HeapBasicObject
v17:CShape = LoadField v16, :shape_id@0x1000
- v18:CShape[0x1001] = GuardBitEquals v17, CShape(0x1001)
+ v18:CShape[0x1001] = GuardBitEquals v17, CShape(0x1001) recompile
v19:NilClass = Const Value(nil)
CheckInterrupts
Return v19
@@ -5614,7 +5613,7 @@ mod hir_opt_tests {
PatchPoint SingleRactorMode
v21:HeapBasicObject = GuardType v6, HeapBasicObject
v22:CShape = LoadField v21, :shape_id@0x1000
- v23:CShape[0x1001] = GuardBitEquals v22, CShape(0x1001)
+ v23:CShape[0x1001] = GuardBitEquals v22, CShape(0x1001) recompile
StoreField v21, :@foo@0x1002, v10
WriteBarrier v21, v10
CheckInterrupts
@@ -5643,7 +5642,7 @@ mod hir_opt_tests {
PatchPoint SingleRactorMode
v21:HeapBasicObject = GuardType v6, HeapBasicObject
v22:CShape = LoadField v21, :shape_id@0x1000
- v23:CShape[0x1001] = GuardBitEquals v22, CShape(0x1001)
+ v23:CShape[0x1001] = GuardBitEquals v22, CShape(0x1001) recompile
StoreField v21, :@foo@0x1002, v10
WriteBarrier v21, v10
v26:CShape[0x1003] = Const CShape(0x1003)
@@ -5688,7 +5687,7 @@ mod hir_opt_tests {
PatchPoint SingleRactorMode
v28:HeapBasicObject = GuardType v6, HeapBasicObject
v29:CShape = LoadField v28, :shape_id@0x1000
- v30:CShape[0x1001] = GuardBitEquals v29, CShape(0x1001)
+ v30:CShape[0x1001] = GuardBitEquals v29, CShape(0x1001) recompile
StoreField v28, :@foo@0x1002, v10
WriteBarrier v28, v10
v33:CShape[0x1003] = Const CShape(0x1003)
@@ -6368,8 +6367,8 @@ mod hir_opt_tests {
v28:ArrayExact = GuardType v10, ArrayExact
PatchPoint NoSingletonClass(Array@0x1010)
PatchPoint MethodRedefined(Array@0x1010, to_s@0x1018, cme:0x1020)
- v33:BasicObject = CCallWithFrame v28, :Array#to_s@0x1048
- v20:String = AnyToString v28, str: v33
+ v34:BasicObject = CCallWithFrame v28, :Array#to_s@0x1048
+ v20:String = AnyToString v28, str: v34
v22:StringExact = StringConcat v14, v20
CheckInterrupts
Return v22
@@ -6459,12 +6458,12 @@ mod hir_opt_tests {
v12:Fixnum[0] = Const Value(0)
PatchPoint NoSingletonClass(Array@0x1010)
PatchPoint MethodRedefined(Array@0x1010, []@0x1018, cme:0x1020)
- v34:CInt64[0] = Const CInt64(0)
- v28:CInt64 = ArrayLength v23
- v29:CInt64[0] = GuardLess v34, v28
- v33:BasicObject = ArrayAref v23, v29
+ v35:CInt64[0] = Const CInt64(0)
+ v29:CInt64 = ArrayLength v23
+ v30:CInt64[0] = GuardLess v35, v29
+ v34:BasicObject = ArrayAref v23, v30
CheckInterrupts
- Return v33
+ Return v34
");
// TODO(max): Check the result of `S[0] = 5; test` using `inspect` to make sure that we
// actually do the load at run-time.
@@ -6491,12 +6490,9 @@ mod hir_opt_tests {
v13:Fixnum[1] = Const Value(1)
PatchPoint NoSingletonClass(Array@0x1008)
PatchPoint MethodRedefined(Array@0x1008, []@0x1010, cme:0x1018)
- v32:CInt64[1] = Const CInt64(1)
- v26:CInt64 = ArrayLength v11
- v27:CInt64[1] = GuardLess v32, v26
- v33:Fixnum[5] = Const Value(5)
+ v34:Fixnum[5] = Const Value(5)
CheckInterrupts
- Return v33
+ Return v34
");
}
@@ -6522,9 +6518,8 @@ mod hir_opt_tests {
PatchPoint NoSingletonClass(Array@0x1008)
PatchPoint MethodRedefined(Array@0x1008, []@0x1010, cme:0x1018)
v32:CInt64[-3] = Const CInt64(-3)
- v26:CInt64 = ArrayLength v11
- v27:CInt64[-3] = GuardLess v32, v26
- v28:CInt64 = AdjustBounds v27, v26
+ v33:CInt64[3] = Const CInt64(3)
+ v28:CInt64 = AdjustBounds v32, v33
v29:CInt64[0] = Const CInt64(0)
v30:CInt64 = GuardGreaterEq v28, v29
v31:BasicObject = ArrayAref v11, v30
@@ -6555,9 +6550,8 @@ mod hir_opt_tests {
PatchPoint NoSingletonClass(Array@0x1008)
PatchPoint MethodRedefined(Array@0x1008, []@0x1010, cme:0x1018)
v32:CInt64[-10] = Const CInt64(-10)
- v26:CInt64 = ArrayLength v11
- v27:CInt64[-10] = GuardLess v32, v26
- v28:CInt64 = AdjustBounds v27, v26
+ v33:CInt64[3] = Const CInt64(3)
+ v28:CInt64 = AdjustBounds v32, v33
v29:CInt64[0] = Const CInt64(0)
v30:CInt64 = GuardGreaterEq v28, v29
v31:BasicObject = ArrayAref v11, v30
@@ -6587,12 +6581,7 @@ mod hir_opt_tests {
v13:Fixnum[10] = Const Value(10)
PatchPoint NoSingletonClass(Array@0x1008)
PatchPoint MethodRedefined(Array@0x1008, []@0x1010, cme:0x1018)
- v32:CInt64[10] = Const CInt64(10)
- v26:CInt64 = ArrayLength v11
- v27:CInt64[10] = GuardLess v32, v26
- v33:NilClass = Const Value(nil)
- CheckInterrupts
- Return v33
+ SideExit GuardLess
");
}
@@ -6840,7 +6829,7 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, Foo)
- v22:Class[Foo@0x1008] = Const Value(VALUE(0x1008))
+ v22:ClassSubclass[Foo@0x1008] = Const Value(VALUE(0x1008))
v12:Fixnum[100] = Const Value(100)
PatchPoint MethodRedefined(Class@0x1010, identity@0x1018, cme:0x1020)
CheckInterrupts
@@ -7509,7 +7498,7 @@ mod hir_opt_tests {
PatchPoint MethodRedefined(C@0x1008, foo@0x1010, cme:0x1018)
v23:ObjectSubclass[class_exact:C] = GuardType v10, ObjectSubclass[class_exact:C]
v26:CShape = LoadField v23, :shape_id@0x1040
- v27:CShape[0x1041] = GuardBitEquals v26, CShape(0x1041)
+ v27:CShape[0x1041] = GuardBitEquals v26, CShape(0x1041) recompile
v28:BasicObject = LoadField v23, :@foo@0x1042
CheckInterrupts
Return v28
@@ -7777,7 +7766,7 @@ mod hir_opt_tests {
PatchPoint SingleRactorMode
v17:Module = GuardType v6, Module
v18:CShape = LoadField v17, :shape_id@0x1000
- v19:CShape[0x1001] = GuardBitEquals v18, CShape(0x1001)
+ v19:CShape[0x1001] = GuardBitEquals v18, CShape(0x1001) recompile
PatchPoint RootBoxOnly
v21:RubyValue = LoadField v17, :fields_obj@0x1002
v22:BasicObject = LoadField v21, :@foo@0x1003
@@ -7849,7 +7838,7 @@ mod hir_opt_tests {
PatchPoint SingleRactorMode
v17:Class = GuardType v6, Class
v18:CShape = LoadField v17, :shape_id@0x1000
- v19:CShape[0x1001] = GuardBitEquals v18, CShape(0x1001)
+ v19:CShape[0x1001] = GuardBitEquals v18, CShape(0x1001) recompile
PatchPoint RootBoxOnly
v21:RubyValue = LoadField v17, :fields_obj@0x1002
v22:BasicObject = LoadField v21, :@foo@0x1003
@@ -7914,7 +7903,7 @@ mod hir_opt_tests {
PatchPoint SingleRactorMode
v17:HeapBasicObject = GuardType v6, HeapBasicObject
v18:CShape = LoadField v17, :shape_id@0x1000
- v19:CShape[0x1001] = GuardBitEquals v18, CShape(0x1001)
+ v19:CShape[0x1001] = GuardBitEquals v18, CShape(0x1001) recompile
v20:CAttrIndex[0] = Const CAttrIndex(0)
v21:BasicObject = CCall v17, :rb_ivar_get_at_no_ractor_check@0x1008, v20
CheckInterrupts
@@ -7949,7 +7938,7 @@ mod hir_opt_tests {
PatchPoint SingleRactorMode
v17:TypedTData = GuardType v6, TypedTData
v18:CShape = LoadField v17, :shape_id@0x1000
- v19:CShape[0x1001] = GuardBitEquals v18, CShape(0x1001)
+ v19:CShape[0x1001] = GuardBitEquals v18, CShape(0x1001) recompile
v20:RubyValue = LoadField v17, :fields_obj@0x1002
v21:BasicObject = LoadField v20, :@a@0x1002
CheckInterrupts
@@ -8186,7 +8175,7 @@ mod hir_opt_tests {
Jump bb4(v29)
bb8():
v44:CShape = LoadField v11, :shape_id@0x1005
- v45:CShape[0x1006] = GuardBitEquals v44, CShape(0x1006)
+ v45:CShape[0x1006] = GuardBitEquals v44, CShape(0x1006) recompile
v46:CPtr = LoadField v11, :as_heap@0x1002
v47:BasicObject = LoadField v46, :@foo@0x1000
Jump bb4(v47)
@@ -8454,9 +8443,9 @@ mod hir_opt_tests {
v11:ArrayExact = ArrayDup v10
PatchPoint NoSingletonClass(Array@0x1008)
PatchPoint MethodRedefined(Array@0x1008, map@0x1010, cme:0x1018)
- v21:BasicObject = SendDirect v11, 0x1040, :map (0x1050)
+ v22:BasicObject = SendDirect v11, 0x1040, :map (0x1050)
CheckInterrupts
- Return v21
+ Return v22
");
}
@@ -8495,7 +8484,7 @@ mod hir_opt_tests {
v41:ArrayExact[VALUE(0x1018)] = Const Value(VALUE(0x1018))
PatchPoint NoSingletonClass(Array@0x1020)
PatchPoint MethodRedefined(Array@0x1020, zip@0x1028, cme:0x1030)
- v45:BasicObject = CCallVariadic v38, :Array#zip@0x1058, v41
+ v46:BasicObject = CCallVariadic v38, :Array#zip@0x1058, v41
PatchPoint NoEPEscape(test)
v24:CPtr = LoadSP
v25:BasicObject = LoadField v24, :result@0x1060
@@ -8744,11 +8733,11 @@ mod hir_opt_tests {
v20:ObjectSubclass[VALUE(0x1008)] = Const Value(VALUE(0x1008))
PatchPoint NoSingletonClass(C@0x1010)
PatchPoint MethodRedefined(C@0x1010, foo@0x1018, cme:0x1020)
- v25:CShape = LoadField v20, :shape_id@0x1048
- v26:CShape[0x1049] = GuardBitEquals v25, CShape(0x1049)
- v27:NilClass = Const Value(nil)
+ v26:CShape = LoadField v20, :shape_id@0x1048
+ v27:CShape[0x1049] = GuardBitEquals v26, CShape(0x1049) recompile
+ v28:NilClass = Const Value(nil)
CheckInterrupts
- Return v27
+ Return v28
");
}
@@ -8780,11 +8769,11 @@ mod hir_opt_tests {
v20:ObjectSubclass[VALUE(0x1008)] = Const Value(VALUE(0x1008))
PatchPoint NoSingletonClass(C@0x1010)
PatchPoint MethodRedefined(C@0x1010, foo@0x1018, cme:0x1020)
- v25:CShape = LoadField v20, :shape_id@0x1048
- v26:CShape[0x1049] = GuardBitEquals v25, CShape(0x1049)
- v27:NilClass = Const Value(nil)
+ v26:CShape = LoadField v20, :shape_id@0x1048
+ v27:CShape[0x1049] = GuardBitEquals v26, CShape(0x1049) recompile
+ v28:NilClass = Const Value(nil)
CheckInterrupts
- Return v27
+ Return v28
");
}
@@ -8817,7 +8806,7 @@ mod hir_opt_tests {
PatchPoint MethodRedefined(C@0x1008, foo@0x1010, cme:0x1018)
v23:ObjectSubclass[class_exact:C] = GuardType v10, ObjectSubclass[class_exact:C]
v26:CShape = LoadField v23, :shape_id@0x1040
- v27:CShape[0x1041] = GuardBitEquals v26, CShape(0x1041)
+ v27:CShape[0x1041] = GuardBitEquals v26, CShape(0x1041) recompile
v28:NilClass = Const Value(nil)
CheckInterrupts
Return v28
@@ -8853,7 +8842,7 @@ mod hir_opt_tests {
PatchPoint MethodRedefined(C@0x1008, foo@0x1010, cme:0x1018)
v23:ObjectSubclass[class_exact:C] = GuardType v10, ObjectSubclass[class_exact:C]
v26:CShape = LoadField v23, :shape_id@0x1040
- v27:CShape[0x1041] = GuardBitEquals v26, CShape(0x1041)
+ v27:CShape[0x1041] = GuardBitEquals v26, CShape(0x1041) recompile
v28:NilClass = Const Value(nil)
CheckInterrupts
Return v28
@@ -9347,8 +9336,8 @@ mod hir_opt_tests {
v14:StringExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
v28:Fixnum = GuardType v10, Fixnum
PatchPoint MethodRedefined(Integer@0x1010, to_s@0x1018, cme:0x1020)
- v32:StringExact = CCallVariadic v28, :Integer#to_s@0x1048
- v22:StringExact = StringConcat v14, v32
+ v33:StringExact = CCallVariadic v28, :Integer#to_s@0x1048
+ v22:StringExact = StringConcat v14, v33
CheckInterrupts
Return v22
");
@@ -9593,9 +9582,9 @@ mod hir_opt_tests {
v12:StaticSymbol[:a] = Const Value(VALUE(0x1010))
PatchPoint NoSingletonClass(Hash@0x1018)
PatchPoint MethodRedefined(Hash@0x1018, []@0x1020, cme:0x1028)
- v27:BasicObject = HashAref v23, v12
+ v28:BasicObject = HashAref v23, v12
CheckInterrupts
- Return v27
+ Return v28
");
}
@@ -9722,13 +9711,13 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, Thread)
- v20:Class[Thread@0x1008] = Const Value(VALUE(0x1008))
+ v20:ClassSubclass[Thread@0x1008] = Const Value(VALUE(0x1008))
PatchPoint MethodRedefined(Class@0x1010, current@0x1018, cme:0x1020)
- v23:CPtr = LoadEC
- v24:CPtr = LoadField v23, :thread_ptr@0x1048
- v25:BasicObject = LoadField v24, :self@0x1049
+ v24:CPtr = LoadEC
+ v25:CPtr = LoadField v24, :thread_ptr@0x1048
+ v26:BasicObject = LoadField v25, :self@0x1049
CheckInterrupts
- Return v25
+ Return v26
");
}
@@ -12413,9 +12402,9 @@ mod hir_opt_tests {
v14:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
PatchPoint NoSingletonClass(String@0x1008)
PatchPoint MethodRedefined(String@0x1008, ==@0x1010, cme:0x1018)
- v31:TrueClass = Const Value(true)
+ v32:TrueClass = Const Value(true)
CheckInterrupts
- Return v31
+ Return v32
");
}
@@ -12445,9 +12434,9 @@ mod hir_opt_tests {
v14:StringExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
PatchPoint NoSingletonClass(String@0x1010)
PatchPoint MethodRedefined(String@0x1010, ==@0x1018, cme:0x1020)
- v27:FalseClass = Const Value(false)
+ v28:FalseClass = Const Value(false)
CheckInterrupts
- Return v27
+ Return v28
");
}
@@ -12478,9 +12467,9 @@ mod hir_opt_tests {
v14:StringExact = StringCopy v13
PatchPoint NoSingletonClass(String@0x1008)
PatchPoint MethodRedefined(String@0x1008, ==@0x1010, cme:0x1018)
- v26:BoolExact = StringEqual v11, v14
+ v27:BoolExact = StringEqual v11, v14
CheckInterrupts
- Return v26
+ Return v27
");
}
@@ -12511,9 +12500,9 @@ mod hir_opt_tests {
v14:StringExact = StringCopy v13
PatchPoint NoSingletonClass(String@0x1010)
PatchPoint MethodRedefined(String@0x1010, ==@0x1018, cme:0x1020)
- v26:BoolExact = StringEqual v11, v14
+ v27:BoolExact = StringEqual v11, v14
CheckInterrupts
- Return v26
+ Return v27
");
}
@@ -12543,9 +12532,9 @@ mod hir_opt_tests {
v12:StringExact[VALUE(0x1000)] = Const Value(VALUE(0x1000))
PatchPoint NoSingletonClass(String@0x1008)
PatchPoint MethodRedefined(String@0x1008, ==@0x1010, cme:0x1018)
- v25:TrueClass = Const Value(true)
+ v26:TrueClass = Const Value(true)
CheckInterrupts
- Return v25
+ Return v26
");
}
@@ -12575,9 +12564,9 @@ mod hir_opt_tests {
v12:StringExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
PatchPoint NoSingletonClass(String@0x1010)
PatchPoint MethodRedefined(String@0x1010, ==@0x1018, cme:0x1020)
- v25:FalseClass = Const Value(false)
+ v26:FalseClass = Const Value(false)
CheckInterrupts
- Return v25
+ Return v26
");
}
@@ -12617,13 +12606,13 @@ mod hir_opt_tests {
v28:StringExact = StringCopy v27
PatchPoint NoSingletonClass(String@0x1008)
PatchPoint MethodRedefined(String@0x1008, <<@0x1010, cme:0x1018)
- v49:StringExact = StringAppend v17, v28
+ v50:StringExact = StringAppend v17, v28
PatchPoint NoEPEscape(test)
PatchPoint NoSingletonClass(String@0x1008)
PatchPoint MethodRedefined(String@0x1008, ==@0x1040, cme:0x1048)
- v53:BoolExact = StringEqual v17, v22
+ v55:BoolExact = StringEqual v17, v22
CheckInterrupts
- Return v53
+ Return v55
");
}
@@ -12685,10 +12674,10 @@ mod hir_opt_tests {
v15:StringExact = StringCopy v14
PatchPoint NoSingletonClass(String@0x1010)
PatchPoint MethodRedefined(String@0x1010, ==@0x1018, cme:0x1020)
- v28:String = GuardType v10, String
- v29:BoolExact = StringEqual v15, v28
+ v29:String = GuardType v10, String
+ v30:BoolExact = StringEqual v15, v29
CheckInterrupts
- Return v29
+ Return v30
");
}
@@ -12979,12 +12968,12 @@ mod hir_opt_tests {
bb3(v9:BasicObject, v10:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1008, String)
- v27:Class[String@0x1010] = Const Value(VALUE(0x1010))
+ v27:ClassSubclass[String@0x1010] = Const Value(VALUE(0x1010))
PatchPoint NoEPEscape(test)
PatchPoint MethodRedefined(Class@0x1018, ===@0x1020, cme:0x1028)
- v30:BoolExact = IsA v10, v27
+ v31:BoolExact = IsA v10, v27
CheckInterrupts
- Return v30
+ Return v31
");
}
@@ -13010,12 +12999,12 @@ mod hir_opt_tests {
bb3(v9:BasicObject, v10:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1008, Kernel)
- v27:ModuleExact[VALUE(0x1010)] = Const Value(VALUE(0x1010))
+ v27:ModuleSubclass[Kernel@0x1010] = Const Value(VALUE(0x1010))
PatchPoint NoEPEscape(test)
PatchPoint MethodRedefined(Module@0x1018, ===@0x1020, cme:0x1028)
- v30:BoolExact = CCall v27, :Module#===@0x1050, v10
+ v31:BoolExact = CCall v27, :Module#===@0x1050, v10
CheckInterrupts
- Return v30
+ Return v31
");
}
@@ -13041,7 +13030,7 @@ mod hir_opt_tests {
bb3(v9:BasicObject, v10:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1008, String)
- v25:Class[String@0x1010] = Const Value(VALUE(0x1010))
+ v25:ClassSubclass[String@0x1010] = Const Value(VALUE(0x1010))
PatchPoint NoSingletonClass(String@0x1010)
PatchPoint MethodRedefined(String@0x1010, is_a?@0x1011, cme:0x1018)
v29:StringExact = GuardType v10, StringExact
@@ -13073,7 +13062,7 @@ mod hir_opt_tests {
bb3(v9:BasicObject, v10:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1008, Kernel)
- v25:ModuleExact[VALUE(0x1010)] = Const Value(VALUE(0x1010))
+ v25:ModuleSubclass[Kernel@0x1010] = Const Value(VALUE(0x1010))
PatchPoint NoSingletonClass(String@0x1018)
PatchPoint MethodRedefined(String@0x1018, is_a?@0x1020, cme:0x1028)
v29:StringExact = GuardType v10, StringExact
@@ -13108,7 +13097,7 @@ mod hir_opt_tests {
bb3(v9:BasicObject, v10:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1008, Integer)
- v29:Class[Integer@0x1010] = Const Value(VALUE(0x1010))
+ v29:ClassSubclass[Integer@0x1010] = Const Value(VALUE(0x1010))
PatchPoint NoSingletonClass(String@0x1018)
PatchPoint MethodRedefined(String@0x1018, is_a?@0x1020, cme:0x1028)
v33:StringExact = GuardType v10, StringExact
@@ -13143,7 +13132,7 @@ mod hir_opt_tests {
bb3(v9:BasicObject, v10:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1008, Integer)
- v31:Class[Integer@0x1010] = Const Value(VALUE(0x1010))
+ v31:ClassSubclass[Integer@0x1010] = Const Value(VALUE(0x1010))
PatchPoint NoEPEscape(test)
PatchPoint MethodRedefined(Class@0x1018, ===@0x1020, cme:0x1028)
v23:Fixnum[5] = Const Value(5)
@@ -13174,7 +13163,7 @@ mod hir_opt_tests {
bb3(v9:BasicObject, v10:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1008, String)
- v25:Class[String@0x1010] = Const Value(VALUE(0x1010))
+ v25:ClassSubclass[String@0x1010] = Const Value(VALUE(0x1010))
PatchPoint NoSingletonClass(String@0x1010)
PatchPoint MethodRedefined(String@0x1010, kind_of?@0x1011, cme:0x1018)
v29:StringExact = GuardType v10, StringExact
@@ -13206,7 +13195,7 @@ mod hir_opt_tests {
bb3(v9:BasicObject, v10:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1008, Kernel)
- v25:ModuleExact[VALUE(0x1010)] = Const Value(VALUE(0x1010))
+ v25:ModuleSubclass[Kernel@0x1010] = Const Value(VALUE(0x1010))
PatchPoint NoSingletonClass(String@0x1018)
PatchPoint MethodRedefined(String@0x1018, kind_of?@0x1020, cme:0x1028)
v29:StringExact = GuardType v10, StringExact
@@ -13241,7 +13230,7 @@ mod hir_opt_tests {
bb3(v9:BasicObject, v10:BasicObject):
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1008, Integer)
- v29:Class[Integer@0x1010] = Const Value(VALUE(0x1010))
+ v29:ClassSubclass[Integer@0x1010] = Const Value(VALUE(0x1010))
PatchPoint NoSingletonClass(String@0x1018)
PatchPoint MethodRedefined(String@0x1018, kind_of?@0x1020, cme:0x1028)
v33:StringExact = GuardType v10, StringExact
@@ -13271,11 +13260,11 @@ mod hir_opt_tests {
v10:Fixnum[5] = Const Value(5)
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, Integer)
- v22:Class[Integer@0x1008] = Const Value(VALUE(0x1008))
+ v22:ClassSubclass[Integer@0x1008] = Const Value(VALUE(0x1008))
PatchPoint MethodRedefined(Integer@0x1008, is_a?@0x1009, cme:0x1010)
- v26:TrueClass = Const Value(true)
+ v27:TrueClass = Const Value(true)
CheckInterrupts
- Return v26
+ Return v27
");
}
@@ -13299,11 +13288,11 @@ mod hir_opt_tests {
v10:Fixnum[5] = Const Value(5)
PatchPoint SingleRactorMode
PatchPoint StableConstantNames(0x1000, String)
- v22:Class[String@0x1008] = Const Value(VALUE(0x1008))
+ v22:ClassSubclass[String@0x1008] = Const Value(VALUE(0x1008))
PatchPoint MethodRedefined(Integer@0x1010, is_a?@0x1018, cme:0x1020)
- v26:FalseClass = Const Value(false)
+ v27:FalseClass = Const Value(false)
CheckInterrupts
- Return v26
+ Return v27
");
}
@@ -13330,12 +13319,12 @@ mod hir_opt_tests {
PatchPoint StableConstantNames(0x1000, O)
v22:ArraySubclass[VALUE(0x1008)] = Const Value(VALUE(0x1008))
PatchPoint StableConstantNames(0x1010, Array)
- v25:Class[Array@0x1018] = Const Value(VALUE(0x1018))
+ v25:ClassSubclass[Array@0x1018] = Const Value(VALUE(0x1018))
PatchPoint NoSingletonClass(C@0x1020)
PatchPoint MethodRedefined(C@0x1020, is_a?@0x1028, cme:0x1030)
- v30:TrueClass = Const Value(true)
+ v31:TrueClass = Const Value(true)
CheckInterrupts
- Return v30
+ Return v31
");
}
@@ -13362,12 +13351,12 @@ mod hir_opt_tests {
PatchPoint StableConstantNames(0x1000, O)
v22:ObjectSubclass[VALUE(0x1008)] = Const Value(VALUE(0x1008))
PatchPoint StableConstantNames(0x1010, C)
- v25:Class[C@0x1018] = Const Value(VALUE(0x1018))
+ v25:ClassSubclass[C@0x1018] = Const Value(VALUE(0x1018))
PatchPoint NoSingletonClass(C@0x1018)
PatchPoint MethodRedefined(C@0x1018, is_a?@0x1019, cme:0x1020)
- v30:TrueClass = Const Value(true)
+ v31:TrueClass = Const Value(true)
CheckInterrupts
- Return v30
+ Return v31
");
}
@@ -13393,11 +13382,11 @@ mod hir_opt_tests {
PatchPoint StableConstantNames(0x1000, O)
v22:StaticSymbol[:my_static_symbol] = Const Value(VALUE(0x1008))
PatchPoint StableConstantNames(0x1010, Symbol)
- v25:Class[Symbol@0x1018] = Const Value(VALUE(0x1018))
+ v25:ClassSubclass[Symbol@0x1018] = Const Value(VALUE(0x1018))
PatchPoint MethodRedefined(Symbol@0x1018, is_a?@0x1019, cme:0x1020)
- v29:TrueClass = Const Value(true)
+ v30:TrueClass = Const Value(true)
CheckInterrupts
- Return v29
+ Return v30
");
}
@@ -13516,12 +13505,12 @@ mod hir_opt_tests {
PatchPoint NoSingletonClass(C@0x1000)
PatchPoint MethodRedefined(C@0x1000, class@0x1008, cme:0x1010)
v43:ObjectSubclass[class_exact:C] = GuardType v6, ObjectSubclass[class_exact:C]
- v46:Class[C@0x1000] = Const Value(VALUE(0x1000))
+ v46:ClassSubclass[C@0x1000] = Const Value(VALUE(0x1000))
v13:StaticSymbol[:_lex_actions] = Const Value(VALUE(0x1038))
v15:TrueClass = Const Value(true)
PatchPoint MethodRedefined(Class@0x1040, respond_to?@0x1048, cme:0x1050)
PatchPoint MethodRedefined(Class@0x1040, _lex_actions@0x1078, cme:0x1080)
- v51:TrueClass = Const Value(true)
+ v52:TrueClass = Const Value(true)
CheckInterrupts
v26:StaticSymbol[:CORRECT] = Const Value(VALUE(0x10a8))
Return v26
@@ -13552,11 +13541,11 @@ mod hir_opt_tests {
PatchPoint NoSingletonClass(C@0x1008)
PatchPoint MethodRedefined(C@0x1008, class@0x1010, cme:0x1018)
v25:ObjectSubclass[class_exact:C] = GuardType v10, ObjectSubclass[class_exact:C]
- v28:Class[C@0x1008] = Const Value(VALUE(0x1008))
+ v28:ClassSubclass[C@0x1008] = Const Value(VALUE(0x1008))
PatchPoint MethodRedefined(Class@0x1040, name@0x1048, cme:0x1050)
- v31:StringExact|NilClass = CCall v28, :Module#name@0x1078
+ v32:StringExact|NilClass = CCall v28, :Module#name@0x1078
CheckInterrupts
- Return v31
+ Return v32
");
}
@@ -13584,7 +13573,7 @@ mod hir_opt_tests {
PatchPoint NoSingletonClass(C@0x1008)
PatchPoint MethodRedefined(C@0x1008, class@0x1010, cme:0x1018)
v23:ObjectSubclass[class_exact:C] = GuardType v10, ObjectSubclass[class_exact:C]
- v26:Class[C@0x1008] = Const Value(VALUE(0x1008))
+ v26:ClassSubclass[C@0x1008] = Const Value(VALUE(0x1008))
CheckInterrupts
Return v26
");
@@ -13609,9 +13598,9 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
v10:Fixnum[5] = Const Value(5)
PatchPoint MethodRedefined(Integer@0x1000, class@0x1008, cme:0x1010)
- v21:Class[Integer@0x1000] = Const Value(VALUE(0x1000))
+ v22:ClassSubclass[Integer@0x1000] = Const Value(VALUE(0x1000))
CheckInterrupts
- Return v21
+ Return v22
");
}
@@ -13634,12 +13623,42 @@ mod hir_opt_tests {
bb3(v6:BasicObject):
PatchPoint MethodRedefined(Object@0x1000, class@0x1008, cme:0x1010)
v18:ObjectSubclass[class_exact*:Object@VALUE(0x1000)] = GuardType v6, ObjectSubclass[class_exact*:Object@VALUE(0x1000)]
- v21:Class[Object@0x1038] = Const Value(VALUE(0x1038))
+ v21:ClassSubclass[Object@0x1038] = Const Value(VALUE(0x1038))
CheckInterrupts
Return v21
");
}
+ #[test]
+ fn test_print_nil_module_name() {
+ eval(r#"
+ X = [Module.new].freeze
+ def test = X[0]
+ test
+ "#);
+ assert_snapshot!(hir_string("test"), @"
+ fn test@:3:
+ bb1():
+ EntryPoint interpreter
+ v1:BasicObject = LoadSelf
+ Jump bb3(v1)
+ bb2():
+ EntryPoint JIT(0)
+ v4:BasicObject = LoadArg :self@0
+ Jump bb3(v4)
+ bb3(v6:BasicObject):
+ PatchPoint SingleRactorMode
+ PatchPoint StableConstantNames(0x1000, X)
+ v23:ArrayExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
+ v12:Fixnum[0] = Const Value(0)
+ PatchPoint NoSingletonClass(Array@0x1010)
+ PatchPoint MethodRedefined(Array@0x1010, []@0x1018, cme:0x1020)
+ v37:ModuleExact[VALUE(0x1048)] = Const Value(VALUE(0x1048))
+ CheckInterrupts
+ Return v37
+ ");
+ }
+
#[test]
fn no_load_from_ep_right_after_entrypoint() {
let formatted = eval("
@@ -13683,16 +13702,16 @@ mod hir_opt_tests {
SetLocal :formatted, l0, EP@3, v16
PatchPoint SingleRactorMode
SetIvar v15, :@formatted, v16
- v47:Class[VMFrozenCore] = Const Value(VALUE(0x1008))
+ v47:ClassSubclass[VMFrozenCore] = Const Value(VALUE(0x1008))
PatchPoint MethodRedefined(Class@0x1010, lambda@0x1018, cme:0x1020)
- v62:BasicObject = CCallWithFrame v47, :RubyVM::FrozenCore.lambda@0x1048, block=0x1050
+ v63:BasicObject = CCallWithFrame v47, :RubyVM::FrozenCore.lambda@0x1048, block=0x1050
v50:CPtr = GetEP 0
v51:BasicObject = LoadField v50, :a@0x1001
v52:BasicObject = LoadField v50, :_b@0x1002
v53:BasicObject = LoadField v50, :_c@0x1058
v54:BasicObject = LoadField v50, :formatted@0x1059
CheckInterrupts
- Return v62
+ Return v63
");
}
@@ -13729,9 +13748,9 @@ mod hir_opt_tests {
v20:ObjectSubclass[VALUE(0x1008)] = Const Value(VALUE(0x1008))
PatchPoint NoSingletonClass(TestFrozen@0x1010)
PatchPoint MethodRedefined(TestFrozen@0x1010, a@0x1018, cme:0x1020)
- v29:Fixnum[1] = Const Value(1)
+ v30:Fixnum[1] = Const Value(1)
CheckInterrupts
- Return v29
+ Return v30
");
}
@@ -13770,9 +13789,9 @@ mod hir_opt_tests {
v20:ObjectSubclass[VALUE(0x1008)] = Const Value(VALUE(0x1008))
PatchPoint NoSingletonClass(TestMultiIvars@0x1010)
PatchPoint MethodRedefined(TestMultiIvars@0x1010, b@0x1018, cme:0x1020)
- v29:Fixnum[20] = Const Value(20)
+ v30:Fixnum[20] = Const Value(20)
CheckInterrupts
- Return v29
+ Return v30
");
}
@@ -13809,9 +13828,9 @@ mod hir_opt_tests {
v20:ObjectSubclass[VALUE(0x1008)] = Const Value(VALUE(0x1008))
PatchPoint NoSingletonClass(TestFrozenStr@0x1010)
PatchPoint MethodRedefined(TestFrozenStr@0x1010, name@0x1018, cme:0x1020)
- v29:StringExact[VALUE(0x1048)] = Const Value(VALUE(0x1048))
+ v30:StringExact[VALUE(0x1048)] = Const Value(VALUE(0x1048))
CheckInterrupts
- Return v29
+ Return v30
");
}
@@ -13848,9 +13867,9 @@ mod hir_opt_tests {
v20:ObjectSubclass[VALUE(0x1008)] = Const Value(VALUE(0x1008))
PatchPoint NoSingletonClass(TestFrozenNil@0x1010)
PatchPoint MethodRedefined(TestFrozenNil@0x1010, value@0x1018, cme:0x1020)
- v29:NilClass = Const Value(nil)
+ v30:NilClass = Const Value(nil)
CheckInterrupts
- Return v29
+ Return v30
");
}
@@ -13887,11 +13906,11 @@ mod hir_opt_tests {
v20:ObjectSubclass[VALUE(0x1008)] = Const Value(VALUE(0x1008))
PatchPoint NoSingletonClass(TestUnfrozen@0x1010)
PatchPoint MethodRedefined(TestUnfrozen@0x1010, a@0x1018, cme:0x1020)
- v25:CShape = LoadField v20, :shape_id@0x1048
- v26:CShape[0x1049] = GuardBitEquals v25, CShape(0x1049)
- v27:BasicObject = LoadField v20, :@a@0x104a
+ v26:CShape = LoadField v20, :shape_id@0x1048
+ v27:CShape[0x1049] = GuardBitEquals v26, CShape(0x1049) recompile
+ v28:BasicObject = LoadField v20, :@a@0x104a
CheckInterrupts
- Return v27
+ Return v28
");
}
@@ -13928,9 +13947,9 @@ mod hir_opt_tests {
v20:ObjectSubclass[VALUE(0x1008)] = Const Value(VALUE(0x1008))
PatchPoint NoSingletonClass(TestAttrReader@0x1010)
PatchPoint MethodRedefined(TestAttrReader@0x1010, value@0x1018, cme:0x1020)
- v29:Fixnum[42] = Const Value(42)
+ v30:Fixnum[42] = Const Value(42)
CheckInterrupts
- Return v29
+ Return v30
");
}
@@ -13967,9 +13986,9 @@ mod hir_opt_tests {
v20:ObjectSubclass[VALUE(0x1008)] = Const Value(VALUE(0x1008))
PatchPoint NoSingletonClass(TestFrozenSym@0x1010)
PatchPoint MethodRedefined(TestFrozenSym@0x1010, sym@0x1018, cme:0x1020)
- v29:StaticSymbol[:hello] = Const Value(VALUE(0x1048))
+ v30:StaticSymbol[:hello] = Const Value(VALUE(0x1048))
CheckInterrupts
- Return v29
+ Return v30
");
}
@@ -14006,9 +14025,9 @@ mod hir_opt_tests {
v20:ObjectSubclass[VALUE(0x1008)] = Const Value(VALUE(0x1008))
PatchPoint NoSingletonClass(TestFrozenBool@0x1010)
PatchPoint MethodRedefined(TestFrozenBool@0x1010, flag@0x1018, cme:0x1020)
- v29:TrueClass = Const Value(true)
+ v30:TrueClass = Const Value(true)
CheckInterrupts
- Return v29
+ Return v30
");
}
@@ -14046,7 +14065,7 @@ mod hir_opt_tests {
PatchPoint MethodRedefined(TestDynamic@0x1008, val@0x1010, cme:0x1018)
v23:ObjectSubclass[class_exact:TestDynamic] = GuardType v10, ObjectSubclass[class_exact:TestDynamic]
v26:CShape = LoadField v23, :shape_id@0x1040
- v27:CShape[0x1041] = GuardBitEquals v26, CShape(0x1041)
+ v27:CShape[0x1041] = GuardBitEquals v26, CShape(0x1041) recompile
v28:BasicObject = LoadField v23, :@val@0x1042
CheckInterrupts
Return v28
@@ -14087,15 +14106,15 @@ mod hir_opt_tests {
v27:ObjectSubclass[VALUE(0x1008)] = Const Value(VALUE(0x1008))
PatchPoint NoSingletonClass(TestNestedAccess@0x1010)
PatchPoint MethodRedefined(TestNestedAccess@0x1010, x@0x1018, cme:0x1020)
- v51:Fixnum[100] = Const Value(100)
+ v53:Fixnum[100] = Const Value(100)
PatchPoint StableConstantNames(0x1048, NESTED_FROZEN)
- v33:ObjectSubclass[VALUE(0x1008)] = Const Value(VALUE(0x1008))
+ v34:ObjectSubclass[VALUE(0x1008)] = Const Value(VALUE(0x1008))
PatchPoint MethodRedefined(TestNestedAccess@0x1010, y@0x1050, cme:0x1058)
- v53:Fixnum[200] = Const Value(200)
+ v55:Fixnum[200] = Const Value(200)
PatchPoint MethodRedefined(Integer@0x1080, +@0x1088, cme:0x1090)
- v54:Fixnum[300] = Const Value(300)
+ v56:Fixnum[300] = Const Value(300)
CheckInterrupts
- Return v54
+ Return v56
");
}
@@ -14122,10 +14141,10 @@ mod hir_opt_tests {
v20:StringExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
PatchPoint NoSingletonClass(String@0x1010)
PatchPoint MethodRedefined(String@0x1010, bytesize@0x1018, cme:0x1020)
- v24:CInt64 = LoadField v20, :len@0x1048
- v25:Fixnum = BoxFixnum v24
+ v25:CInt64 = LoadField v20, :len@0x1048
+ v26:Fixnum = BoxFixnum v25
CheckInterrupts
- Return v25
+ Return v26
");
}
@@ -15530,7 +15549,7 @@ mod hir_opt_tests {
PatchPoint SingleRactorMode
v35:HeapBasicObject = GuardType v8, HeapBasicObject
v36:CShape = LoadField v35, :shape_id@0x1000
- v37:CShape[0x1001] = GuardBitEquals v36, CShape(0x1001)
+ v37:CShape[0x1001] = GuardBitEquals v36, CShape(0x1001) recompile
StoreField v35, :@a@0x1002, v13
WriteBarrier v35, v13
v40:CShape[0x1003] = Const CShape(0x1003)
@@ -15578,7 +15597,7 @@ mod hir_opt_tests {
PatchPoint SingleRactorMode
v49:HeapBasicObject = GuardType v10, HeapBasicObject
v50:CShape = LoadField v49, :shape_id@0x1000
- v51:CShape[0x1001] = GuardBitEquals v50, CShape(0x1001)
+ v51:CShape[0x1001] = GuardBitEquals v50, CShape(0x1001) recompile
StoreField v49, :@a@0x1002, v16
WriteBarrier v49, v16
v54:CShape[0x1003] = Const CShape(0x1003)
@@ -15587,7 +15606,7 @@ mod hir_opt_tests {
v26:Fixnum[5] = Const Value(5)
PatchPoint NoEPEscape(initialize)
PatchPoint MethodRedefined(Integer@0x1008, +@0x1010, cme:0x1018)
- v64:Fixnum[6] = Const Value(6)
+ v65:Fixnum[6] = Const Value(6)
PatchPoint SingleRactorMode
WriteBarrier v23, v16
CheckInterrupts
@@ -15626,7 +15645,7 @@ mod hir_opt_tests {
PatchPoint SingleRactorMode
v43:HeapBasicObject = GuardType v8, HeapBasicObject
v44:CShape = LoadField v43, :shape_id@0x1000
- v45:CShape[0x1001] = GuardBitEquals v44, CShape(0x1001)
+ v45:CShape[0x1001] = GuardBitEquals v44, CShape(0x1001) recompile
StoreField v43, :@a@0x1002, v13
WriteBarrier v43, v13
v48:CShape[0x1003] = Const CShape(0x1003)
@@ -15895,9 +15914,9 @@ mod hir_opt_tests {
v21:Fixnum[2] = Const Value(2)
v40:Fixnum = FixnumSub v35, v21
PatchPoint MethodRedefined(Integer@0x1008, +@0x1040, cme:0x1048)
- v43:Fixnum = FixnumAdd v36, v40
+ v44:Fixnum = FixnumAdd v36, v40
CheckInterrupts
- Return v43
+ Return v44
");
}
@@ -16030,7 +16049,7 @@ mod hir_opt_tests {
Jump bb8(v63)
bb12():
v97:CShape = LoadField v46, :shape_id@0x103c
- v98:CShape[0x103d] = GuardBitEquals v97, CShape(0x103d)
+ v98:CShape[0x103d] = GuardBitEquals v97, CShape(0x103d) recompile
v99:BasicObject = LoadField v46, :@levar@0x103a
Jump bb8(v99)
bb8(v48:BasicObject):
@@ -16041,7 +16060,7 @@ mod hir_opt_tests {
PatchPoint NoEPEscape(set_value_loop)
PatchPoint SingleRactorMode
v101:CShape = LoadField v46, :shape_id@0x103c
- v102:CShape[0x103e] = GuardBitEquals v101, CShape(0x103e)
+ v102:CShape[0x103e] = GuardBitEquals v101, CShape(0x103e) recompile
StoreField v46, :@levar@0x103a, v41
WriteBarrier v46, v41
v105:CShape[0x103d] = Const CShape(0x103d)
@@ -16509,20 +16528,80 @@ mod hir_opt_tests {
v138:ObjectSubclass[class_exact:C] = GuardType v12, ObjectSubclass[class_exact:C]
v139:BasicObject = LoadField v138, :var@0x1040
PatchPoint MethodRedefined(Integer@0x1048, +@0x1050, cme:0x1058)
- v178:Fixnum = GuardType v139, Fixnum
- v179:Fixnum = FixnumAdd v17, v178
+ v179:Fixnum = GuardType v139, Fixnum
+ v180:Fixnum = FixnumAdd v17, v179
PatchPoint NoEPEscape(test)
- v183:Fixnum = FixnumAdd v179, v178
- v187:Fixnum = FixnumAdd v183, v178
- v191:Fixnum = FixnumAdd v187, v178
- v195:Fixnum = FixnumAdd v191, v178
- v199:Fixnum = FixnumAdd v195, v178
- v203:Fixnum = FixnumAdd v199, v178
- v207:Fixnum = FixnumAdd v203, v178
- v211:Fixnum = FixnumAdd v207, v178
- v215:Fixnum = FixnumAdd v211, v178
- CheckInterrupts
- Return v215
+ v185:Fixnum = FixnumAdd v180, v179
+ v190:Fixnum = FixnumAdd v185, v179
+ v195:Fixnum = FixnumAdd v190, v179
+ v200:Fixnum = FixnumAdd v195, v179
+ v205:Fixnum = FixnumAdd v200, v179
+ v210:Fixnum = FixnumAdd v205, v179
+ v215:Fixnum = FixnumAdd v210, v179
+ v220:Fixnum = FixnumAdd v215, v179
+ v225:Fixnum = FixnumAdd v220, v179
+ CheckInterrupts
+ Return v225
+ ");
+ }
+
+ #[test]
+ fn test_dont_fold_array_length() {
+ eval(r#"
+ A = [1, 2, 3, 4]
+ def test = A.length
+ test
+ "#);
+ assert_snapshot!(hir_string("test"), @"
+ fn test@:3:
+ bb1():
+ EntryPoint interpreter
+ v1:BasicObject = LoadSelf
+ Jump bb3(v1)
+ bb2():
+ EntryPoint JIT(0)
+ v4:BasicObject = LoadArg :self@0
+ Jump bb3(v4)
+ bb3(v6:BasicObject):
+ PatchPoint SingleRactorMode
+ PatchPoint StableConstantNames(0x1000, A)
+ v21:ArrayExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
+ PatchPoint NoSingletonClass(Array@0x1010)
+ PatchPoint MethodRedefined(Array@0x1010, length@0x1018, cme:0x1020)
+ v26:CInt64 = ArrayLength v21
+ v27:Fixnum = BoxFixnum v26
+ CheckInterrupts
+ Return v27
+ ");
+ }
+
+ #[test]
+ fn test_fold_frozen_array_length() {
+ eval(r#"
+ A = [1, 2, 3, 4].freeze
+ def test = A.length
+ test
+ "#);
+ assert_snapshot!(hir_string("test"), @"
+ fn test@:3:
+ bb1():
+ EntryPoint interpreter
+ v1:BasicObject = LoadSelf
+ Jump bb3(v1)
+ bb2():
+ EntryPoint JIT(0)
+ v4:BasicObject = LoadArg :self@0
+ Jump bb3(v4)
+ bb3(v6:BasicObject):
+ PatchPoint SingleRactorMode
+ PatchPoint StableConstantNames(0x1000, A)
+ v21:ArrayExact[VALUE(0x1008)] = Const Value(VALUE(0x1008))
+ PatchPoint NoSingletonClass(Array@0x1010)
+ PatchPoint MethodRedefined(Array@0x1010, length@0x1018, cme:0x1020)
+ v28:CInt64[4] = Const CInt64(4)
+ v27:Fixnum = BoxFixnum v28
+ CheckInterrupts
+ Return v27
");
}
}
diff --git a/zjit/src/hir/tests.rs b/zjit/src/hir/tests.rs
index 566cf7aeb7cf7a..7a1cd85c5fb38f 100644
--- a/zjit/src/hir/tests.rs
+++ b/zjit/src/hir/tests.rs
@@ -50,10 +50,10 @@ mod snapshot_tests {
v12:Fixnum[2] = Const Value(2)
v13:Any = Snapshot FrameState { pc: 0x1008, stack: [v10, v12], locals: [] }
PatchPoint MethodRedefined(Integer@0x1010, +@0x1018, cme:0x1020)
- v33:Fixnum[6] = Const Value(6)
- v21:Any = Snapshot FrameState { pc: 0x1048, stack: [v33], locals: [] }
+ v35:Fixnum[6] = Const Value(6)
+ v21:Any = Snapshot FrameState { pc: 0x1048, stack: [v35], locals: [] }
CheckInterrupts
- Return v33
+ Return v35
");
}
@@ -2384,11 +2384,11 @@ pub(crate) mod hir_build_tests {
v7:BasicObject = LoadArg :a@1
Jump bb3(v6, v7)
bb3(v9:BasicObject, v10:BasicObject):
- v15:Class[VMFrozenCore] = Const Value(VALUE(0x1008))
+ v15:ClassSubclass[VMFrozenCore] = Const Value(VALUE(0x1008))
v17:HashExact = NewHash
PatchPoint NoEPEscape(test)
v22:BasicObject = Send v15, :core#hash_merge_kwd, v17, v10 # SendFallbackReason: Uncategorized(opt_send_without_block)
- v24:Class[VMFrozenCore] = Const Value(VALUE(0x1008))
+ v24:ClassSubclass[VMFrozenCore] = Const Value(VALUE(0x1008))
v27:StaticSymbol[:b] = Const Value(VALUE(0x1010))
v29:Fixnum[1] = Const Value(1)
v31:BasicObject = Send v24, :core#hash_merge_ptr, v22, v27, v29 # SendFallbackReason: Uncategorized(opt_send_without_block)
@@ -4360,7 +4360,7 @@ pub(crate) mod hir_build_tests {
v4:BasicObject = LoadArg :self@0
Jump bb3(v4)
bb3(v6:BasicObject):
- v10:Class[VMFrozenCore] = Const Value(VALUE(0x1000))
+ v10:ClassSubclass[VMFrozenCore] = Const Value(VALUE(0x1000))
v12:BasicObject = PutSpecialObject CBase
v14:StaticSymbol[:aliased] = Const Value(VALUE(0x1008))
v16:StaticSymbol[:__callee__] = Const Value(VALUE(0x1010))
diff --git a/zjit/src/hir_type/gen_hir_type.rb b/zjit/src/hir_type/gen_hir_type.rb
index e9d925ba0f5b13..41f96a7a82e4d4 100644
--- a/zjit/src/hir_type/gen_hir_type.rb
+++ b/zjit/src/hir_type/gen_hir_type.rb
@@ -75,8 +75,8 @@ def to_graphviz type, f
# Define a new type that can be subclassed (most of them).
# If c_name is given, mark the rb_cXYZ object as equivalent to this exact type.
-def base_type name, c_name: nil
- type = $object.subtype name
+def base_type name, base: $object, c_name: nil
+ type = base.subtype name
exact = type.subtype(name+"Exact")
subclass = type.subtype(name+"Subclass")
if c_name
@@ -111,7 +111,7 @@ def final_type name, base: $object, c_name: nil
module_class, _ = base_type "Module", c_name: "rb_cModule"
# Class cannot be subclassed by doing `class Sub < Class`,
# but every metaclass is a subclass of `Class`. It's not final.
-module_class.subtype "Class"
+base_type "Class", base: module_class, c_name: "rb_cClass"
numeric, _ = base_type "Numeric", c_name: "rb_cNumeric"
diff --git a/zjit/src/hir_type/hir_type.inc.rs b/zjit/src/hir_type/hir_type.inc.rs
index 8b95914ddf180a..f4c3bf348916b0 100644
--- a/zjit/src/hir_type/hir_type.inc.rs
+++ b/zjit/src/hir_type/hir_type.inc.rs
@@ -9,7 +9,7 @@ mod bits {
pub const BasicObjectSubclass: u64 = 1u64 << 3;
pub const Bignum: u64 = 1u64 << 4;
pub const BoolExact: u64 = FalseClass | TrueClass;
- pub const BuiltinExact: u64 = ArrayExact | BasicObjectExact | FalseClass | Float | HashExact | Integer | ModuleExact | NilClass | NumericExact | ObjectExact | RangeExact | RegexpExact | SetExact | StringExact | Symbol | TrueClass;
+ pub const BuiltinExact: u64 = ArrayExact | BasicObjectExact | ClassExact | FalseClass | Float | HashExact | Integer | ModuleExact | NilClass | NumericExact | ObjectExact | RangeExact | RegexpExact | SetExact | StringExact | Symbol | TrueClass;
pub const CAttrIndex: u64 = 1u64 << 5;
pub const CBool: u64 = 1u64 << 6;
pub const CDouble: u64 = 1u64 << 7;
@@ -29,54 +29,56 @@ mod bits {
pub const CUnsigned: u64 = CAttrIndex | CShape | CUInt16 | CUInt32 | CUInt64 | CUInt8;
pub const CValue: u64 = CBool | CDouble | CInt | CNull | CPtr;
pub const CallableMethodEntry: u64 = 1u64 << 19;
- pub const Class: u64 = 1u64 << 20;
- pub const DynamicSymbol: u64 = 1u64 << 21;
+ pub const Class: u64 = ClassExact | ClassSubclass;
+ pub const ClassExact: u64 = 1u64 << 20;
+ pub const ClassSubclass: u64 = 1u64 << 21;
+ pub const DynamicSymbol: u64 = 1u64 << 22;
pub const Empty: u64 = 0u64;
- pub const FalseClass: u64 = 1u64 << 22;
+ pub const FalseClass: u64 = 1u64 << 23;
pub const Falsy: u64 = FalseClass | NilClass;
- pub const Fixnum: u64 = 1u64 << 23;
+ pub const Fixnum: u64 = 1u64 << 24;
pub const Float: u64 = Flonum | HeapFloat;
- pub const Flonum: u64 = 1u64 << 24;
+ pub const Flonum: u64 = 1u64 << 25;
pub const Hash: u64 = HashExact | HashSubclass;
- pub const HashExact: u64 = 1u64 << 25;
- pub const HashSubclass: u64 = 1u64 << 26;
+ pub const HashExact: u64 = 1u64 << 26;
+ pub const HashSubclass: u64 = 1u64 << 27;
pub const HeapBasicObject: u64 = BasicObject & !Immediate;
- pub const HeapFloat: u64 = 1u64 << 27;
+ pub const HeapFloat: u64 = 1u64 << 28;
pub const HeapObject: u64 = Object & !Immediate;
pub const Immediate: u64 = FalseClass | Fixnum | Flonum | NilClass | StaticSymbol | TrueClass | Undef;
pub const Integer: u64 = Bignum | Fixnum;
pub const Module: u64 = Class | ModuleExact | ModuleSubclass;
- pub const ModuleExact: u64 = 1u64 << 28;
- pub const ModuleSubclass: u64 = 1u64 << 29;
- pub const NilClass: u64 = 1u64 << 30;
+ pub const ModuleExact: u64 = 1u64 << 29;
+ pub const ModuleSubclass: u64 = 1u64 << 30;
+ pub const NilClass: u64 = 1u64 << 31;
pub const NotNil: u64 = BasicObject & !NilClass;
pub const Numeric: u64 = Float | Integer | NumericExact | NumericSubclass;
- pub const NumericExact: u64 = 1u64 << 31;
- pub const NumericSubclass: u64 = 1u64 << 32;
+ pub const NumericExact: u64 = 1u64 << 32;
+ pub const NumericSubclass: u64 = 1u64 << 33;
pub const Object: u64 = Array | FalseClass | Hash | Module | NilClass | Numeric | ObjectExact | ObjectSubclass | Range | Regexp | Set | String | Symbol | TrueClass;
- pub const ObjectExact: u64 = 1u64 << 33;
- pub const ObjectSubclass: u64 = 1u64 << 34;
+ pub const ObjectExact: u64 = 1u64 << 34;
+ pub const ObjectSubclass: u64 = 1u64 << 35;
pub const Range: u64 = RangeExact | RangeSubclass;
- pub const RangeExact: u64 = 1u64 << 35;
- pub const RangeSubclass: u64 = 1u64 << 36;
+ pub const RangeExact: u64 = 1u64 << 36;
+ pub const RangeSubclass: u64 = 1u64 << 37;
pub const Regexp: u64 = RegexpExact | RegexpSubclass;
- pub const RegexpExact: u64 = 1u64 << 37;
- pub const RegexpSubclass: u64 = 1u64 << 38;
+ pub const RegexpExact: u64 = 1u64 << 38;
+ pub const RegexpSubclass: u64 = 1u64 << 39;
pub const RubyValue: u64 = BasicObject | CallableMethodEntry | Undef;
pub const Set: u64 = SetExact | SetSubclass;
- pub const SetExact: u64 = 1u64 << 39;
- pub const SetSubclass: u64 = 1u64 << 40;
- pub const StaticSymbol: u64 = 1u64 << 41;
+ pub const SetExact: u64 = 1u64 << 40;
+ pub const SetSubclass: u64 = 1u64 << 41;
+ pub const StaticSymbol: u64 = 1u64 << 42;
pub const String: u64 = StringExact | StringSubclass;
- pub const StringExact: u64 = 1u64 << 42;
- pub const StringSubclass: u64 = 1u64 << 43;
- pub const Subclass: u64 = ArraySubclass | BasicObjectSubclass | HashSubclass | ModuleSubclass | NumericSubclass | ObjectSubclass | RangeSubclass | RegexpSubclass | SetSubclass | StringSubclass;
+ pub const StringExact: u64 = 1u64 << 43;
+ pub const StringSubclass: u64 = 1u64 << 44;
+ pub const Subclass: u64 = ArraySubclass | BasicObjectSubclass | ClassSubclass | HashSubclass | ModuleSubclass | NumericSubclass | ObjectSubclass | RangeSubclass | RegexpSubclass | SetSubclass | StringSubclass;
pub const Symbol: u64 = DynamicSymbol | StaticSymbol;
- pub const TrueClass: u64 = 1u64 << 44;
+ pub const TrueClass: u64 = 1u64 << 45;
pub const Truthy: u64 = BasicObject & !Falsy;
- pub const TypedTData: u64 = 1u64 << 45;
- pub const Undef: u64 = 1u64 << 46;
- pub const AllBitPatterns: [(&str, u64); 76] = [
+ pub const TypedTData: u64 = 1u64 << 46;
+ pub const Undef: u64 = 1u64 << 47;
+ pub const AllBitPatterns: [(&str, u64); 78] = [
("Any", Any),
("RubyValue", RubyValue),
("Immediate", Immediate),
@@ -127,6 +129,8 @@ mod bits {
("FalseClass", FalseClass),
("DynamicSymbol", DynamicSymbol),
("Class", Class),
+ ("ClassSubclass", ClassSubclass),
+ ("ClassExact", ClassExact),
("CallableMethodEntry", CallableMethodEntry),
("CValue", CValue),
("CInt", CInt),
@@ -154,7 +158,7 @@ mod bits {
("ArrayExact", ArrayExact),
("Empty", Empty),
];
- pub const NumTypeBits: u64 = 47;
+ pub const NumTypeBits: u64 = 48;
}
pub mod types {
use super::*;
@@ -188,6 +192,8 @@ pub mod types {
pub const CValue: Type = Type::from_bits(bits::CValue);
pub const CallableMethodEntry: Type = Type::from_bits(bits::CallableMethodEntry);
pub const Class: Type = Type::from_bits(bits::Class);
+ pub const ClassExact: Type = Type::from_bits(bits::ClassExact);
+ pub const ClassSubclass: Type = Type::from_bits(bits::ClassSubclass);
pub const DynamicSymbol: Type = Type::from_bits(bits::DynamicSymbol);
pub const Empty: Type = Type::from_bits(bits::Empty);
pub const FalseClass: Type = Type::from_bits(bits::FalseClass);
@@ -234,7 +240,7 @@ pub mod types {
pub const Truthy: Type = Type::from_bits(bits::Truthy);
pub const TypedTData: Type = Type::from_bits(bits::TypedTData);
pub const Undef: Type = Type::from_bits(bits::Undef);
- pub const ExactBitsAndClass: [(u64, *const VALUE); 16] = [
+ pub const ExactBitsAndClass: [(u64, *const VALUE); 17] = [
(bits::ObjectExact, &raw const crate::cruby::rb_cObject),
(bits::BasicObjectExact, &raw const crate::cruby::rb_cBasicObject),
(bits::StringExact, &raw const crate::cruby::rb_cString),
@@ -244,6 +250,7 @@ pub mod types {
(bits::SetExact, &raw const crate::cruby::rb_cSet),
(bits::RegexpExact, &raw const crate::cruby::rb_cRegexp),
(bits::ModuleExact, &raw const crate::cruby::rb_cModule),
+ (bits::ClassExact, &raw const crate::cruby::rb_cClass),
(bits::NumericExact, &raw const crate::cruby::rb_cNumeric),
(bits::Integer, &raw const crate::cruby::rb_cInteger),
(bits::Float, &raw const crate::cruby::rb_cFloat),
@@ -252,8 +259,9 @@ pub mod types {
(bits::TrueClass, &raw const crate::cruby::rb_cTrueClass),
(bits::FalseClass, &raw const crate::cruby::rb_cFalseClass),
];
- pub const SubclassBitsAndClass: [(u64, *const VALUE); 16] = [
+ pub const SubclassBitsAndClass: [(u64, *const VALUE); 17] = [
(bits::ArraySubclass, &raw const crate::cruby::rb_cArray),
+ (bits::ClassSubclass, &raw const crate::cruby::rb_cClass),
(bits::FalseClass, &raw const crate::cruby::rb_cFalseClass),
(bits::Integer, &raw const crate::cruby::rb_cInteger),
(bits::HashSubclass, &raw const crate::cruby::rb_cHash),
@@ -270,8 +278,9 @@ pub mod types {
(bits::ObjectSubclass, &raw const crate::cruby::rb_cObject),
(bits::BasicObjectSubclass, &raw const crate::cruby::rb_cBasicObject),
];
- pub const InexactBitsAndClass: [(u64, *const VALUE); 16] = [
+ pub const InexactBitsAndClass: [(u64, *const VALUE); 17] = [
(bits::Array, &raw const crate::cruby::rb_cArray),
+ (bits::Class, &raw const crate::cruby::rb_cClass),
(bits::FalseClass, &raw const crate::cruby::rb_cFalseClass),
(bits::Integer, &raw const crate::cruby::rb_cInteger),
(bits::Hash, &raw const crate::cruby::rb_cHash),
diff --git a/zjit/src/hir_type/mod.rs b/zjit/src/hir_type/mod.rs
index 206b74e7d38de3..cdfc15a9355f64 100644
--- a/zjit/src/hir_type/mod.rs
+++ b/zjit/src/hir_type/mod.rs
@@ -2,13 +2,13 @@
#![allow(non_upper_case_globals)]
use crate::cruby;
-use crate::cruby::{rb_block_param_proxy, Qfalse, Qnil, Qtrue, RUBY_T_ARRAY, RUBY_T_CLASS, RUBY_T_HASH, RUBY_T_MODULE, RUBY_T_STRING, VALUE};
-use crate::cruby::{rb_cInteger, rb_cFloat, rb_cArray, rb_cHash, rb_cString, rb_cSymbol, rb_cRange, rb_cModule, rb_zjit_singleton_class_p};
+use crate::cruby::{rb_block_param_proxy, Qfalse, Qnil, Qtrue, RUBY_T_ARRAY, RUBY_T_HASH, RUBY_T_STRING, VALUE};
+use crate::cruby::{rb_cInteger, rb_cFloat, rb_cArray, rb_cHash, rb_cString, rb_cSymbol, rb_cRange, rb_zjit_singleton_class_p};
use crate::cruby::ClassRelationship;
use crate::cruby::get_class_name;
+use crate::cruby::get_module_name;
use crate::cruby::ruby_sym_to_rust_string;
use crate::cruby::rb_mRubyVMFrozenCore;
-use crate::cruby::rb_obj_class;
use crate::hir::{Const, PtrPrintMap};
use crate::profile::ProfiledType;
@@ -80,6 +80,14 @@ fn write_spec(f: &mut std::fmt::Formatter, printer: &TypePrinter) -> std::fmt::R
Specialization::Object(val) if ty.is_subtype(types::Symbol) => write!(f, "[:{}]", ruby_sym_to_rust_string(val)),
Specialization::Object(val) if ty.is_subtype(types::Class) =>
write!(f, "[{}@{:p}]", get_class_name(val), printer.ptr_map.map_ptr(val.0 as *const std::ffi::c_void)),
+ Specialization::Object(val) if ty.is_subtype(types::Module) => {
+ if let Some(name) = get_module_name(val) {
+ write!(f, "[{}@{:p}]", name, printer.ptr_map.map_ptr(val.0 as *const std::ffi::c_void))
+ } else {
+ // Same as generic Specialization::Object
+ write!(f, "[{}]", val.print(printer.ptr_map))
+ }
+ }
Specialization::Object(val) => write!(f, "[{}]", val.print(printer.ptr_map)),
// TODO(max): Ensure singleton classes never have Type specialization
Specialization::Type(val) if unsafe { rb_zjit_singleton_class_p(val) } =>
@@ -169,18 +177,6 @@ fn is_range_exact(val: VALUE) -> bool {
val.class_of() == unsafe { rb_cRange }
}
-fn is_module_exact(val: VALUE) -> bool {
- if val.builtin_type() != RUBY_T_MODULE {
- return false;
- }
-
- // For Class and Module instances, `class_of` will return the singleton class of the object.
- // Using `rb_obj_class` will give us the actual class of the module so we can check if the
- // object is an instance of Module, or an instance of Module subclass.
- let klass = unsafe { rb_obj_class(val) };
- klass == unsafe { rb_cModule }
-}
-
impl Type {
/// Create a `Type` from the given integer.
pub const fn fixnum(val: i64) -> Type {
@@ -212,9 +208,6 @@ impl Type {
if is_array_exact(val) { bits::ArrayExact }
else if is_hash_exact(val) { bits::HashExact }
else if is_string_exact(val) { bits::StringExact }
- // Singleton classes
- else if is_module_exact(val) { bits::ModuleExact }
- else if val.builtin_type() == RUBY_T_CLASS { bits::Class }
// Classes that have an immediate/heap split
else if val.class_of() == unsafe { rb_cInteger } { bits::Bignum }
else if val.class_of() == unsafe { rb_cFloat } { bits::HeapFloat }