1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

YJIT: Allow --yjit-dump-disasm to dump into a file (#6552)

* YJIT: Allow --yjit-dump-disasm to dump into a file

* YJIT: Move IO implementation to disasm.rs

* YJIT: More consistent naming
This commit is contained in:
Takashi Kokubun 2022-10-17 10:47:22 -07:00 committed by GitHub
parent 64c52c4282
commit f11765aef0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
Notes: git 2022-10-17 17:47:41 +00:00
Merged-By: k0kubun <takashikkbn@gmail.com>
4 changed files with 40 additions and 29 deletions

View file

@ -1100,13 +1100,10 @@ impl Assembler
let gc_offsets = self.compile_with_regs(cb, alloc_regs); let gc_offsets = self.compile_with_regs(cb, alloc_regs);
#[cfg(feature = "disasm")] #[cfg(feature = "disasm")]
if get_option!(dump_disasm) == DumpDisasm::All || (get_option!(dump_disasm) == DumpDisasm::Inline && cb.inline()) { if let Some(dump_disasm) = get_option_ref!(dump_disasm) {
use crate::disasm::disasm_addr_range; use crate::disasm::dump_disasm_addr_range;
let last_ptr = cb.get_write_ptr(); let end_addr = cb.get_write_ptr().raw_ptr();
let disasm = disasm_addr_range(cb, start_addr, last_ptr.raw_ptr() as usize - start_addr as usize); dump_disasm_addr_range(cb, start_addr, end_addr, dump_disasm)
if disasm.len() > 0 {
println!("{disasm}");
}
} }
gc_offsets gc_offsets
} }

View file

