mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
ZJIT: Create perf map files for profilers (#13941)
This lets us ZJIT compiled functions show up in the profiles of, say, perf, or samply. Fix https://github.com/Shopify/ruby/issues/634
This commit is contained in:
parent
86320a5300
commit
30b1368829
2 changed files with 42 additions and 2 deletions
|
@ -154,6 +154,20 @@ fn gen_iseq_entry_point_body(cb: &mut CodeBlock, iseq: IseqPtr) -> *const u8 {
|
|||
start_ptr.map(|start_ptr| start_ptr.raw_ptr(cb)).unwrap_or(std::ptr::null())
|
||||
}
|
||||
|
||||
/// Write an entry to the perf map in /tmp
|
||||
fn register_with_perf(iseq_name: String, start_ptr: usize, code_size: usize) {
|
||||
use std::io::Write;
|
||||
let perf_map = format!("/tmp/perf-{}.map", std::process::id());
|
||||
let Ok(mut file) = std::fs::OpenOptions::new().create(true).append(true).open(&perf_map) else {
|
||||
debug!("Failed to open perf map file: {perf_map}");
|
||||
return;
|
||||
};
|
||||
let Ok(_) = writeln!(file, "{:#x} {:#x} zjit::{}", start_ptr, code_size, iseq_name) else {
|
||||
debug!("Failed to write {iseq_name} to perf map file: {perf_map}");
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
/// Compile a JIT entry
|
||||
fn gen_entry(cb: &mut CodeBlock, iseq: IseqPtr, function: &Function, function_ptr: CodePtr, c_stack_bytes: usize) -> Option<CodePtr> {
|
||||
// Set up registers for CFP, EC, SP, and basic block arguments
|
||||
|
@ -172,7 +186,17 @@ fn gen_entry(cb: &mut CodeBlock, iseq: IseqPtr, function: &Function, function_pt
|
|||
asm.frame_teardown();
|
||||
asm.cret(C_RET_OPND);
|
||||
|
||||
asm.compile(cb).map(|(start_ptr, _)| start_ptr)
|
||||
let result = asm.compile(cb).map(|(start_ptr, _)| start_ptr);
|
||||
if let Some(start_addr) = result {
|
||||
if get_option!(perf) {
|
||||
let start_ptr = start_addr.raw_ptr(cb) as usize;
|
||||
let end_ptr = cb.get_write_ptr().raw_ptr(cb) as usize;
|
||||
let code_size = end_ptr - start_ptr;
|
||||
let iseq_name = iseq_get_location(iseq, 0);
|
||||
register_with_perf(format!("entry for {iseq_name}"), start_ptr, code_size);
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Compile an ISEQ into machine code
|
||||
|
@ -255,7 +279,17 @@ fn gen_function(cb: &mut CodeBlock, iseq: IseqPtr, function: &Function) -> Optio
|
|||
}
|
||||
|
||||
// Generate code if everything can be compiled
|
||||
asm.compile(cb).map(|(start_ptr, gc_offsets)| (start_ptr, gc_offsets, jit))
|
||||
let result = asm.compile(cb).map(|(start_ptr, gc_offsets)| (start_ptr, gc_offsets, jit));
|
||||
if let Some((start_ptr, _, _)) = result {
|
||||
if get_option!(perf) {
|
||||
let start_usize = start_ptr.raw_ptr(cb) as usize;
|
||||
let end_usize = cb.get_write_ptr().raw_ptr(cb) as usize;
|
||||
let code_size = end_usize - start_usize;
|
||||
let iseq_name = iseq_get_location(iseq, 0);
|
||||
register_with_perf(iseq_name, start_usize, code_size);
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Compile an instruction
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue