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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Takashi Kokubun
						Takashi Kokubun