diff --git a/Cargo.lock b/Cargo.lock index 31c9b56548..e5f4ba09f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2083,7 +2083,6 @@ dependencies = [ "cc", "cfg-if", "indexmap", - "lazy_static", "libc", "memoffset", "more-asserts", diff --git a/crates/api/src/frame_info.rs b/crates/api/src/frame_info.rs new file mode 100644 index 0000000000..45b050e7ca --- /dev/null +++ b/crates/api/src/frame_info.rs @@ -0,0 +1,183 @@ +use crate::module::Names; +use std::collections::BTreeMap; +use std::sync::{Arc, RwLock}; +use wasmtime_environ::entity::EntityRef; +use wasmtime_environ::wasm::FuncIndex; +use wasmtime_jit::CompiledModule; + +lazy_static::lazy_static! { + /// This is a global cache of backtrace frame information for all active + /// + /// This global cache is used during `Trap` creation to symbolicate frames. + /// This is populated on module compilation, and it is cleared out whenever + /// all references to a module are dropped. + pub static ref FRAME_INFO: GlobalFrameInfo = GlobalFrameInfo::default(); +} + +#[derive(Default)] +pub struct GlobalFrameInfo { + /// An internal map that keeps track of backtrace frame information for + /// each module. + /// + /// This map is morally a map of ranges to a map of information for that + /// module. Each module is expected to reside in a disjoint section of + /// contiguous memory. No modules can overlap. + /// + /// The key of this map is the highest address in the module and the value + /// is the module's information, which also contains the start address. + ranges: RwLock>, +} + +/// An RAII structure used to unregister a module's frame information when the +/// module is destroyed. +pub struct GlobalFrameInfoRegistration { + /// The key that will be removed from the global `ranges` map when this is + /// dropped. + key: usize, +} + +struct ModuleFrameInfo { + start: usize, + functions: BTreeMap, + names: Arc, +} + +impl GlobalFrameInfo { + /// Registers a new compiled module's frame information. + /// + /// This function will register the `names` information for all of the + /// compiled functions within `module`. If the `module` has no functions + /// then `None` will be returned. Otherwise the returned object, when + /// dropped, will be used to unregister all name information from this map. + pub fn register( + &self, + names: &Arc, + module: &CompiledModule, + ) -> Option { + let mut min = usize::max_value(); + let mut max = 0; + let mut functions = BTreeMap::new(); + for (i, allocated) in module.finished_functions() { + let (start, end) = unsafe { + let ptr = (**allocated).as_ptr(); + let len = (**allocated).len(); + (ptr as usize, ptr as usize + len) + }; + if start < min { + min = start; + } + if end > max { + max = end; + } + let func_index = module.module().func_index(i); + assert!(functions.insert(end, (start, func_index)).is_none()); + } + if functions.len() == 0 { + return None; + } + + let mut ranges = self.ranges.write().unwrap(); + // First up assert that our chunk of jit functions doesn't collide with + // any other known chunks of jit functions... + if let Some((_, prev)) = ranges.range(max..).next() { + assert!(prev.start > max); + } + if let Some((prev_end, _)) = ranges.range(..=min).next_back() { + assert!(*prev_end < min); + } + + // ... then insert our range and assert nothing was there previously + let prev = ranges.insert( + max, + ModuleFrameInfo { + start: min, + functions, + names: names.clone(), + }, + ); + assert!(prev.is_none()); + Some(GlobalFrameInfoRegistration { key: max }) + } + + /// Fetches information about a program counter in a backtrace. + /// + /// Returns an object if this `pc` is known to some previously registered + /// module, or returns `None` if no information can be found. + pub fn lookup(&self, pc: usize) -> Option { + let ranges = self.ranges.read().ok()?; + let (end, info) = ranges.range(pc..).next()?; + if pc < info.start || *end < pc { + return None; + } + let (end, (start, func_index)) = info.functions.range(pc..).next()?; + if pc < *start || *end < pc { + return None; + } + Some(FrameInfo { + module_name: info.names.module_name.clone(), + func_index: func_index.index() as u32, + func_name: info.names.module.func_names.get(func_index).cloned(), + }) + } +} + +impl Drop for GlobalFrameInfoRegistration { + fn drop(&mut self) { + if let Ok(mut map) = FRAME_INFO.ranges.write() { + map.remove(&self.key); + } + } +} + +/// Description of a frame in a backtrace for a [`Trap`]. +/// +/// Whenever a WebAssembly trap occurs an instance of [`Trap`] is created. Each +/// [`Trap`] has a backtrace of the WebAssembly frames that led to the trap, and +/// each frame is described by this structure. +#[derive(Debug)] +pub struct FrameInfo { + module_name: Option, + func_index: u32, + func_name: Option, +} + +impl FrameInfo { + /// Returns the WebAssembly function index for this frame. + /// + /// This function index is the index in the function index space of the + /// WebAssembly module that this frame comes from. + pub fn func_index(&self) -> u32 { + self.func_index + } + + /// Returns the identifer of the module that this frame is for. + /// + /// Module identifiers are present in the `name` section of a WebAssembly + /// binary, but this may not return the exact item in the `name` section. + /// Module names can be overwritten at construction time or perhaps inferred + /// from file names. The primary purpose of this function is to assist in + /// debugging and therefore may be tweaked over time. + /// + /// This function returns `None` when no name can be found or inferred. + pub fn module_name(&self) -> Option<&str> { + self.module_name.as_deref() + } + + /// Returns a descriptive name of the function for this frame, if one is + /// available. + /// + /// The name of this function may come from the `name` section of the + /// WebAssembly binary, or wasmtime may try to infer a better name for it if + /// not available, for example the name of the export if it's exported. + /// + /// This return value is primarily used for debugging and human-readable + /// purposes for things like traps. Note that the exact return value may be + /// tweaked over time here and isn't guaranteed to be something in + /// particular about a wasm module due to its primary purpose of assisting + /// in debugging. + /// + /// This function returns `None` when no name could be inferred. + pub fn func_name(&self) -> Option<&str> { + self.func_name.as_deref() + } +} diff --git a/crates/api/src/func.rs b/crates/api/src/func.rs index 41e1687284..187f379edd 100644 --- a/crates/api/src/func.rs +++ b/crates/api/src/func.rs @@ -73,7 +73,10 @@ macro_rules! wrappers { unsafe { let (instance, export) = crate::trampoline::generate_raw_func_export( &ty, - shim:: as *const _, + std::slice::from_raw_parts_mut( + shim:: as *mut _, + 0, + ), store, Box::new(func), ) diff --git a/crates/api/src/instance.rs b/crates/api/src/instance.rs index 309d9bb0ac..1a44b656b2 100644 --- a/crates/api/src/instance.rs +++ b/crates/api/src/instance.rs @@ -120,7 +120,7 @@ impl Instance { } exports.into_boxed_slice() }; - module.register_names(); + module.register_frame_info(); Ok(Instance { instance_handle, module: module.clone(), diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index d68d5802cc..911bc18dd4 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -10,6 +10,7 @@ mod callable; mod externals; +mod frame_info; mod func; mod instance; mod module; @@ -22,12 +23,13 @@ mod values; pub use crate::callable::Callable; pub use crate::externals::*; +pub use crate::frame_info::FrameInfo; pub use crate::func::{Func, WasmArg, WasmRet}; pub use crate::instance::Instance; pub use crate::module::Module; pub use crate::r#ref::{AnyRef, HostInfo, HostRef}; pub use crate::runtime::{Config, Engine, OptLevel, Store, Strategy}; -pub use crate::trap::{FrameInfo, Trap}; +pub use crate::trap::Trap; pub use crate::types::*; pub use crate::values::*; diff --git a/crates/api/src/module.rs b/crates/api/src/module.rs index 4c6ffa77e4..7719600907 100644 --- a/crates/api/src/module.rs +++ b/crates/api/src/module.rs @@ -1,15 +1,12 @@ +use crate::frame_info::{GlobalFrameInfoRegistration, FRAME_INFO}; use crate::runtime::Store; use crate::types::{ ExportType, ExternType, FuncType, GlobalType, ImportType, Limits, MemoryType, Mutability, TableType, ValType, }; use anyhow::{bail, Error, Result}; -use lazy_static::lazy_static; -use std::cell::Cell; -use std::collections::HashMap; use std::path::Path; -use std::rc::Rc; -use std::sync::{Arc, RwLock}; +use std::sync::{Arc, Mutex}; use wasmparser::{ validate, CustomSectionKind, ExternalKind, ImportSectionEntryType, ModuleReader, Name, OperatorValidatorConfig, SectionCode, ValidatingParserConfig, @@ -83,8 +80,7 @@ fn into_table_type(tt: wasmparser::TableType) -> TableType { /// In other words it's a shallow copy, not a deep copy. #[derive(Clone)] pub struct Module { - // FIXME(#777) should be `Arc` and this type should be thread-safe - inner: Rc, + inner: Arc, } struct ModuleInner { @@ -92,7 +88,7 @@ struct ModuleInner { imports: Box<[ImportType]>, exports: Box<[ExportType]>, compiled: CompiledModule, - registered_names: Cell, + frame_info_registration: Mutex>>, names: Arc, } @@ -101,17 +97,6 @@ pub struct Names { pub module_name: Option, } -lazy_static! { - /// This is a global cache of names known for all compiled modules in this - /// process. - /// - /// This global cache is used during `Trap` creation to symbolicate frames. - /// This is populated on module compilation, and it is cleared out whenever - /// all references to a module are dropped, aka the `Drop for ModuleInner` - /// below. - pub static ref NAMES: RwLock>> = RwLock::default(); -} - impl Module { /// Creates a new WebAssembly `Module` from the given in-memory `bytes`. /// @@ -170,7 +155,7 @@ impl Module { /// See [`Module::new`] for other details. pub fn new_with_name(store: &Store, bytes: impl AsRef<[u8]>, name: &str) -> Result { let mut module = Module::new(store, bytes.as_ref())?; - let inner = Rc::get_mut(&mut module.inner).unwrap(); + let inner = Arc::get_mut(&mut module.inner).unwrap(); Arc::get_mut(&mut inner.names).unwrap().module_name = Some(name.to_string()); Ok(module) } @@ -199,9 +184,9 @@ impl Module { /// used instead. pub fn from_binary(store: &Store, binary: &[u8]) -> Result { Module::validate(store, binary)?; - // Note that the call to `validate` here should be ok because we - // previously validated the binary, meaning we're guaranteed to pass a - // valid binary for `store`. + // Note that the call to `from_binary_unchecked` here should be ok + // because we previously validated the binary, meaning we're guaranteed + // to pass a valid binary for `store`. unsafe { Module::from_binary_unchecked(store, binary) } } @@ -284,13 +269,13 @@ impl Module { module: compiled.module().clone(), }); Ok(Module { - inner: Rc::new(ModuleInner { + inner: Arc::new(ModuleInner { store: store.clone(), imports: Box::new([]), exports: Box::new([]), names, compiled, - registered_names: Cell::new(false), + frame_info_registration: Mutex::new(None), }), }) } @@ -323,7 +308,7 @@ impl Module { } fn read_imports_and_exports(&mut self, binary: &[u8]) -> Result<()> { - let inner = Rc::get_mut(&mut self.inner).unwrap(); + let inner = Arc::get_mut(&mut self.inner).unwrap(); let mut reader = ModuleReader::new(binary)?; let mut imports = Vec::new(); let mut exports = Vec::new(); @@ -452,23 +437,14 @@ impl Module { Ok(()) } - /// Register this module's names in the global map of module names. + /// Register this module's stack frame information into the global scope. /// /// This is required to ensure that any traps can be properly symbolicated. - pub(crate) fn register_names(&self) { - if self.inner.registered_names.get() { + pub(crate) fn register_frame_info(&self) { + let mut info = self.inner.frame_info_registration.lock().unwrap(); + if info.is_some() { return; } - let names = self.inner.names.clone(); - NAMES.write().unwrap().insert(names.module.id, names); - self.inner.registered_names.set(true); - } -} - -impl Drop for ModuleInner { - fn drop(&mut self) { - if self.registered_names.get() { - NAMES.write().unwrap().remove(&self.names.module.id); - } + *info = Some(FRAME_INFO.register(&self.inner.names, &self.inner.compiled)); } } diff --git a/crates/api/src/trampoline/create_handle.rs b/crates/api/src/trampoline/create_handle.rs index 679f9ef45c..86bca33876 100644 --- a/crates/api/src/trampoline/create_handle.rs +++ b/crates/api/src/trampoline/create_handle.rs @@ -13,7 +13,7 @@ use wasmtime_runtime::{Imports, InstanceHandle, VMFunctionBody}; pub(crate) fn create_handle( module: Module, store: &Store, - finished_functions: PrimaryMap, + finished_functions: PrimaryMap, state: Box, ) -> Result { let imports = Imports::new( diff --git a/crates/api/src/trampoline/func.rs b/crates/api/src/trampoline/func.rs index bced16addb..5076a2f9b2 100644 --- a/crates/api/src/trampoline/func.rs +++ b/crates/api/src/trampoline/func.rs @@ -121,7 +121,7 @@ fn make_trampoline( fn_builder_ctx: &mut FunctionBuilderContext, call_id: u32, signature: &ir::Signature, -) -> *const VMFunctionBody { +) -> *mut [VMFunctionBody] { // Mostly reverse copy of the similar method from wasmtime's // wasmtime-jit/src/compiler.rs. let pointer_type = isa.pointer_type(); @@ -241,7 +241,6 @@ fn make_trampoline( unwind_info, }) .expect("allocate_for_function") - .as_ptr() } pub fn create_handle_with_function( @@ -263,7 +262,7 @@ pub fn create_handle_with_function( let mut fn_builder_ctx = FunctionBuilderContext::new(); let mut module = Module::new(); - let mut finished_functions: PrimaryMap = + let mut finished_functions: PrimaryMap = PrimaryMap::new(); let mut code_memory = CodeMemory::new(); @@ -295,7 +294,7 @@ pub fn create_handle_with_function( pub unsafe fn create_handle_with_raw_function( ft: &FuncType, - func: *const VMFunctionBody, + func: *mut [VMFunctionBody], store: &Store, state: Box, ) -> Result { @@ -312,8 +311,7 @@ pub unsafe fn create_handle_with_raw_function( }; let mut module = Module::new(); - let mut finished_functions: PrimaryMap = - PrimaryMap::new(); + let mut finished_functions = PrimaryMap::new(); let sig_id = module.signatures.push(sig.clone()); let func_id = module.functions.push(sig_id); diff --git a/crates/api/src/trampoline/mod.rs b/crates/api/src/trampoline/mod.rs index 9e7754a95c..d65906ae12 100644 --- a/crates/api/src/trampoline/mod.rs +++ b/crates/api/src/trampoline/mod.rs @@ -33,7 +33,7 @@ pub fn generate_func_export( /// instance/export/etc may exhibit undefined behavior. pub unsafe fn generate_raw_func_export( ft: &FuncType, - func: *const VMFunctionBody, + func: *mut [VMFunctionBody], store: &Store, state: Box, ) -> Result<(wasmtime_runtime::InstanceHandle, wasmtime_runtime::Export)> { diff --git a/crates/api/src/trap.rs b/crates/api/src/trap.rs index 019939fab3..8b5d6f7b98 100644 --- a/crates/api/src/trap.rs +++ b/crates/api/src/trap.rs @@ -1,8 +1,8 @@ -use crate::module::NAMES; +use crate::frame_info::FRAME_INFO; +use crate::FrameInfo; use backtrace::Backtrace; use std::fmt; use std::sync::Arc; -use wasmtime_environ::entity::EntityRef; /// A struct representing an aborted instruction execution, with a message /// indicating the cause. @@ -55,22 +55,11 @@ impl Trap { fn new_with_trace(message: String, native_trace: Backtrace) -> Self { let mut wasm_trace = Vec::new(); - let names = NAMES.read().unwrap(); for frame in native_trace.frames() { let pc = frame.ip() as usize; - let info = match wasmtime_runtime::jit_function_registry::find(pc) { - Some(info) => info, - None => continue, - }; - let names = match names.get(&info.module_id) { - Some(names) => names, - None => continue, - }; - wasm_trace.push(FrameInfo { - func_index: info.func_index.index() as u32, - module_name: names.module_name.clone(), - func_name: names.module.func_names.get(&info.func_index).cloned(), - }) + if let Some(info) = FRAME_INFO.lookup(pc) { + wasm_trace.push(info); + } } Trap { inner: Arc::new(TrapInner { @@ -119,7 +108,7 @@ impl fmt::Display for Trap { Ok(name) => write!(f, "{}", name)?, Err(_) => write!(f, "{}", name)?, }, - None => write!(f, "", frame.func_index)?, + None => write!(f, "", frame.func_index())?, } writeln!(f, "")?; } @@ -128,56 +117,3 @@ impl fmt::Display for Trap { } impl std::error::Error for Trap {} - -/// Description of a frame in a backtrace for a [`Trap`]. -/// -/// Whenever a WebAssembly trap occurs an instance of [`Trap`] is created. Each -/// [`Trap`] has a backtrace of the WebAssembly frames that led to the trap, and -/// each frame is described by this structure. -#[derive(Debug)] -pub struct FrameInfo { - module_name: Option, - func_index: u32, - func_name: Option, -} - -impl FrameInfo { - /// Returns the WebAssembly function index for this frame. - /// - /// This function index is the index in the function index space of the - /// WebAssembly module that this frame comes from. - pub fn func_index(&self) -> u32 { - self.func_index - } - - /// Returns the identifer of the module that this frame is for. - /// - /// Module identifiers are present in the `name` section of a WebAssembly - /// binary, but this may not return the exact item in the `name` section. - /// Module names can be overwritten at construction time or perhaps inferred - /// from file names. The primary purpose of this function is to assist in - /// debugging and therefore may be tweaked over time. - /// - /// This function returns `None` when no name can be found or inferred. - pub fn module_name(&self) -> Option<&str> { - self.module_name.as_deref() - } - - /// Returns a descriptive name of the function for this frame, if one is - /// available. - /// - /// The name of this function may come from the `name` section of the - /// WebAssembly binary, or wasmtime may try to infer a better name for it if - /// not available, for example the name of the export if it's exported. - /// - /// This return value is primarily used for debugging and human-readable - /// purposes for things like traps. Note that the exact return value may be - /// tweaked over time here and isn't guaranteed to be something in - /// particular about a wasm module due to its primary purpose of assisting - /// in debugging. - /// - /// This function returns `None` when no name could be inferred. - pub fn func_name(&self) -> Option<&str> { - self.func_name.as_deref() - } -} diff --git a/crates/jit/src/compiler.rs b/crates/jit/src/compiler.rs index 440093d84c..bc519d9f5d 100644 --- a/crates/jit/src/compiler.rs +++ b/crates/jit/src/compiler.rs @@ -21,8 +21,7 @@ use wasmtime_environ::{ Traps, Tunables, VMOffsets, }; use wasmtime_runtime::{ - jit_function_registry, InstantiationError, SignatureRegistry, TrapRegistration, TrapRegistry, - VMFunctionBody, + InstantiationError, SignatureRegistry, TrapRegistration, TrapRegistry, VMFunctionBody, }; /// Select which kind of compilation to use. @@ -51,7 +50,6 @@ pub struct Compiler { isa: Box, code_memory: CodeMemory, - jit_function_ranges: Vec<(usize, usize)>, trap_registry: TrapRegistry, trampoline_park: HashMap<*const VMFunctionBody, *const VMFunctionBody>, signatures: SignatureRegistry, @@ -72,7 +70,6 @@ impl Compiler { Self { isa, code_memory: CodeMemory::new(), - jit_function_ranges: Vec::new(), trampoline_park: HashMap::new(), signatures: SignatureRegistry::new(), fn_builder_ctx: FunctionBuilderContext::new(), @@ -83,14 +80,6 @@ impl Compiler { } } -impl Drop for Compiler { - fn drop(&mut self) { - for (start, end) in self.jit_function_ranges.iter() { - jit_function_registry::unregister(*start, *end); - } - } -} - impl Compiler { /// Return the target's frontend configuration settings. pub fn frontend_config(&self) -> TargetFrontendConfig { @@ -157,19 +146,6 @@ impl Compiler { let trap_registration = register_traps(&allocated_functions, &traps, &self.trap_registry); - for (i, allocated) in allocated_functions.iter() { - let ptr = (*allocated) as *const VMFunctionBody; - let body_len = compilation.get(i).body.len(); - self.jit_function_ranges - .push((ptr as usize, ptr as usize + body_len)); - let func_index = module.func_index(i); - let tag = jit_function_registry::JITFunctionTag { - module_id: module.id, - func_index, - }; - jit_function_registry::register(ptr as usize, ptr as usize + body_len, tag); - } - // Translate debug info (DWARF) only if at least one function is present. let dbg = if debug_data.is_some() && !allocated_functions.is_empty() { let target_config = self.isa.frontend_config(); diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs index 790e10276f..f6b33e41ff 100644 --- a/crates/jit/src/instantiate.rs +++ b/crates/jit/src/instantiate.rs @@ -48,7 +48,7 @@ pub enum SetupError { /// from the wasm buffer rather than holding its own copy. struct RawCompiledModule<'data> { module: Module, - finished_functions: BoxedSlice, + finished_functions: BoxedSlice, data_initializers: Box<[DataInitializer<'data>]>, signatures: BoxedSlice, dbg_jit_registration: Option, @@ -74,7 +74,7 @@ impl<'data> RawCompiledModule<'data> { None }; - let (allocated_functions, jt_offsets, relocations, dbg_image, trap_registration) = compiler + let (finished_functions, jt_offsets, relocations, dbg_image, trap_registration) = compiler .compile( &translation.module, translation.module_translation.as_ref().unwrap(), @@ -84,22 +84,11 @@ impl<'data> RawCompiledModule<'data> { link_module( &translation.module, - &allocated_functions, + &finished_functions, &jt_offsets, relocations, ); - // Gather up the pointers to the compiled functions. - let finished_functions: BoxedSlice = - allocated_functions - .into_iter() - .map(|(_index, allocated)| { - let fatptr: *const [VMFunctionBody] = *allocated; - fatptr as *const VMFunctionBody - }) - .collect::>() - .into_boxed_slice(); - // Compute indices into the shared signature table. let signatures = { let signature_registry = compiler.signatures(); @@ -125,7 +114,7 @@ impl<'data> RawCompiledModule<'data> { Ok(Self { module: translation.module, - finished_functions, + finished_functions: finished_functions.into_boxed_slice(), data_initializers: translation.data_initializers.into_boxed_slice(), signatures: signatures.into_boxed_slice(), dbg_jit_registration, @@ -137,7 +126,7 @@ impl<'data> RawCompiledModule<'data> { /// A compiled wasm module, ready to be instantiated. pub struct CompiledModule { module: Arc, - finished_functions: BoxedSlice, + finished_functions: BoxedSlice, data_initializers: Box<[OwnedDataInitializer]>, signatures: BoxedSlice, dbg_jit_registration: Option>, @@ -170,7 +159,7 @@ impl CompiledModule { /// Construct a `CompiledModule` from component parts. pub fn from_parts( module: Module, - finished_functions: BoxedSlice, + finished_functions: BoxedSlice, data_initializers: Box<[OwnedDataInitializer]>, signatures: BoxedSlice, dbg_jit_registration: Option, @@ -229,6 +218,11 @@ impl CompiledModule { pub fn module_ref(&self) -> &Module { &self.module } + + /// Returns the map of all finished JIT functions compiled for this module + pub fn finished_functions(&self) -> &BoxedSlice { + &self.finished_functions + } } /// Similar to `DataInitializer`, but owns its own copy of the data rather diff --git a/crates/runtime/Cargo.toml b/crates/runtime/Cargo.toml index d37f6cc9a5..6f8e8c8608 100644 --- a/crates/runtime/Cargo.toml +++ b/crates/runtime/Cargo.toml @@ -13,7 +13,6 @@ edition = "2018" [dependencies] wasmtime-environ = { path = "../environ", version = "0.9.0" } region = "2.0.0" -lazy_static = "1.2.0" libc = { version = "0.2.60", default-features = false } memoffset = "0.5.3" indexmap = "1.0.2" diff --git a/crates/runtime/src/instance.rs b/crates/runtime/src/instance.rs index be3cc45fb4..7bfc5fe605 100644 --- a/crates/runtime/src/instance.rs +++ b/crates/runtime/src/instance.rs @@ -90,7 +90,7 @@ pub(crate) struct Instance { tables: BoxedSlice, /// Pointers to functions in executable memory. - finished_functions: BoxedSlice, + finished_functions: BoxedSlice, /// Hosts can store arbitrary per-instance information here. host_state: Box, @@ -279,7 +279,10 @@ impl Instance { let signature = self.module.signatures[self.module.functions[*index]].clone(); let (address, vmctx) = if let Some(def_index) = self.module.defined_func_index(*index) { - (self.finished_functions[def_index], self.vmctx_ptr()) + ( + self.finished_functions[def_index] as *const _, + self.vmctx_ptr(), + ) } else { let import = self.imported_function(*index); (import.body, import.vmctx) @@ -353,7 +356,7 @@ impl Instance { .finished_functions .get(defined_index) .expect("function index is out of bounds"); - (body, self.vmctx_ptr()) + (body as *const _, self.vmctx_ptr()) } None => { assert_lt!(index.index(), self.module.imported_funcs.len()); @@ -540,7 +543,7 @@ impl InstanceHandle { pub unsafe fn new( module: Arc, trap_registration: TrapRegistration, - finished_functions: BoxedSlice, + finished_functions: BoxedSlice, imports: Imports, data_initializers: &[DataInitializer<'_>], vmshared_signatures: BoxedSlice, @@ -927,7 +930,7 @@ fn initialize_tables(instance: &Instance) -> Result<(), InstantiationError> { let callee_sig = instance.module.functions[*func_idx]; let (callee_ptr, callee_vmctx) = if let Some(index) = instance.module.defined_func_index(*func_idx) { - (instance.finished_functions[index], vmctx) + (instance.finished_functions[index] as *const _, vmctx) } else { let imported_func = instance.imported_function(*func_idx); (imported_func.body, imported_func.vmctx) diff --git a/crates/runtime/src/jit_function_registry.rs b/crates/runtime/src/jit_function_registry.rs deleted file mode 100644 index bb185c068c..0000000000 --- a/crates/runtime/src/jit_function_registry.rs +++ /dev/null @@ -1,73 +0,0 @@ -#![allow(missing_docs)] - -use lazy_static::lazy_static; -use std::collections::BTreeMap; -use std::sync::{Arc, RwLock}; -use wasmtime_environ::wasm::FuncIndex; - -lazy_static! { - static ref REGISTRY: RwLock = RwLock::new(JITFunctionRegistry::default()); -} - -#[derive(Clone)] -pub struct JITFunctionTag { - pub module_id: usize, - pub func_index: FuncIndex, -} - -struct JITFunctionRegistry { - ranges: BTreeMap)>, -} - -impl Default for JITFunctionRegistry { - fn default() -> Self { - Self { - ranges: Default::default(), - } - } -} - -impl JITFunctionRegistry { - fn register(&mut self, fn_start: usize, fn_end: usize, tag: JITFunctionTag) { - self.ranges.insert(fn_end, (fn_start, Arc::new(tag))); - } - - fn unregister(&mut self, fn_end: usize) { - self.ranges.remove(&fn_end); - } - - fn find(&self, pc: usize) -> Option<&Arc> { - self.ranges - .range(pc..) - .next() - .and_then(|(end, (start, s))| { - if *start <= pc && pc < *end { - Some(s) - } else { - None - } - }) - } -} - -pub fn register(fn_start: usize, fn_end: usize, tag: JITFunctionTag) { - REGISTRY - .write() - .expect("jit function registry lock got poisoned") - .register(fn_start, fn_end, tag); -} - -pub fn unregister(_fn_start: usize, fn_end: usize) { - REGISTRY - .write() - .expect("jit function registry lock got poisoned") - .unregister(fn_end); -} - -pub fn find(pc: usize) -> Option> { - REGISTRY - .read() - .expect("jit function registry lock got poisoned") - .find(pc) - .cloned() -} diff --git a/crates/runtime/src/lib.rs b/crates/runtime/src/lib.rs index 06f90152aa..188265a747 100644 --- a/crates/runtime/src/lib.rs +++ b/crates/runtime/src/lib.rs @@ -34,7 +34,6 @@ mod trap_registry; mod traphandlers; mod vmcontext; -pub mod jit_function_registry; pub mod libcalls; pub use crate::export::Export;