use crate::{CompiledModule, ProfilingAgent};
use anyhow::Result;
use ittapi::jit::MethodLoadBuilder;
use std::sync::{atomic, Mutex};
use wasmtime_environ::EntityRef;
pub struct VTuneAgent {
state: Mutex<State>,
}
#[derive(Default)]
struct State {
vtune: ittapi::jit::Jit,
}
impl VTuneAgent {
pub fn new() -> Result<Self> {
Ok(VTuneAgent {
state: Mutex::new(State {
vtune: Default::default(),
}),
})
}
}
impl Drop for VTuneAgent {
fn drop(&mut self) {
self.state.lock().unwrap().event_shutdown();
}
}
impl State {
fn notify_code(&mut self, module_name: &str, method_name: &str, addr: *const u8, len: usize) {
self.vtune
.load_method(
MethodLoadBuilder::new(method_name.to_owned(), addr, len)
.class_file_name(module_name.to_owned())
.source_file_name("<unknown wasm filename>".to_owned()),
)
.unwrap();
}
fn event_shutdown(&mut self) {
let _ = self.vtune.shutdown();
}
}
impl ProfilingAgent for VTuneAgent {
fn module_load(&self, module: &CompiledModule, dbg_image: Option<&[u8]>) {
self.state.lock().unwrap().module_load(module, dbg_image);
}
fn load_single_trampoline(&self, name: &str, addr: *const u8, size: usize, pid: u32, tid: u32) {
self.state
.lock()
.unwrap()
.load_single_trampoline(name, addr, size, pid, tid);
}
}
impl State {
fn module_load(&mut self, module: &CompiledModule, _dbg_image: Option<&[u8]>) {
static MODULE_ID: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
let global_module_id = MODULE_ID.fetch_add(1, atomic::Ordering::SeqCst);
let module_name = module
.module()
.name
.as_ref()
.cloned()
.unwrap_or_else(|| format!("wasm_module_{}", global_module_id));
for (idx, func) in module.finished_functions() {
let addr = func.as_ptr();
let len = func.len();
let method_name = super::debug_name(module, idx);
log::trace!(
"new function {:?}::{:?} @ {:?}\n",
module_name,
method_name,
addr
);
self.notify_code(&module_name, &method_name, addr, len);
}
for (idx, func, len) in module.trampolines() {
let idx = idx.index();
let (addr, len) = (func as usize as *const u8, len);
let method_name = format!("wasm::trampoline[{}]", idx,);
log::trace!(
"new trampoline for exported signature {} @ {:?}\n",
idx,
addr
);
self.notify_code(&module_name, &method_name, addr, len);
}
}
fn load_single_trampoline(
&mut self,
name: &str,
addr: *const u8,
size: usize,
_pid: u32,
_tid: u32,
) {
self.notify_code("wasm trampoline for Func::new", name, addr, size);
}
}