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:
parent
64c52c4282
commit
f11765aef0
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
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue