Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load generated trampolines into jitdump when profiling #3344

Merged
merged 2 commits into from
Sep 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions crates/jit/src/instantiate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,13 +397,17 @@ impl CompiledModule {
}

/// Returns the per-signature trampolines for this module.
pub fn trampolines(&self) -> impl Iterator<Item = (SignatureIndex, VMTrampoline)> + '_ {
pub fn trampolines(&self) -> impl Iterator<Item = (SignatureIndex, VMTrampoline, usize)> + '_ {
let code = self.code();
self.trampolines.iter().map(move |info| {
(info.signature, unsafe {
let ptr = &code[info.start as usize];
std::mem::transmute::<*const u8, VMTrampoline>(ptr)
})
(
info.signature,
unsafe {
let ptr = &code[info.start as usize];
std::mem::transmute::<*const u8, VMTrampoline>(ptr)
},
info.length as usize,
)
})
}

Expand Down
8 changes: 6 additions & 2 deletions crates/jit/src/profiling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ pub use vtune::VTuneAgent;
/// Common interface for profiling tools.
pub trait ProfilingAgent: Send + Sync + 'static {
/// Notify the profiler of a new module loaded into memory
fn module_load(&self, module: &CompiledModule, dbg_image: Option<&[u8]>) -> ();
fn module_load(&self, module: &CompiledModule, dbg_image: Option<&[u8]>);
/// Notify the profiler that the object file provided contains
/// dynamically-generated trampolines which are now being loaded.
fn trampoline_load(&self, file: &object::File<'_>);
}

/// Default agent for unsupported profiling build.
Expand All @@ -54,7 +57,8 @@ impl Error for NullProfilerAgentError {
}

impl ProfilingAgent for NullProfilerAgent {
fn module_load(&self, _module: &CompiledModule, _dbg_image: Option<&[u8]>) -> () {}
fn module_load(&self, _module: &CompiledModule, _dbg_image: Option<&[u8]>) {}
fn trampoline_load(&self, _file: &object::File<'_>) {}
}

#[allow(dead_code)]
Expand Down
1 change: 1 addition & 0 deletions crates/jit/src/profiling/jitdump_disabled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ impl JitDumpAgent {

impl ProfilingAgent for JitDumpAgent {
fn module_load(&self, _module: &CompiledModule, _dbg_image: Option<&[u8]>) {}
fn trampoline_load(&self, _file: &object::File<'_>) {}
}
54 changes: 52 additions & 2 deletions crates/jit/src/profiling/jitdump_linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use std::ptr;
use std::sync::Mutex;
use std::{borrow, mem, process};
use target_lexicon::Architecture;
use wasmtime_environ::EntityRef;

use object::elf;

Expand Down Expand Up @@ -207,6 +208,9 @@ impl ProfilingAgent for JitDumpAgent {
fn module_load(&self, module: &CompiledModule, dbg_image: Option<&[u8]>) {
self.state.lock().unwrap().module_load(module, dbg_image);
}
fn trampoline_load(&self, file: &object::File<'_>) {
self.state.lock().unwrap().trampoline_load(file)
}
}

impl State {
Expand Down Expand Up @@ -292,7 +296,7 @@ impl State {
}

/// Sent when a method is compiled and loaded into memory by the VM.
pub fn module_load(&mut self, module: &CompiledModule, dbg_image: Option<&[u8]>) -> () {
pub fn module_load(&mut self, module: &CompiledModule, dbg_image: Option<&[u8]>) {
let pid = process::id();
let tid = pid; // ThreadId does appear to track underlying thread. Using PID.

Expand All @@ -311,6 +315,52 @@ impl State {
self.dump_code_load_record(&name, addr, len, timestamp, pid, tid);
}
}
for (idx, func, len) in module.trampolines() {
let (addr, len) = (func as usize as *const u8, len);
let timestamp = self.get_time_stamp();
let name = format!("wasm::trampoline[{}]", idx.index());
self.dump_code_load_record(&name, addr, len, timestamp, pid, tid);
}
}

fn trampoline_load(&mut self, image: &object::File<'_>) {
use object::{ObjectSection, ObjectSymbol, SectionKind, SymbolKind};
let pid = process::id();
let tid = pid;

let text_base = match image.sections().find(|s| s.kind() == SectionKind::Text) {
Some(section) => match section.data() {
Ok(data) => data.as_ptr() as usize,
Err(_) => return,
},
None => return,
};

for sym in image.symbols() {
if !sym.is_definition() {
continue;
}
if sym.kind() != SymbolKind::Text {
continue;
}
let address = sym.address();
let size = sym.size();
if address == 0 || size == 0 {
continue;
}
if let Ok(name) = sym.name() {
let addr = text_base + address as usize;
let timestamp = self.get_time_stamp();
self.dump_code_load_record(
&name,
addr as *const u8,
size as usize,
timestamp,
pid,
tid,
);
}
}
}

fn dump_code_load_record(
Expand All @@ -321,7 +371,7 @@ impl State {
timestamp: u64,
pid: u32,
tid: u32,
) -> () {
) {
let name_len = method_name.len() + 1;
let size_limit = mem::size_of::<CodeLoadRecord>();

Expand Down
1 change: 1 addition & 0 deletions crates/jit/src/profiling/vtune_disabled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ impl VTuneAgent {

impl ProfilingAgent for VTuneAgent {
fn module_load(&self, _module: &crate::CompiledModule, _dbg_image: Option<&[u8]>) {}
fn trampoline_load(&self, _file: &object::File<'_>) {}
}
3 changes: 3 additions & 0 deletions crates/jit/src/profiling/vtune_linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ impl ProfilingAgent for VTuneAgent {
fn module_load(&self, module: &CompiledModule, dbg_image: Option<&[u8]>) {
self.state.lock().unwrap().module_load(module, dbg_image);
}
fn trampoline_load(&self, _file: &object::File<'_>) {
// TODO: needs an implementation
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heads up @jlb6740, since you're the original author of the VTune support: generated trampolines for calling into Wasm weren't previously being registered for profilers (see the top-level PR description) and there are some updates needed for including them in the VTune support. See the jitdump support in this PR for an idea of the kind of thing needed. I don't know exactly what is needed for VTune.

}
}

impl State {
Expand Down
4 changes: 3 additions & 1 deletion crates/wasmtime/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,9 @@ impl Module {
let signatures = Arc::new(SignatureCollection::new_for_module(
engine.signatures(),
&types.wasm_signatures,
modules.iter().flat_map(|m| m.trampolines()),
modules
.iter()
.flat_map(|m| m.trampolines().map(|(idx, f, _)| (idx, f))),
));

let module = modules.remove(main_module);
Expand Down
1 change: 1 addition & 0 deletions crates/wasmtime/src/trampoline/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ where
// also take care of unwind table registration.
let mut code_memory = CodeMemory::new(obj);
let code = code_memory.publish()?;
engine.config().profiler.trampoline_load(&code.obj);

// Extract the host/wasm trampolines from the results of compilation since
// we know their start/length.
Expand Down