Skip to content

Commit 6bfc99c

Browse files
committed
ZJIT: Add HIR DebugStatement insn to enable print-style debugging
Useful for printing more information while debugging but keeping the statements interleaved with the HIR. With a local change like this diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index bff384f..de5b41caa1 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -2491,6 +2491,8 @@ fn type_specialize(&mut self) { cme = unsafe { rb_aliased_callable_method_entry(cme) }; def_type = unsafe { get_cme_def_type(cme) }; } + eprintln!("WTH"); + hir_debug_statement!(self, block, "HOWDY def_type {:?}", def_type); if def_type == VM_METHOD_TYPE_ISEQ { // TODO(max): Allow non-iseq; cache cme // Only specialize positional-positional calls The print statement (1) shows up early (anywhere) whereas the HIR debug statement (2) is interleaved with the rest of the HIR so you can easily correlate debug info to the compilation of whatever function you are observing: 1. WTH <- shows up before all hir is dumped Optimized HIR: fn test@test.rb:2: bb0(): EntryPoint interpreter v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) Jump bb2(v4) bb2(v6:BasicObject): v11:Fixnum[1] = Const Value(1) 2. # HOWDY def_type 0 PatchPoint MethodRedefined(Object@0x10184ed10, foo@0x9c01, cme:0x101967060) The debug statements show up in HIR, LIR, and disasm: bb2(v6:BasicObject): v11:Fixnum[1] = Const Value(1) # HOWDY def_type 0 PatchPoint MethodRedefined(Object@0x1220fed10, foo@0x9c01, cme:0x123717060) -- PatchPoint Exit(PatchPoint(NoTracePoint)) # Insn: v11 Const Value(1) # Insn: v18 # HOWDY def_type 0 # Insn: v19 PatchPoint MethodRedefined(Object@0x103aaed00, foo@0x9c01, cme:0x103bc7080) PatchPoint Exit(PatchPoint(MethodRedefined(Object@0x103aaed00, foo@0x9c01, cme:0x103bc7080))) -- 0x1230bc0f0: nop # Insn: v11 Const Value(1) # Insn: v18 # HOWDY def_type 0 # Insn: v19 PatchPoint MethodRedefined(Object@0x103c6ed20, foo@0x9c01, cme:0x103d87070) 0x1230bc0f4: nop
1 parent 465a86c commit 6bfc99c

2 files changed

Lines changed: 29 additions & 5 deletions

File tree

zjit/src/codegen.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio
375375
Insn::ToRegexp { opt, values, state } => gen_toregexp(jit, asm, *opt, opnds!(values), &function.frame_state(*state)),
376376
Insn::Param => unreachable!("block.insns should not have Insn::Param"),
377377
Insn::Snapshot { .. } => return Ok(()), // we don't need to do anything for this instruction at the moment
378+
Insn::DebugStatement { .. } => return Ok(()), // debugging instruction, no code generation needed
378379
Insn::Jump(branch) => no_output!(gen_jump(jit, asm, branch)),
379380
Insn::IfTrue { val, target } => no_output!(gen_if_true(jit, asm, opnd!(val), target)),
380381
Insn::IfFalse { val, target } => no_output!(gen_if_false(jit, asm, opnd!(val), target)),

zjit/src/hir.rs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ use SendFallbackReason::*;
2020
mod tests;
2121
mod opt_tests;
2222

23+
#[allow(unused_macros)]
24+
macro_rules! hir_debug_statement {
25+
($func:expr, $block:expr, $($arg:tt)*) => {
26+
$func.push_debug_statement($block, format!($($arg)*))
27+
};
28+
}
29+
30+
#[allow(unused_imports)]
31+
pub(crate) use hir_debug_statement;
32+
2333
/// An index of an [`Insn`] in a [`Function`]. This is a popular
2434
/// type since this effectively acts as a pointer to an [`Insn`].
2535
/// See also: [`Function::find`].
@@ -932,6 +942,9 @@ pub enum Insn {
932942
/// Equivalent of RUBY_VM_CHECK_INTS. Automatically inserted by the compiler before jumps and
933943
/// return instructions.
934944
CheckInterrupts { state: InsnId },
945+
946+
/// Debugging statement that can be inserted into HIR for diagnostics
947+
DebugStatement { message: String },
935948
}
936949

937950
impl Insn {
@@ -943,7 +956,8 @@ impl Insn {
943956
| Insn::PatchPoint { .. } | Insn::SetIvar { .. } | Insn::SetClassVar { .. } | Insn::ArrayExtend { .. }
944957
| Insn::ArrayPush { .. } | Insn::SideExit { .. } | Insn::SetGlobal { .. }
945958
| Insn::SetLocal { .. } | Insn::Throw { .. } | Insn::IncrCounter(_) | Insn::IncrCounterPtr { .. }
946-
| Insn::CheckInterrupts { .. } | Insn::GuardBlockParamProxy { .. } | Insn::StoreField { .. } | Insn::WriteBarrier { .. } => false,
959+
| Insn::CheckInterrupts { .. } | Insn::GuardBlockParamProxy { .. } | Insn::StoreField { .. } | Insn::WriteBarrier { .. }
960+
| Insn::DebugStatement { .. } => false,
947961
_ => true,
948962
}
949963
}
@@ -1011,6 +1025,7 @@ impl Insn {
10111025
Insn::BoxBool { .. } => false,
10121026
Insn::IsBitEqual { .. } => false,
10131027
Insn::IsA { .. } => false,
1028+
Insn::DebugStatement { .. } => true,
10141029
_ => true,
10151030
}
10161031
}
@@ -1340,6 +1355,7 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
13401355
Insn::IncrCounter(counter) => write!(f, "IncrCounter {counter:?}"),
13411356
Insn::CheckInterrupts { .. } => write!(f, "CheckInterrupts"),
13421357
Insn::IsA { val, class } => write!(f, "IsA {val}, {class}"),
1358+
Insn::DebugStatement { message } => write!(f, "# {message}"),
13431359
}
13441360
}
13451361
}
@@ -1692,6 +1708,10 @@ impl Function {
16921708
id
16931709
}
16941710

