diff options
| author | Max Bernstein <rubybugs@bernsteinbear.com> | 2026-02-09 12:40:27 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-02-09 12:40:27 -0500 |
| commit | 21862be0afdd76d80875b4f98ce104113090c0c3 (patch) | |
| tree | de2c49a3c7645da748692b9b6877452cffb6f35f | |
| parent | 84c9822fefa442ef2fff174437a8bd723c8c658b (diff) | |
ZJIT: Add mask_name to GuardXYZBitsSet (#16064)
This makes HIR easier to debug.
| -rw-r--r-- | zjit/src/codegen.rs | 4 | ||||
| -rw-r--r-- | zjit/src/cruby.rs | 9 | ||||
| -rw-r--r-- | zjit/src/hir.rs | 18 | ||||
| -rw-r--r-- | zjit/src/hir/opt_tests.rs | 24 | ||||
| -rw-r--r-- | zjit/src/hir/tests.rs | 4 |
5 files changed, 35 insertions, 24 deletions
diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index a1ac23311b..2fe9958e62 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -536,8 +536,8 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio Insn::GuardType { val, guard_type, state } => gen_guard_type(jit, asm, opnd!(val), *guard_type, &function.frame_state(*state)), Insn::GuardTypeNot { val, guard_type, state } => gen_guard_type_not(jit, asm, opnd!(val), *guard_type, &function.frame_state(*state)), &Insn::GuardBitEquals { val, expected, reason, state } => gen_guard_bit_equals(jit, asm, opnd!(val), expected, reason, &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::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::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))), diff --git a/zjit/src/cruby.rs b/zjit/src/cruby.rs index 8c57e4cc71..8e569793a8 100644 --- a/zjit/src/cruby.rs +++ b/zjit/src/cruby.rs @@ -783,6 +783,12 @@ impl ID { } } +impl Display for ID { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.contents_lossy()) + } +} + /// Produce a Ruby string from a Rust string slice pub fn rust_str_to_ruby(str: &str) -> VALUE { unsafe { rb_utf8_str_new(str.as_ptr() as *const _, str.len() as i64) } @@ -1401,6 +1407,9 @@ pub(crate) mod ids { name: _ep_method_entry name: _ep_specval name: _rbasic_flags + name: RUBY_FL_FREEZE + name: RUBY_ELTS_SHARED + name: VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM } /// Get an CRuby `ID` to an interned string, e.g. a particular method name. diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index eba3edee99..5d8cb2f7c0 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -1027,9 +1027,9 @@ pub enum Insn { /// Side-exit if val is not the expected Const. GuardBitEquals { val: InsnId, expected: Const, reason: SideExitReason, state: InsnId }, /// Side-exit if (val & mask) == 0 - GuardAnyBitSet { val: InsnId, mask: Const, reason: SideExitReason, state: InsnId }, + GuardAnyBitSet { val: InsnId, mask: Const, mask_name: Option<ID>, reason: SideExitReason, state: InsnId }, /// Side-exit if (val & mask) != 0 - GuardNoBitsSet { val: InsnId, mask: Const, reason: SideExitReason, state: InsnId }, + GuardNoBitsSet { val: InsnId, mask: Const, mask_name: Option<ID>, reason: SideExitReason, state: InsnId }, /// Side-exit if left is not greater than or equal to right (both operands are C long). GuardGreaterEq { left: InsnId, right: InsnId, state: InsnId }, /// Side-exit if left is not less than right (both operands are C long). @@ -1550,7 +1550,9 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> { Insn::HasType { val, expected, .. } => { write!(f, "HasType {val}, {}", expected.print(self.ptr_map)) }, Insn::GuardTypeNot { val, guard_type, .. } => { write!(f, "GuardTypeNot {val}, {}", guard_type.print(self.ptr_map)) }, Insn::GuardBitEquals { val, expected, .. } => { write!(f, "GuardBitEquals {val}, {}", expected.print(self.ptr_map)) }, + 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)) }, Insn::GuardNoBitsSet { val, mask, .. } => { write!(f, "GuardNoBitsSet {val}, {}", mask.print(self.ptr_map)) }, Insn::GuardLess { left, right, .. } => write!(f, "GuardLess {left}, {right}"), Insn::GuardGreaterEq { left, right, .. } => write!(f, "GuardGreaterEq {left}, {right}"), @@ -2236,8 +2238,8 @@ impl Function { &GuardType { val, guard_type, state } => GuardType { val: find!(val), guard_type, state }, &GuardTypeNot { val, guard_type, state } => GuardTypeNot { val: find!(val), guard_type, state }, &GuardBitEquals { val, expected, reason, state } => GuardBitEquals { val: find!(val), expected, reason, state }, - &GuardAnyBitSet { val, mask, reason, state } => GuardAnyBitSet { val: find!(val), mask, reason, state }, - &GuardNoBitsSet { val, mask, reason, state } => GuardNoBitsSet { val: find!(val), mask, reason, state }, + &GuardAnyBitSet { val, mask, mask_name, reason, state } => GuardAnyBitSet { val: find!(val), mask, mask_name, reason, state }, + &GuardNoBitsSet { val, mask, mask_name, reason, state } => GuardNoBitsSet { val: find!(val), mask, mask_name, reason, state }, &GuardGreaterEq { left, right, state } => GuardGreaterEq { left: find!(left), right: find!(right), state }, &GuardLess { left, right, state } => GuardLess { left: find!(left), right: find!(right), state }, &IsBlockGiven { lep } => IsBlockGiven { lep: find!(lep) }, @@ -3004,12 +3006,12 @@ impl Function { pub fn guard_not_frozen(&mut self, block: BlockId, recv: InsnId, state: InsnId) { let flags = self.load_rbasic_flags(block, recv); - self.push_insn(block, Insn::GuardNoBitsSet { val: flags, mask: Const::CUInt64(RUBY_FL_FREEZE as u64), reason: SideExitReason::GuardNotFrozen, state }); + self.push_insn(block, Insn::GuardNoBitsSet { val: flags, mask: Const::CUInt64(RUBY_FL_FREEZE as u64), mask_name: Some(ID!(RUBY_FL_FREEZE)), reason: SideExitReason::GuardNotFrozen, state }); } pub fn guard_not_shared(&mut self, block: BlockId, recv: InsnId, state: InsnId) { let flags = self.load_rbasic_flags(block, recv); - self.push_insn(block, Insn::GuardNoBitsSet { val: flags, mask: Const::CUInt64(RUBY_ELTS_SHARED as u64), reason: SideExitReason::GuardNotShared, state }); + self.push_insn(block, Insn::GuardNoBitsSet { val: flags, mask: Const::CUInt64(RUBY_ELTS_SHARED as u64), mask_name: Some(ID!(RUBY_ELTS_SHARED)), reason: SideExitReason::GuardNotShared, state }); } /// Rewrite eligible Send/SendWithoutBlock opcodes into SendDirect @@ -6794,7 +6796,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { let ep = fun.push_insn(block, Insn::GetEP { level }); let flags = fun.push_insn(block, Insn::LoadField { recv: ep, id: ID!(_env_data_index_flags), offset: SIZEOF_VALUE_I32 * (VM_ENV_DATA_INDEX_FLAGS as i32), return_type: types::CInt64 }); - fun.push_insn(block, Insn::GuardNoBitsSet { val: flags, mask: Const::CUInt64(VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM.into()), reason: SideExitReason::BlockParamProxyModified, state: exit_id }); + fun.push_insn(block, Insn::GuardNoBitsSet { val: flags, mask: Const::CUInt64(VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM.into()), mask_name: Some(ID!(VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM)), reason: SideExitReason::BlockParamProxyModified, state: exit_id }); let block_handler = fun.push_insn(block, Insn::LoadField { recv: ep, id: ID!(_env_data_index_specval), offset: SIZEOF_VALUE_I32 * VM_ENV_DATA_INDEX_SPECVAL, return_type: types::CInt64 }); @@ -6812,7 +6814,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { const _: () = assert!(RUBY_SYMBOL_FLAG & 1 == 0, "guard below rejects symbol block handlers"); // Bail out if the block handler is neither ISEQ nor ifunc - fun.push_insn(block, Insn::GuardAnyBitSet { val: block_handler, mask: Const::CUInt64(0x1), reason: SideExitReason::BlockParamProxyNotIseqOrIfunc, state: exit_id }); + fun.push_insn(block, Insn::GuardAnyBitSet { val: block_handler, mask: Const::CUInt64(0x1), mask_name: None, reason: SideExitReason::BlockParamProxyNotIseqOrIfunc, state: exit_id }); // TODO(Shopify/ruby#753): GC root, so we should be able to avoid unnecessary GC tracing state.stack_push(fun.push_insn(block, Insn::Const { val: Const::Value(unsafe { rb_block_param_proxy }) })); } diff --git a/zjit/src/hir/opt_tests.rs b/zjit/src/hir/opt_tests.rs index e80175c679..d0d2e19078 100644 --- a/zjit/src/hir/opt_tests.rs +++ b/zjit/src/hir/opt_tests.rs @@ -3888,7 +3888,7 @@ mod hir_opt_tests { bb2(v8:BasicObject, v9:BasicObject): v14:CPtr = GetEP 0 v15:CInt64 = LoadField v14, :_env_data_index_flags@0x1000 - v16:CInt64 = GuardNoBitsSet v15, CUInt64(512) + v16:CInt64 = GuardNoBitsSet v15, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM=CUInt64(512) v17:CInt64 = LoadField v14, :_env_data_index_specval@0x1001 v18:CInt64 = GuardAnyBitSet v17, CUInt64(1) v19:HeapObject[BlockParamProxy] = Const Value(VALUE(0x1008)) @@ -6560,7 +6560,7 @@ mod hir_opt_tests { v13:ArrayExact = NewArray v15:CPtr = GetEP 0 v16:CInt64 = LoadField v15, :_env_data_index_flags@0x1000 - v17:CInt64 = GuardNoBitsSet v16, CUInt64(512) + v17:CInt64 = GuardNoBitsSet v16, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM=CUInt64(512) v18:CInt64 = LoadField v15, :_env_data_index_specval@0x1001 v19:CInt64 = GuardAnyBitSet v18, CUInt64(1) v20:HeapObject[BlockParamProxy] = Const Value(VALUE(0x1008)) @@ -6591,7 +6591,7 @@ mod hir_opt_tests { v13:ArrayExact = NewArray v15:CPtr = GetEP 0 v16:CInt64 = LoadField v15, :_env_data_index_flags@0x1000 - v17:CInt64 = GuardNoBitsSet v16, CUInt64(512) + v17:CInt64 = GuardNoBitsSet v16, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM=CUInt64(512) v18:CInt64 = LoadField v15, :_env_data_index_specval@0x1001 v19:CInt64[0] = GuardBitEquals v18, CInt64(0) v20:NilClass = Const Value(nil) @@ -6625,7 +6625,7 @@ mod hir_opt_tests { v10:ArrayExact = NewArray v12:CPtr = GetEP 1 v13:CInt64 = LoadField v12, :_env_data_index_flags@0x1000 - v14:CInt64 = GuardNoBitsSet v13, CUInt64(512) + v14:CInt64 = GuardNoBitsSet v13, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM=CUInt64(512) v15:CInt64 = LoadField v12, :_env_data_index_specval@0x1001 v16:CInt64 = GuardAnyBitSet v15, CUInt64(1) v17:HeapObject[BlockParamProxy] = Const Value(VALUE(0x1008)) @@ -6987,7 +6987,7 @@ mod hir_opt_tests { PatchPoint MethodRedefined(C@0x1000, foo=@0x1008, cme:0x1010) v29:HeapObject[class_exact:C] = GuardType v11, HeapObject[class_exact:C] v30:CUInt64 = LoadField v29, :_rbasic_flags@0x1038 - v31:CUInt64 = GuardNoBitsSet v30, CUInt64(2048) + v31:CUInt64 = GuardNoBitsSet v30, RUBY_FL_FREEZE=CUInt64(2048) StoreField v29, :foo=@0x1039, v12 WriteBarrier v29, v12 CheckInterrupts @@ -7020,7 +7020,7 @@ mod hir_opt_tests { PatchPoint MethodRedefined(C@0x1000, foo=@0x1008, cme:0x1010) v29:HeapObject[class_exact:C] = GuardType v11, HeapObject[class_exact:C] v30:CUInt64 = LoadField v29, :_rbasic_flags@0x1038 - v31:CUInt64 = GuardNoBitsSet v30, CUInt64(2048) + v31:CUInt64 = GuardNoBitsSet v30, RUBY_FL_FREEZE=CUInt64(2048) v32:CPtr = LoadField v29, :_as_heap@0x1039 StoreField v32, :foo=@0x103a, v12 WriteBarrier v29, v12 @@ -7641,9 +7641,9 @@ mod hir_opt_tests { PatchPoint MethodRedefined(Array@0x1000, []=@0x1008, cme:0x1010) v31:ArrayExact = GuardType v9, ArrayExact v32:CUInt64 = LoadField v31, :_rbasic_flags@0x1038 - v33:CUInt64 = GuardNoBitsSet v32, CUInt64(2048) + v33:CUInt64 = GuardNoBitsSet v32, RUBY_FL_FREEZE=CUInt64(2048) v34:CUInt64 = LoadField v31, :_rbasic_flags@0x1038 - v35:CUInt64 = GuardNoBitsSet v34, CUInt64(4096) + v35:CUInt64 = GuardNoBitsSet v34, RUBY_ELTS_SHARED=CUInt64(4096) v36:CInt64[1] = UnboxFixnum v16 v37:CInt64 = ArrayLength v31 v38:CInt64[1] = GuardLess v36, v37 @@ -7683,9 +7683,9 @@ mod hir_opt_tests { v35:ArrayExact = GuardType v13, ArrayExact v36:Fixnum = GuardType v14, Fixnum v37:CUInt64 = LoadField v35, :_rbasic_flags@0x1038 - v38:CUInt64 = GuardNoBitsSet v37, CUInt64(2048) + v38:CUInt64 = GuardNoBitsSet v37, RUBY_FL_FREEZE=CUInt64(2048) v39:CUInt64 = LoadField v35, :_rbasic_flags@0x1038 - v40:CUInt64 = GuardNoBitsSet v39, CUInt64(4096) + v40:CUInt64 = GuardNoBitsSet v39, RUBY_ELTS_SHARED=CUInt64(4096) v41:CInt64 = UnboxFixnum v36 v42:CInt64 = ArrayLength v35 v43:CInt64 = GuardLess v41, v42 @@ -8011,7 +8011,7 @@ mod hir_opt_tests { v36:CInt64[0] = Const CInt64(0) v37:CInt64 = GuardGreaterEq v35, v36 v38:CUInt64 = LoadField v30, :_rbasic_flags@0x1039 - v39:CUInt64 = GuardNoBitsSet v38, CUInt64(2048) + v39:CUInt64 = GuardNoBitsSet v38, RUBY_FL_FREEZE=CUInt64(2048) v40:Fixnum = StringSetbyteFixnum v30, v31, v32 IncrCounter inline_cfunc_optimized_send_count CheckInterrupts @@ -8053,7 +8053,7 @@ mod hir_opt_tests { v36:CInt64[0] = Const CInt64(0) v37:CInt64 = GuardGreaterEq v35, v36 v38:CUInt64 = LoadField v30, :_rbasic_flags@0x1039 - v39:CUInt64 = GuardNoBitsSet v38, CUInt64(2048) + v39:CUInt64 = GuardNoBitsSet v38, RUBY_FL_FREEZE=CUInt64(2048) v40:Fixnum = StringSetbyteFixnum v30, v31, v32 IncrCounter inline_cfunc_optimized_send_count CheckInterrupts diff --git a/zjit/src/hir/tests.rs b/zjit/src/hir/tests.rs index 17b156a663..fab8c6e262 100644 --- a/zjit/src/hir/tests.rs +++ b/zjit/src/hir/tests.rs @@ -2058,7 +2058,7 @@ pub mod hir_build_tests { PatchPoint NoEPEscape(test) v33:CPtr = GetEP 0 v34:CInt64 = LoadField v33, :_env_data_index_flags@0x1000 - v35:CInt64 = GuardNoBitsSet v34, CUInt64(512) + v35:CInt64 = GuardNoBitsSet v34, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM=CUInt64(512) v36:CInt64 = LoadField v33, :_env_data_index_specval@0x1001 v37:CInt64 = GuardAnyBitSet v36, CUInt64(1) v38:HeapObject[BlockParamProxy] = Const Value(VALUE(0x1008)) @@ -3435,7 +3435,7 @@ pub mod hir_build_tests { PatchPoint NoEPEscape(open) v31:CPtr = GetEP 0 v32:CInt64 = LoadField v31, :_env_data_index_flags@0x1000 - v33:CInt64 = GuardNoBitsSet v32, CUInt64(512) + v33:CInt64 = GuardNoBitsSet v32, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM=CUInt64(512) v34:CInt64 = LoadField v31, :_env_data_index_specval@0x1001 v35:CInt64 = GuardAnyBitSet v34, CUInt64(1) v36:HeapObject[BlockParamProxy] = Const Value(VALUE(0x1008)) |