@ -612,7 +612,7 @@ pub fn gen_entry_prologue(cb: &mut CodeBlock, iseq: IseqPtr, insn_idx: u32) -> O
let code_ptr = cb.get_write_ptr(); let code_ptr = cb.get_write_ptr();
let mut asm = Assembler::new(); let mut asm = Assembler::new();
if get_option!(dump_disasm).is_enabled() { if get_option_ref!(dump_disasm).is_some() {
asm.comment(&format!("YJIT entry: {}", iseq_get_location(iseq))); asm.comment(&format!("YJIT entry: {}", iseq_get_location(iseq)));
} else { } else {
asm.comment("YJIT entry"); asm.comment("YJIT entry");
@ -742,7 +742,7 @@ pub fn gen_single_block(
let mut asm = Assembler::new(); let mut asm = Assembler::new();
#[cfg(feature = "disasm")] #[cfg(feature = "disasm")]
if get_option!(dump_disasm).is_enabled() { if get_option_ref!(dump_disasm).is_some() {
asm.comment(&format!("Block: {} (ISEQ offset: {})", iseq_get_location(blockid.iseq), blockid.idx)); asm.comment(&format!("Block: {} (ISEQ offset: {})", iseq_get_location(blockid.iseq), blockid.idx));
} }

View file

@ -2,6 +2,7 @@ use crate::core::*;
use crate::cruby::*; use crate::cruby::*;
use crate::yjit::yjit_enabled_p; use crate::yjit::yjit_enabled_p;
use crate::asm::CodeBlock; use crate::asm::CodeBlock;
use crate::options::DumpDisasm;
use std::fmt::Write; use std::fmt::Write;
@ -95,7 +96,7 @@ pub fn disasm_iseq_insn_range(iseq: IseqPtr, start_idx: u32, end_idx: u32) -> St
writeln!(out, "== {:=<60}", block_ident).unwrap(); writeln!(out, "== {:=<60}", block_ident).unwrap();
// Disassemble the instructions // Disassemble the instructions
out.push_str(&disasm_addr_range(global_cb, start_addr, code_size)); out.push_str(&disasm_addr_range(global_cb, start_addr, (start_addr as usize + code_size) as *const u8));
// If this is not the last block // If this is not the last block
if block_idx < block_list.len() - 1 { if block_idx < block_list.len() - 1 {
@ -115,9 +116,25 @@ pub fn disasm_iseq_insn_range(iseq: IseqPtr, start_idx: u32, end_idx: u32) -> St
return out; return out;
} }
#[cfg(feature = "disasm")]
pub fn dump_disasm_addr_range(cb: &CodeBlock, start_addr: *const u8, end_addr: *const u8, dump_disasm: &DumpDisasm) {
use std::fs::File;
use std::io::Write;
let disasm = disasm_addr_range(cb, start_addr, end_addr);
if disasm.len() > 0 {
match dump_disasm {
DumpDisasm::Stdout => println!("{disasm}"),
DumpDisasm::File(path) => {
let mut f = File::options().append(true).create(true).open(path).unwrap();
f.write_all(disasm.as_bytes()).unwrap();
}
};
}
}
#[cfg(feature = "disasm")] #[cfg(feature = "disasm")]
pub fn disasm_addr_range(cb: &CodeBlock, start_addr: *const u8, code_size: usize) -> String { pub fn disasm_addr_range(cb: &CodeBlock, start_addr: *const u8, end_addr: *const u8) -> String {
let mut out = String::from(""); let mut out = String::from("");
// Initialize capstone // Initialize capstone
@ -141,6 +158,7 @@ pub fn disasm_addr_range(cb: &CodeBlock, start_addr: *const u8, code_size: usize
cs.set_skipdata(true).unwrap(); cs.set_skipdata(true).unwrap();
// Disassemble the instructions // Disassemble the instructions
let code_size = end_addr as usize - start_addr as usize;
let code_slice = unsafe { std::slice::from_raw_parts(start_addr, code_size) }; let code_slice = unsafe { std::slice::from_raw_parts(start_addr, code_size) };
let insns = cs.disasm_all(code_slice, start_addr as u64).unwrap(); let insns = cs.disasm_all(code_slice, start_addr as u64).unwrap();

View file

@ -36,7 +36,7 @@ pub struct Options {
pub dump_insns: bool, pub dump_insns: bool,
/// Dump all compiled instructions of target cbs. /// Dump all compiled instructions of target cbs.
pub dump_disasm: DumpDisasm, pub dump_disasm: Option<DumpDisasm>,
/// Print when specific ISEQ items are compiled or invalidated /// Print when specific ISEQ items are compiled or invalidated
pub dump_iseq_disasm: Option<String>, pub dump_iseq_disasm: Option<String>,
@ -62,26 +62,18 @@ pub static mut OPTIONS: Options = Options {
gen_stats: false, gen_stats: false,
gen_trace_exits: false, gen_trace_exits: false,
dump_insns: false, dump_insns: false,
dump_disasm: DumpDisasm::None, dump_disasm: None,
verify_ctx: false, verify_ctx: false,
global_constant_state: false, global_constant_state: false,
dump_iseq_disasm: None, dump_iseq_disasm: None,
}; };
#[derive(Copy, Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
pub enum DumpDisasm { pub enum DumpDisasm {
// Dump only inline cb // Dump to stdout
Inline, Stdout,
// Dump both inline and outlined cbs // Dump to "yjit_{pid}.log" file under the specified directory
All, File(String),
// Dont dump anything
None,
}
impl DumpDisasm {
pub fn is_enabled(&self) -> bool {
*self != DumpDisasm::None
}
} }
/// Macro to get an option value by name /// Macro to get an option value by name
@ -168,9 +160,13 @@ pub fn parse_option(str_ptr: *const std::os::raw::c_char) -> Option<()> {
}, },
("dump-disasm", _) => match opt_val.to_string().as_str() { ("dump-disasm", _) => match opt_val.to_string().as_str() {
"all" => unsafe { OPTIONS.dump_disasm = DumpDisasm::All }, "" => unsafe { OPTIONS.dump_disasm = Some(DumpDisasm::Stdout) },
"" => unsafe { OPTIONS.dump_disasm = DumpDisasm::Inline }, directory => {
_ => return None, let pid = std::process::id();
let path = format!("{directory}/yjit_{pid}.log");
println!("YJIT disasm dump: {path}");
unsafe { OPTIONS.dump_disasm = Some(DumpDisasm::File(path)) }
}
}, },
("dump-iseq-disasm", _) => unsafe { ("dump-iseq-disasm", _) => unsafe {