1711+
pub fn push_debug_statement(&mut self, block: BlockId, message: String) -> InsnId {
1712+
self.push_insn(block, Insn::DebugStatement { message })
1713+
}
1714+
16951715
// Add an instruction to an SSA block
16961716
fn push_insn_id(&mut self, block: BlockId, insn_id: InsnId) -> InsnId {
16971717
self.blocks[block.0].insns.push(insn_id);
@@ -1811,7 +1831,8 @@ impl Function {
18111831
| LoadEC
18121832
| LoadSelf
18131833
| IncrCounterPtr {..}
1814-
| IncrCounter(_)) => result.clone(),
1834+
| IncrCounter(_)
1835+
| DebugStatement {..}) => result.clone(),
18151836
&Snapshot { state: FrameState { iseq, insn_idx, pc, ref stack, ref locals } } =>
18161837
Snapshot {
18171838
state: FrameState {
@@ -2023,7 +2044,7 @@ impl Function {
20232044
| Insn::PatchPoint { .. } | Insn::SetIvar { .. } | Insn::SetClassVar { .. } | Insn::ArrayExtend { .. }
20242045
| Insn::ArrayPush { .. } | Insn::SideExit { .. } | Insn::SetLocal { .. } | Insn::IncrCounter(_)
20252046
| Insn::CheckInterrupts { .. } | Insn::GuardBlockParamProxy { .. } | Insn::IncrCounterPtr { .. }
2026-
| Insn::StoreField { .. } | Insn::WriteBarrier { .. } =>
2047+
| Insn::StoreField { .. } | Insn::WriteBarrier { .. } | Insn::DebugStatement { .. } =>
20272048
panic!("Cannot infer type of instruction with no output: {}. See Insn::has_output().", self.insns[insn.0]),
20282049
Insn::Const { val: Const::Value(val) } => Type::from_value(*val),
20292050
Insn::Const { val: Const::CBool(val) } => Type::from_cbool(*val),
@@ -3602,7 +3623,8 @@ impl Function {
36023623
| &Insn::PutSpecialObject { .. }
36033624
| &Insn::IsBlockGiven
36043625
| &Insn::IncrCounter(_)
3605-
| &Insn::IncrCounterPtr { .. } =>
3626+
| &Insn::IncrCounterPtr { .. }
3627+
| &Insn::DebugStatement { .. } =>
36063628
{}
36073629
&Insn::PatchPoint { state, .. }
36083630
| &Insn::CheckInterrupts { state }
@@ -4329,7 +4351,8 @@ impl Function {
43294351
| Insn::GetSpecialNumber { .. }
43304352
| Insn::GetSpecialSymbol { .. }
43314353
| Insn::GetLocal { .. }
4332-
| Insn::StoreField { .. } => {
4354+
| Insn::StoreField { .. }
4355+
| Insn::DebugStatement { .. } => {
43334356
Ok(())
43344357
}
43354358
// Instructions with 1 Ruby object operand

0 commit comments

Comments
 (0)