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 }