diff --git a/Cargo.lock b/Cargo.lock index 367d13e9a3..2d1dab80c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1485,10 +1485,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" [[package]] -name = "ittapi-rs" -version = "0.2.0" +name = "ittapi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "663fe0550070071ff59e981864a9cd3ee1c869ed0a088140d9ac4dc05ea6b1a1" +dependencies = [ + "anyhow", + "ittapi-sys", + "log", +] + +[[package]] +name = "ittapi-sys" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f712648a1ad72fbfb7adc2772c331e8d90f022f8cf30cbabefba2878dd3172b0" +checksum = "e21911b7183f38c71d75ab478a527f314e28db51027037ece2e5511ed9410703" dependencies = [ "cc", ] @@ -3571,7 +3582,7 @@ dependencies = [ "cfg-if", "cpp_demangle", "gimli", - "ittapi-rs", + "ittapi", "log", "object", "rustc-demangle", diff --git a/crates/jit/Cargo.toml b/crates/jit/Cargo.toml index 128789dc23..da683d794c 100644 --- a/crates/jit/Cargo.toml +++ b/crates/jit/Cargo.toml @@ -22,7 +22,7 @@ gimli = { version = "0.26.0", default-features = false, features = ["std", "read object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "elf"] } serde = { version = "1.0.94", features = ["derive"] } addr2line = { version = "0.17.0", default-features = false } -ittapi-rs = { version = "0.2.0", optional = true } +ittapi = { version = "0.3.0", optional = true } bincode = "1.2.1" rustc-demangle = "0.1.16" cpp_demangle = "0.3.2" @@ -39,7 +39,7 @@ rustix = { version = "0.35.6", features = ["process"] } [features] jitdump = ['wasmtime-jit-debug'] -vtune = ['ittapi-rs'] +vtune = ['ittapi'] [badges] maintenance = { status = "actively-developed" } diff --git a/crates/jit/src/profiling.rs b/crates/jit/src/profiling.rs index b9741fa36f..a20db14614 100644 --- a/crates/jit/src/profiling.rs +++ b/crates/jit/src/profiling.rs @@ -12,7 +12,9 @@ cfg_if::cfg_if! { } cfg_if::cfg_if! { - if #[cfg(all(feature = "vtune", target_arch = "x86_64"))] { + // Note: VTune support is disabled on windows mingw because the ittapi crate doesn't compile + // there; see also https://github.com/bytecodealliance/wasmtime/pull/4003 for rationale. + if #[cfg(all(feature = "vtune", target_arch = "x86_64", not(all(target_os = "windows", target_env = "gnu"))))] { #[path = "profiling/vtune.rs"] mod vtune; } else { diff --git a/crates/jit/src/profiling/vtune.rs b/crates/jit/src/profiling/vtune.rs index 2e6f0eebf6..3e6b6415a5 100644 --- a/crates/jit/src/profiling/vtune.rs +++ b/crates/jit/src/profiling/vtune.rs @@ -14,28 +14,30 @@ use crate::{CompiledModule, ProfilingAgent}; use anyhow::Result; -use core::ptr; -use ittapi_rs::*; -use std::ffi::CString; +use ittapi::jit::MethodLoadBuilder; use std::sync::{atomic, Mutex}; use wasmtime_environ::EntityRef; /// Interface for driving the ittapi for VTune support pub struct VTuneAgent { - // Note that we use a mutex internally to serialize state updates - // since multiple threads may be sharing this agent. + // Note that we use a mutex internally to serialize state updates since multiple threads may be + // sharing this agent. state: Mutex, } /// Interface for driving vtune -#[derive(Clone, Debug, Default)] -struct State; +#[derive(Default)] +struct State { + vtune: ittapi::jit::Jit, +} impl VTuneAgent { /// Initialize a VTuneAgent. pub fn new() -> Result { Ok(VTuneAgent { - state: Mutex::new(State), + state: Mutex::new(State { + vtune: Default::default(), + }), }) } } @@ -47,56 +49,21 @@ impl Drop for VTuneAgent { } impl State { - /// Return a method ID for use with the ittapi. - fn get_method_id(&self) -> u32 { - unsafe { iJIT_GetNewMethodID() } - } - /// Notify vtune about a newly tracked code region. - fn event_load( - &mut self, - method_id: u32, - module_name: &str, - method_name: &str, - addr: *const u8, - len: usize, - ) -> () { - let mut jmethod = _iJIT_Method_Load { - method_id, - method_name: CString::new(method_name) - .expect("CString::new failed") - .into_raw(), - method_load_address: addr as *mut ::std::os::raw::c_void, - method_size: len as u32, - line_number_size: 0, - line_number_table: ptr::null_mut(), - class_id: 0, - class_file_name: CString::new(module_name) - .expect("CString::new failed") - .into_raw(), - source_file_name: CString::new("") - .expect("CString::new failed") - .into_raw(), - }; - let jmethod_ptr = &mut jmethod as *mut _ as *mut _; - unsafe { - log::trace!( - "NotifyEvent: method load (single method with id {})", - method_id - ); - let _ret = iJIT_NotifyEvent( - iJIT_jvm_event_iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, - jmethod_ptr as *mut ::std::os::raw::c_void, - ); - } + 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("".to_owned()), + ) + .unwrap(); } /// Shutdown module - fn event_shutdown(&mut self) -> () { - unsafe { - log::trace!("NotifyEvent shutdown (whole module)"); - let _ret = iJIT_NotifyEvent(iJIT_jvm_event_iJVM_EVENT_TYPE_SHUTDOWN, ptr::null_mut()); - } + fn event_shutdown(&mut self) { + // Ignore if something went wrong. + let _ = self.vtune.shutdown(); } } @@ -113,7 +80,7 @@ impl ProfilingAgent for VTuneAgent { } impl State { - fn module_load(&mut self, module: &CompiledModule, _dbg_image: Option<&[u8]>) -> () { + fn module_load(&mut self, module: &CompiledModule, _dbg_image: Option<&[u8]>) { // Global counter for module ids. static MODULE_ID: atomic::AtomicUsize = atomic::AtomicUsize::new(0); let global_module_id = MODULE_ID.fetch_add(1, atomic::Ordering::SeqCst); @@ -128,15 +95,13 @@ impl State { for (idx, func) in module.finished_functions() { let (addr, len) = unsafe { ((*func).as_ptr().cast::(), (*func).len()) }; let method_name = super::debug_name(module, idx); - let method_id = self.get_method_id(); log::trace!( - "new function ({}) {:?}::{:?} @ {:?}\n", - method_id, + "new function {:?}::{:?} @ {:?}\n", module_name, method_name, addr ); - self.event_load(method_id, &module_name, &method_name, addr, len); + self.notify_code(&module_name, &method_name, addr, len); } // Note: these are the trampolines into exported functions. @@ -144,14 +109,12 @@ impl State { let idx = idx.index(); let (addr, len) = (func as usize as *const u8, len); let method_name = format!("wasm::trampoline[{}]", idx,); - let method_id = self.get_method_id(); log::trace!( - "new trampoline ({}) for exported signature {} @ {:?}\n", - method_id, + "new trampoline for exported signature {} @ {:?}\n", idx, addr ); - self.event_load(method_id, &module_name, &method_name, addr, len); + self.notify_code(&module_name, &method_name, addr, len); } } @@ -163,7 +126,6 @@ impl State { _pid: u32, _tid: u32, ) { - let method_id = self.get_method_id(); - self.event_load(method_id, "wasm trampoline for Func::new", name, addr, size); + self.notify_code("wasm trampoline for Func::new", name, addr, size); } }