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);
#[cfg(feature = "disasm")]
if get_option!(dump_disasm) == DumpDisasm::All || (get_option!(dump_disasm) == DumpDisasm::Inline && cb.inline()) {
use crate::disasm::disasm_addr_range;
let last_ptr = cb.get_write_ptr();
let disasm = disasm_addr_range(cb, start_addr, last_ptr.raw_ptr() as usize - start_addr as usize);
if disasm.len() > 0 {
println!("{disasm}");
}
if let Some(dump_disasm) = get_option_ref!(dump_disasm) {
use crate::disasm::dump_disasm_addr_range;
let end_addr = cb.get_write_ptr().raw_ptr();
dump_disasm_addr_range(cb, start_addr, end_addr, dump_disasm)
}
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 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)));
} else {
asm.comment("YJIT entry");
@ -742,7 +742,7 @@ pub fn gen_single_block(
let mut asm = Assembler::new();
#[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));
}

View file

@ -2,6 +2,7 @@ use crate::core::*;
use crate::cruby::*;
use crate::yjit::yjit_enabled_p;
use crate::asm::CodeBlock;
use crate::options::DumpDisasm;
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();
// 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 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;
}
#[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")]
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("");
// 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();
// 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 insns = cs.disasm_all(code_slice, start_addr as u64).unwrap();

View file

@ -36,7 +36,7 @@ pub struct Options {
pub dump_insns: bool,
/// 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
pub dump_iseq_disasm: Option<String>,
@ -62,26 +62,18 @@ pub static mut OPTIONS: Options = Options {
gen_stats: false,
gen_trace_exits: false,
dump_insns: false,
dump_disasm: DumpDisasm::None,
dump_disasm: None,
verify_ctx: false,
global_constant_state: false,
dump_iseq_disasm: None,
};
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum DumpDisasm {
// Dump only inline cb
Inline,
// Dump both inline and outlined cbs
All,
// Dont dump anything
None,
}
impl DumpDisasm {
pub fn is_enabled(&self) -> bool {
*self != DumpDisasm::None
}
// Dump to stdout
Stdout,
// Dump to "yjit_{pid}.log" file under the specified directory
File(String),
}
/// 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() {
"all" => unsafe { OPTIONS.dump_disasm = DumpDisasm::All },
"" => unsafe { OPTIONS.dump_disasm = DumpDisasm::Inline },
_ => return None,
"" => unsafe { OPTIONS.dump_disasm = Some(DumpDisasm::Stdout) },
directory => {
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 {