[前][次][番号順一覧][スレッド一覧]

ruby-changes:74064

From: Takashi <ko1@a...>
Date: Tue, 18 Oct 2022 02:47:38 +0900 (JST)
Subject: [ruby-changes:74064] f11765aef0 (master): YJIT: Allow --yjit-dump-disasm to dump into a file (#6552)

https://git.ruby-lang.org/ruby.git/commit/?id=f11765aef0

From f11765aef0cafb6fadf98216c94507f2390a0a70 Mon Sep 17 00:00:00 2001
From: Takashi Kokubun <takashikkbn@g...>
Date: Mon, 17 Oct 2022 10:47:22 -0700
Subject: 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
---
 yjit/src/backend/ir.rs | 11 ++++-------
 yjit/src/codegen.rs    |  4 ++--
 yjit/src/disasm.rs     | 22 ++++++++++++++++++++--
 yjit/src/options.rs    | 32 ++++++++++++++------------------
 4 files changed, 40 insertions(+), 29 deletions(-)

diff --git a/yjit/src/backend/ir.rs b/yjit/src/backend/ir.rs
index e11235aec9..df0600b2ff 100644
--- a/yjit/src/backend/ir.rs
+++ b/yjit/src/backend/ir.rs
@@ -1100,13 +1100,10 @@ impl Assembler https://github.com/ruby/ruby/blob/trunk/yjit/src/backend/ir.rs#L1100
         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
     }
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index 626916b240..ae01149081 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -612,7 +612,7 @@ pub fn gen_entry_prologue(cb: &mut CodeBlock, iseq: IseqPtr, insn_idx: u32) -> O https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L612
     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( https://github.com/ruby/ruby/blob/trunk/yjit/src/codegen.rs#L742
     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));
     }
 
diff --git a/yjit/src/disasm.rs b/yjit/src/disasm.rs
index 9e45dffd60..21ab6b5507 100644
--- a/yjit/src/disasm.rs
+++ b/yjit/src/disasm.rs
@@ -2,6 +2,7 @@ use crate::core::*; https://github.com/ruby/ruby/blob/trunk/yjit/src/disasm.rs#L2
 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 https://github.com/ruby/ruby/blob/trunk/yjit/src/disasm.rs#L96
             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 https://github.com/ruby/ruby/blob/trunk/yjit/src/disasm.rs#L116
     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 https://github.com/ruby/ruby/blob/trunk/yjit/src/disasm.rs#L158
     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();
 
diff --git a/yjit/src/options.rs b/yjit/src/options.rs
index d2b43ecb26..303ae4980f 100644
--- a/yjit/src/options.rs
+++ b/yjit/src/options.rs
@@ -36,7 +36,7 @@ pub struct Options { https://github.com/ruby/ruby/blob/trunk/yjit/src/options.rs#L36
     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 { https://github.com/ruby/ruby/blob/trunk/yjit/src/options.rs#L62
     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<()> { https://github.com/ruby/ruby/blob/trunk/yjit/src/options.rs#L160
         },
 
         ("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 {
-- 
cgit v1.2.3


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]