ZJIT: Add the ISEQ name to Block asm comments (#14070)

This commit is contained in:
Takashi Kokubun 2025-07-31 14:28:08 -07:00 committed by GitHub
parent 5a7be72c06
commit 543f8dcad3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 30 additions and 22 deletions

View file

@ -244,7 +244,11 @@ fn gen_function(cb: &mut CodeBlock, iseq: IseqPtr, function: &Function) -> Optio
let reverse_post_order = function.rpo(); let reverse_post_order = function.rpo();
for &block_id in reverse_post_order.iter() { for &block_id in reverse_post_order.iter() {
let block = function.block(block_id); let block = function.block(block_id);
asm_comment!(asm, "Block: {block_id}({})", block.params().map(|param| format!("{param}")).collect::<Vec<_>>().join(", ")); asm_comment!(
asm, "{block_id}({}): {}",
block.params().map(|param| format!("{param}")).collect::<Vec<_>>().join(", "),
iseq_get_location(iseq, block.insn_idx),
);
// Write a label to jump to the basic block // Write a label to jump to the basic block
let label = jit.get_label(&mut asm, block_id); let label = jit.get_label(&mut asm, block_id);

View file

@ -715,7 +715,7 @@ pub fn iseq_name(iseq: IseqPtr) -> String {
// Location is the file defining the method, colon, method name. // Location is the file defining the method, colon, method name.
// Filenames are sometimes internal strings supplied to eval, // Filenames are sometimes internal strings supplied to eval,
// so be careful with them. // so be careful with them.
pub fn iseq_get_location(iseq: IseqPtr, pos: u16) -> String { pub fn iseq_get_location(iseq: IseqPtr, pos: u32) -> String {
let iseq_path = unsafe { rb_iseq_path(iseq) }; let iseq_path = unsafe { rb_iseq_path(iseq) };
let iseq_lineno = unsafe { rb_iseq_line_no(iseq, pos as usize) }; let iseq_lineno = unsafe { rb_iseq_line_no(iseq, pos as usize) };

View file

@ -796,6 +796,8 @@ impl std::fmt::Display for Insn {
/// An extended basic block in a [`Function`]. /// An extended basic block in a [`Function`].
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct Block { pub struct Block {
/// The index of the first YARV instruction for the Block in the ISEQ
pub insn_idx: u32,
params: Vec<InsnId>, params: Vec<InsnId>,
insns: Vec<InsnId>, insns: Vec<InsnId>,
} }
@ -1024,9 +1026,11 @@ impl Function {
} }
} }
fn new_block(&mut self) -> BlockId { fn new_block(&mut self, insn_idx: u32) -> BlockId {
let id = BlockId(self.blocks.len()); let id = BlockId(self.blocks.len());
self.blocks.push(Block::default()); let mut block = Block::default();
block.insn_idx = insn_idx;
self.blocks.push(block);
id id
} }
@ -2543,7 +2547,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
if insn_idx == 0 { if insn_idx == 0 {
todo!("Separate entry block for param/self/..."); todo!("Separate entry block for param/self/...");
} }
insn_idx_to_block.insert(insn_idx, fun.new_block()); insn_idx_to_block.insert(insn_idx, fun.new_block(insn_idx));
} }
// Iteratively fill out basic blocks using a queue // Iteratively fill out basic blocks using a queue
@ -3243,7 +3247,7 @@ mod rpo_tests {
fn jump() { fn jump() {
let mut function = Function::new(std::ptr::null()); let mut function = Function::new(std::ptr::null());
let entry = function.entry_block; let entry = function.entry_block;
let exit = function.new_block(); let exit = function.new_block(0);
function.push_insn(entry, Insn::Jump(BranchEdge { target: exit, args: vec![] })); function.push_insn(entry, Insn::Jump(BranchEdge { target: exit, args: vec![] }));
let val = function.push_insn(entry, Insn::Const { val: Const::Value(Qnil) }); let val = function.push_insn(entry, Insn::Const { val: Const::Value(Qnil) });
function.push_insn(entry, Insn::Return { val }); function.push_insn(entry, Insn::Return { val });
@ -3254,8 +3258,8 @@ mod rpo_tests {
fn diamond_iftrue() { fn diamond_iftrue() {
let mut function = Function::new(std::ptr::null()); let mut function = Function::new(std::ptr::null());
let entry = function.entry_block; let entry = function.entry_block;
let side = function.new_block(); let side = function.new_block(0);
let exit = function.new_block(); let exit = function.new_block(0);
function.push_insn(side, Insn::Jump(BranchEdge { target: exit, args: vec![] })); function.push_insn(side, Insn::Jump(BranchEdge { target: exit, args: vec![] }));
let val = function.push_insn(entry, Insn::Const { val: Const::Value(Qnil) }); let val = function.push_insn(entry, Insn::Const { val: Const::Value(Qnil) });
function.push_insn(entry, Insn::IfTrue { val, target: BranchEdge { target: side, args: vec![] } }); function.push_insn(entry, Insn::IfTrue { val, target: BranchEdge { target: side, args: vec![] } });
@ -3269,8 +3273,8 @@ mod rpo_tests {
fn diamond_iffalse() { fn diamond_iffalse() {
let mut function = Function::new(std::ptr::null()); let mut function = Function::new(std::ptr::null());
let entry = function.entry_block; let entry = function.entry_block;
let side = function.new_block(); let side = function.new_block(0);
let exit = function.new_block(); let exit = function.new_block(0);
function.push_insn(side, Insn::Jump(BranchEdge { target: exit, args: vec![] })); function.push_insn(side, Insn::Jump(BranchEdge { target: exit, args: vec![] }));
let val = function.push_insn(entry, Insn::Const { val: Const::Value(Qnil) }); let val = function.push_insn(entry, Insn::Const { val: Const::Value(Qnil) });
function.push_insn(entry, Insn::IfFalse { val, target: BranchEdge { target: side, args: vec![] } }); function.push_insn(entry, Insn::IfFalse { val, target: BranchEdge { target: side, args: vec![] } });
@ -3325,7 +3329,7 @@ mod validation_tests {
fn iftrue_mismatch_args() { fn iftrue_mismatch_args() {
let mut function = Function::new(std::ptr::null()); let mut function = Function::new(std::ptr::null());
let entry = function.entry_block; let entry = function.entry_block;
let side = function.new_block(); let side = function.new_block(0);
let val = function.push_insn(entry, Insn::Const { val: Const::Value(Qnil) }); let val = function.push_insn(entry, Insn::Const { val: Const::Value(Qnil) });
function.push_insn(entry, Insn::IfTrue { val, target: BranchEdge { target: side, args: vec![val, val, val] } }); function.push_insn(entry, Insn::IfTrue { val, target: BranchEdge { target: side, args: vec![val, val, val] } });
assert_matches_err(function.validate(), ValidationError::MismatchedBlockArity(entry, 0, 3)); assert_matches_err(function.validate(), ValidationError::MismatchedBlockArity(entry, 0, 3));
@ -3335,7 +3339,7 @@ mod validation_tests {
fn iffalse_mismatch_args() { fn iffalse_mismatch_args() {
let mut function = Function::new(std::ptr::null()); let mut function = Function::new(std::ptr::null());
let entry = function.entry_block; let entry = function.entry_block;
let side = function.new_block(); let side = function.new_block(0);
let val = function.push_insn(entry, Insn::Const { val: Const::Value(Qnil) }); let val = function.push_insn(entry, Insn::Const { val: Const::Value(Qnil) });
function.push_insn(entry, Insn::IfFalse { val, target: BranchEdge { target: side, args: vec![val, val, val] } }); function.push_insn(entry, Insn::IfFalse { val, target: BranchEdge { target: side, args: vec![val, val, val] } });
assert_matches_err(function.validate(), ValidationError::MismatchedBlockArity(entry, 0, 3)); assert_matches_err(function.validate(), ValidationError::MismatchedBlockArity(entry, 0, 3));
@ -3345,7 +3349,7 @@ mod validation_tests {
fn jump_mismatch_args() { fn jump_mismatch_args() {
let mut function = Function::new(std::ptr::null()); let mut function = Function::new(std::ptr::null());
let entry = function.entry_block; let entry = function.entry_block;
let side = function.new_block(); let side = function.new_block(0);
let val = function.push_insn(entry, Insn::Const { val: Const::Value(Qnil) }); let val = function.push_insn(entry, Insn::Const { val: Const::Value(Qnil) });
function.push_insn(entry, Insn::Jump ( BranchEdge { target: side, args: vec![val, val, val] } )); function.push_insn(entry, Insn::Jump ( BranchEdge { target: side, args: vec![val, val, val] } ));
assert_matches_err(function.validate(), ValidationError::MismatchedBlockArity(entry, 0, 3)); assert_matches_err(function.validate(), ValidationError::MismatchedBlockArity(entry, 0, 3));
@ -3377,8 +3381,8 @@ mod validation_tests {
// This tests that one branch is missing a definition which fails. // This tests that one branch is missing a definition which fails.
let mut function = Function::new(std::ptr::null()); let mut function = Function::new(std::ptr::null());
let entry = function.entry_block; let entry = function.entry_block;
let side = function.new_block(); let side = function.new_block(0);
let exit = function.new_block(); let exit = function.new_block(0);
let v0 = function.push_insn(side, Insn::Const { val: Const::Value(VALUE::fixnum_from_usize(3)) }); let v0 = function.push_insn(side, Insn::Const { val: Const::Value(VALUE::fixnum_from_usize(3)) });
function.push_insn(side, Insn::Jump(BranchEdge { target: exit, args: vec![] })); function.push_insn(side, Insn::Jump(BranchEdge { target: exit, args: vec![] }));
let val1 = function.push_insn(entry, Insn::Const { val: Const::CBool(false) }); let val1 = function.push_insn(entry, Insn::Const { val: Const::CBool(false) });
@ -3396,8 +3400,8 @@ mod validation_tests {
// This tests that both branches with a definition succeeds. // This tests that both branches with a definition succeeds.
let mut function = Function::new(std::ptr::null()); let mut function = Function::new(std::ptr::null());
let entry = function.entry_block; let entry = function.entry_block;
let side = function.new_block(); let side = function.new_block(0);
let exit = function.new_block(); let exit = function.new_block(0);
let v0 = function.push_insn(entry, Insn::Const { val: Const::Value(VALUE::fixnum_from_usize(3)) }); let v0 = function.push_insn(entry, Insn::Const { val: Const::Value(VALUE::fixnum_from_usize(3)) });
function.push_insn(side, Insn::Jump(BranchEdge { target: exit, args: vec![] })); function.push_insn(side, Insn::Jump(BranchEdge { target: exit, args: vec![] }));
let val = function.push_insn(entry, Insn::Const { val: Const::CBool(false) }); let val = function.push_insn(entry, Insn::Const { val: Const::CBool(false) });
@ -3437,7 +3441,7 @@ mod validation_tests {
let mut function = Function::new(std::ptr::null()); let mut function = Function::new(std::ptr::null());
let entry = function.entry_block; let entry = function.entry_block;
let val = function.push_insn(entry, Insn::Const { val: Const::Value(Qnil) }); let val = function.push_insn(entry, Insn::Const { val: Const::Value(Qnil) });
let exit = function.new_block(); let exit = function.new_block(0);
function.push_insn(entry, Insn::Jump(BranchEdge { target: exit, args: vec![] })); function.push_insn(entry, Insn::Jump(BranchEdge { target: exit, args: vec![] }));
function.push_insn_id(exit, val); function.push_insn_id(exit, val);
function.push_insn(exit, Insn::Return { val }); function.push_insn(exit, Insn::Return { val });
@ -3532,8 +3536,8 @@ mod infer_tests {
fn diamond_iffalse_merge_fixnum() { fn diamond_iffalse_merge_fixnum() {
let mut function = Function::new(std::ptr::null()); let mut function = Function::new(std::ptr::null());
let entry = function.entry_block; let entry = function.entry_block;
let side = function.new_block(); let side = function.new_block(0);
let exit = function.new_block(); let exit = function.new_block(0);
let v0 = function.push_insn(side, Insn::Const { val: Const::Value(VALUE::fixnum_from_usize(3)) }); let v0 = function.push_insn(side, Insn::Const { val: Const::Value(VALUE::fixnum_from_usize(3)) });
function.push_insn(side, Insn::Jump(BranchEdge { target: exit, args: vec![v0] })); function.push_insn(side, Insn::Jump(BranchEdge { target: exit, args: vec![v0] }));
let val = function.push_insn(entry, Insn::Const { val: Const::CBool(false) }); let val = function.push_insn(entry, Insn::Const { val: Const::CBool(false) });
@ -3551,8 +3555,8 @@ mod infer_tests {
fn diamond_iffalse_merge_bool() { fn diamond_iffalse_merge_bool() {
let mut function = Function::new(std::ptr::null()); let mut function = Function::new(std::ptr::null());
let entry = function.entry_block; let entry = function.entry_block;
let side = function.new_block(); let side = function.new_block(0);
let exit = function.new_block(); let exit = function.new_block(0);
let v0 = function.push_insn(side, Insn::Const { val: Const::Value(Qtrue) }); let v0 = function.push_insn(side, Insn::Const { val: Const::Value(Qtrue) });
function.push_insn(side, Insn::Jump(BranchEdge { target: exit, args: vec![v0] })); function.push_insn(side, Insn::Jump(BranchEdge { target: exit, args: vec![v0] }));
let val = function.push_insn(entry, Insn::Const { val: Const::CBool(false) }); let val = function.push_insn(entry, Insn::Const { val: Const::CBool(false) });