Improve handling of strings for backtraces (#843)

* Improve handling of strings for backtraces

Largely avoid storing strings at all in the `wasmtime-*` internal
crates, and instead only store strings in a separate global cache
specific to the `wasmtime` crate itself. This global cache is inserted
and removed from dynamically as modules are created and deallocated, and
the global cache is consulted whenever a `Trap` is created to
symbolicate any wasm frames.

This also avoids the need to thread `module_name` through the jit crates
and back, and additionally removes the need for `ModuleSyncString`.

* Run rustfmt
This commit is contained in:
Alex Crichton
2020-01-24 11:53:55 -06:00
committed by GitHub
parent 21e0a99884
commit 3db1074c15
17 changed files with 139 additions and 156 deletions

1
Cargo.lock generated
View File

@@ -2032,6 +2032,7 @@ dependencies = [
"backtrace", "backtrace",
"cfg-if", "cfg-if",
"file-per-thread-logger", "file-per-thread-logger",
"lazy_static",
"libc", "libc",
"pretty_env_logger", "pretty_env_logger",
"rayon", "rayon",

View File

@@ -20,6 +20,7 @@ libc = "0.2"
cfg-if = "0.1.9" cfg-if = "0.1.9"
backtrace = "0.3.42" backtrace = "0.3.42"
rustc-demangle = "0.1.16" rustc-demangle = "0.1.16"
lazy_static = "1.4"
[target.'cfg(target_os = "windows")'.dependencies] [target.'cfg(target_os = "windows")'.dependencies]
winapi = "0.3.7" winapi = "0.3.7"

View File

@@ -108,8 +108,7 @@ impl Instance {
/// [issue]: https://github.com/bytecodealliance/wasmtime/issues/727 /// [issue]: https://github.com/bytecodealliance/wasmtime/issues/727
pub fn new(module: &Module, imports: &[Extern]) -> Result<Instance, Error> { pub fn new(module: &Module, imports: &[Extern]) -> Result<Instance, Error> {
let store = module.store(); let store = module.store();
let mut instance_handle = let mut instance_handle = instantiate(module.compiled_module(), imports)?;
instantiate(module.compiled_module().expect("compiled_module"), imports)?;
let exports = { let exports = {
let mut exports = Vec::with_capacity(module.exports().len()); let mut exports = Vec::with_capacity(module.exports().len());
@@ -124,6 +123,7 @@ impl Instance {
} }
exports.into_boxed_slice() exports.into_boxed_slice()
}; };
module.register_names();
Ok(Instance { Ok(Instance {
instance_handle, instance_handle,
module: module.clone(), module: module.clone(),

View File

@@ -4,7 +4,11 @@ use crate::types::{
TableType, ValType, TableType, ValType,
}; };
use anyhow::{Error, Result}; use anyhow::{Error, Result};
use lazy_static::lazy_static;
use std::cell::Cell;
use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
use std::sync::{Arc, RwLock};
use wasmparser::{ use wasmparser::{
validate, CustomSectionKind, ExternalKind, ImportSectionEntryType, ModuleReader, Name, validate, CustomSectionKind, ExternalKind, ImportSectionEntryType, ModuleReader, Name,
OperatorValidatorConfig, SectionCode, ValidatingParserConfig, OperatorValidatorConfig, SectionCode, ValidatingParserConfig,
@@ -81,8 +85,25 @@ struct ModuleInner {
store: Store, store: Store,
imports: Box<[ImportType]>, imports: Box<[ImportType]>,
exports: Box<[ExportType]>, exports: Box<[ExportType]>,
name: Option<String>, compiled: CompiledModule,
compiled: Option<CompiledModule>, registered_names: Cell<bool>,
names: Arc<Names>,
}
pub struct Names {
pub module: Arc<wasmtime_environ::Module>,
pub module_name: Option<String>,
}
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<HashMap<usize, Arc<Names>>> = RwLock::default();
} }
impl Module { impl Module {
@@ -123,10 +144,7 @@ impl Module {
/// [binary]: https://webassembly.github.io/spec/core/binary/index.html /// [binary]: https://webassembly.github.io/spec/core/binary/index.html
pub fn new(store: &Store, binary: &[u8]) -> Result<Module> { pub fn new(store: &Store, binary: &[u8]) -> Result<Module> {
Module::validate(store, binary)?; Module::validate(store, binary)?;
// Note that the call to `unsafe` here should be ok because we unsafe { Module::new_unchecked(store, binary) }
// previously validated the binary, meaning we're guaranteed to pass a
// valid binary for `store`.
unsafe { Module::new_internal(store, binary, None) }
} }
/// Creates a new WebAssembly `Module` from the given in-memory `binary` /// Creates a new WebAssembly `Module` from the given in-memory `binary`
@@ -134,11 +152,10 @@ impl Module {
/// ///
/// See [`Module::new`] for other details. /// See [`Module::new`] for other details.
pub fn new_with_name(store: &Store, binary: &[u8], name: &str) -> Result<Module> { pub fn new_with_name(store: &Store, binary: &[u8], name: &str) -> Result<Module> {
Module::validate(store, binary)?; let mut module = Module::new(store, binary)?;
// Note that the call to `unsafe` here should be ok because we let inner = Rc::get_mut(&mut module.inner).unwrap();
// previously validated the binary, meaning we're guaranteed to pass a Arc::get_mut(&mut inner.names).unwrap().module_name = Some(name.to_string());
// valid binary for `store`. Ok(module)
unsafe { Module::new_internal(store, binary, Some(name)) }
} }
/// Creates a new WebAssembly `Module` from the given in-memory `binary` /// Creates a new WebAssembly `Module` from the given in-memory `binary`
@@ -168,20 +185,8 @@ impl Module {
/// be somewhat valid for decoding purposes, and the basics of decoding can /// be somewhat valid for decoding purposes, and the basics of decoding can
/// still fail. /// still fail.
pub unsafe fn new_unchecked(store: &Store, binary: &[u8]) -> Result<Module> { pub unsafe fn new_unchecked(store: &Store, binary: &[u8]) -> Result<Module> {
Module::new_internal(store, binary, None) let mut ret = Module::compile(store, binary)?;
}
/// Creates a new `Module` and compiles it without doing any validation.
unsafe fn new_internal(store: &Store, binary: &[u8], name: Option<&str>) -> Result<Module> {
let mut ret = Module::empty(store);
ret.read_imports_and_exports(binary)?; ret.read_imports_and_exports(binary)?;
let inner = Rc::get_mut(&mut ret.inner).unwrap();
if let Some(name) = name {
// Assign or override the module's name if supplied.
inner.name = Some(name.to_string());
}
inner.compiled = Some(compile(store, binary, inner.name.as_deref())?);
Ok(ret) Ok(ret)
} }
@@ -220,31 +225,42 @@ impl Module {
#[doc(hidden)] #[doc(hidden)]
pub fn from_exports(store: &Store, exports: Box<[ExportType]>) -> Self { pub fn from_exports(store: &Store, exports: Box<[ExportType]>) -> Self {
let mut ret = Module::empty(store); let mut ret = unsafe { Module::compile(store, b"\0asm\x01\0\0\0").unwrap() };
Rc::get_mut(&mut ret.inner).unwrap().exports = exports; Rc::get_mut(&mut ret.inner).unwrap().exports = exports;
return ret; return ret;
} }
fn empty(store: &Store) -> Self { unsafe fn compile(store: &Store, binary: &[u8]) -> Result<Self> {
Module { let compiled = CompiledModule::new(
&mut store.compiler_mut(),
binary,
store.engine().config().debug_info,
)?;
let names = Arc::new(Names {
module_name: None,
module: compiled.module().clone(),
});
Ok(Module {
inner: Rc::new(ModuleInner { inner: Rc::new(ModuleInner {
store: store.clone(), store: store.clone(),
imports: Box::new([]), imports: Box::new([]),
exports: Box::new([]), exports: Box::new([]),
name: None, names,
compiled: None, compiled,
registered_names: Cell::new(false),
}), }),
} })
} }
pub(crate) fn compiled_module(&self) -> Option<&CompiledModule> { pub(crate) fn compiled_module(&self) -> &CompiledModule {
self.inner.compiled.as_ref() &self.inner.compiled
} }
/// Returns identifier/name that this [`Module`] has. This name /// Returns identifier/name that this [`Module`] has. This name
/// is used in traps/backtrace details. /// is used in traps/backtrace details.
pub fn name(&self) -> Option<&str> { pub fn name(&self) -> Option<&str> {
self.inner.name.as_deref() self.inner.names.module_name.as_deref()
} }
/// Returns the list of imports that this [`Module`] has and must be /// Returns the list of imports that this [`Module`] has and must be
@@ -375,7 +391,8 @@ impl Module {
while let Ok(entry) = reader.read() { while let Ok(entry) = reader.read() {
if let Name::Module(name) = entry { if let Name::Module(name) = entry {
if let Ok(name) = name.get_name() { if let Ok(name) = name.get_name() {
inner.name = Some(name.to_string()); Arc::get_mut(&mut inner.names).unwrap().module_name =
Some(name.to_string());
} }
break; break;
} }
@@ -392,14 +409,24 @@ impl Module {
inner.exports = exports.into(); inner.exports = exports.into();
Ok(()) Ok(())
} }
/// Register this module's names in the global map of module names.
///
/// This is required to ensure that any traps can be properly symbolicated.
pub(crate) fn register_names(&self) {
if self.inner.registered_names.get() {
return;
}
let names = self.inner.names.clone();
NAMES.write().unwrap().insert(names.module.id, names);
self.inner.registered_names.set(true);
}
} }
fn compile(store: &Store, binary: &[u8], module_name: Option<&str>) -> Result<CompiledModule> { impl Drop for ModuleInner {
let compiled_module = CompiledModule::new( fn drop(&mut self) {
&mut store.compiler_mut(), if self.registered_names.get() {
binary, NAMES.write().unwrap().remove(&self.names.module.id);
module_name, }
store.engine().config().debug_info, }
)?;
Ok(compiled_module)
} }

View File

@@ -4,7 +4,7 @@ use crate::runtime::Store;
use anyhow::Result; use anyhow::Result;
use std::any::Any; use std::any::Any;
use std::collections::HashSet; use std::collections::HashSet;
use std::rc::Rc; use std::sync::Arc;
use wasmtime_environ::entity::PrimaryMap; use wasmtime_environ::entity::PrimaryMap;
use wasmtime_environ::wasm::DefinedFuncIndex; use wasmtime_environ::wasm::DefinedFuncIndex;
use wasmtime_environ::Module; use wasmtime_environ::Module;
@@ -37,7 +37,7 @@ pub(crate) fn create_handle(
.unwrap_or_else(PrimaryMap::new); .unwrap_or_else(PrimaryMap::new);
Ok(InstanceHandle::new( Ok(InstanceHandle::new(
Rc::new(module), Arc::new(module),
finished_functions.into_boxed_slice(), finished_functions.into_boxed_slice(),
imports, imports,
&data_initializers, &data_initializers,

View File

@@ -1,6 +1,8 @@
use crate::module::NAMES;
use backtrace::Backtrace; use backtrace::Backtrace;
use std::fmt; use std::fmt;
use std::sync::Arc; use std::sync::Arc;
use wasmtime_environ::entity::EntityRef;
/// A struct representing an aborted instruction execution, with a message /// A struct representing an aborted instruction execution, with a message
/// indicating the cause. /// indicating the cause.
@@ -36,16 +38,23 @@ impl Trap {
fn new_with_trace(message: String, native_trace: Backtrace) -> Self { fn new_with_trace(message: String, native_trace: Backtrace) -> Self {
let mut wasm_trace = Vec::new(); let mut wasm_trace = Vec::new();
let names = NAMES.read().unwrap();
for frame in native_trace.frames() { for frame in native_trace.frames() {
let pc = frame.ip() as usize; let pc = frame.ip() as usize;
if let Some(info) = wasmtime_runtime::jit_function_registry::find(pc) { 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 { wasm_trace.push(FrameInfo {
func_index: info.func_index as u32, func_index: info.func_index.index() as u32,
module_name: info.module_id.get().map(|s| s.to_string()), module_name: names.module_name.clone(),
func_name: info.func_name.get().map(|s| s.to_string()), func_name: names.module.func_names.get(&info.func_index).cloned(),
}) })
} }
}
Trap { Trap {
inner: Arc::new(TrapInner { inner: Arc::new(TrapInner {
message, message,

View File

@@ -54,7 +54,7 @@ pub use crate::func_environ::BuiltinFunctionIndex;
#[cfg(feature = "lightbeam")] #[cfg(feature = "lightbeam")]
pub use crate::lightbeam::Lightbeam; pub use crate::lightbeam::Lightbeam;
pub use crate::module::{ pub use crate::module::{
Export, MemoryPlan, MemoryStyle, Module, ModuleSyncString, TableElements, TablePlan, TableStyle, Export, MemoryPlan, MemoryStyle, Module, TableElements, TablePlan, TableStyle,
}; };
pub use crate::module_environ::{ pub use crate::module_environ::{
translate_signature, DataInitializer, DataInitializerLocation, FunctionBodyData, translate_signature, DataInitializer, DataInitializerLocation, FunctionBodyData,

View File

@@ -3,15 +3,16 @@
use crate::module_environ::FunctionBodyData; use crate::module_environ::FunctionBodyData;
use crate::tunables::Tunables; use crate::tunables::Tunables;
use cranelift_codegen::ir; use cranelift_codegen::ir;
use cranelift_entity::{EntityRef, PrimaryMap, SecondaryMap}; use cranelift_entity::{EntityRef, PrimaryMap};
use cranelift_wasm::{ use cranelift_wasm::{
DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, Global, DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, Global,
GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex,
}; };
use indexmap::IndexMap; use indexmap::IndexMap;
use more_asserts::assert_ge; use more_asserts::assert_ge;
use std::collections::HashMap;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
/// A WebAssembly table initializer. /// A WebAssembly table initializer.
#[derive(Clone, Debug, Hash)] #[derive(Clone, Debug, Hash)]
@@ -129,33 +130,14 @@ impl TablePlan {
} }
} }
/// Allows module strings to be cached as reused across
/// multiple threads. Useful for debug/trace information.
#[derive(Debug, Clone)]
pub struct ModuleSyncString(Option<Arc<String>>);
impl ModuleSyncString {
/// Gets optional string reference.
pub fn get(&self) -> Option<&str> {
self.0.as_deref().map(|s| s.as_str())
}
/// Constructs the string.
pub fn new(s: Option<&str>) -> Self {
ModuleSyncString(s.map(|s| Arc::new(s.to_string())))
}
}
impl Default for ModuleSyncString {
fn default() -> Self {
ModuleSyncString(None)
}
}
/// A translated WebAssembly module, excluding the function bodies and /// A translated WebAssembly module, excluding the function bodies and
/// memory initializers. /// memory initializers.
// WARNING: when modifying, make sure that `hash_for_cache` is still valid! // WARNING: when modifying, make sure that `hash_for_cache` is still valid!
#[derive(Debug)] #[derive(Debug)]
pub struct Module { pub struct Module {
/// A unique identifier (within this process) for this module.
pub id: usize,
/// Unprocessed signatures exactly as provided by `declare_signature()`. /// Unprocessed signatures exactly as provided by `declare_signature()`.
pub signatures: PrimaryMap<SignatureIndex, ir::Signature>, pub signatures: PrimaryMap<SignatureIndex, ir::Signature>,
@@ -193,17 +175,17 @@ pub struct Module {
/// WebAssembly table initializers. /// WebAssembly table initializers.
pub table_elements: Vec<TableElements>, pub table_elements: Vec<TableElements>,
/// Module name. /// WebAssembly table initializers.
pub name: ModuleSyncString, pub func_names: HashMap<FuncIndex, String>,
/// Function names.
pub func_names: SecondaryMap<FuncIndex, ModuleSyncString>,
} }
impl Module { impl Module {
/// Allocates the module data structures. /// Allocates the module data structures.
pub fn new() -> Self { pub fn new() -> Self {
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
Self { Self {
id: NEXT_ID.fetch_add(1, SeqCst),
signatures: PrimaryMap::new(), signatures: PrimaryMap::new(),
imported_funcs: PrimaryMap::new(), imported_funcs: PrimaryMap::new(),
imported_tables: PrimaryMap::new(), imported_tables: PrimaryMap::new(),
@@ -216,8 +198,7 @@ impl Module {
exports: IndexMap::new(), exports: IndexMap::new(),
start_func: None, start_func: None,
table_elements: Vec::new(), table_elements: Vec::new(),
name: Default::default(), func_names: HashMap::new(),
func_names: SecondaryMap::new(),
} }
} }

View File

@@ -1,5 +1,5 @@
use crate::func_environ::FuncEnvironment; use crate::func_environ::FuncEnvironment;
use crate::module::{Export, MemoryPlan, Module, ModuleSyncString, TableElements, TablePlan}; use crate::module::{Export, MemoryPlan, Module, TableElements, TablePlan};
use crate::tunables::Tunables; use crate::tunables::Tunables;
use cranelift_codegen::ir; use cranelift_codegen::ir;
use cranelift_codegen::ir::{AbiParam, ArgumentPurpose}; use cranelift_codegen::ir::{AbiParam, ArgumentPurpose};
@@ -371,7 +371,10 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
} }
fn declare_func_name(&mut self, func_index: FuncIndex, name: &'data str) -> WasmResult<()> { fn declare_func_name(&mut self, func_index: FuncIndex, name: &'data str) -> WasmResult<()> {
self.result.module.func_names[func_index] = ModuleSyncString::new(Some(name)); self.result
.module
.func_names
.insert(func_index, name.to_string());
Ok(()) Ok(())
} }
} }

View File

@@ -167,15 +167,9 @@ impl Compiler {
self.jit_function_ranges self.jit_function_ranges
.push((ptr as usize, ptr as usize + body_len)); .push((ptr as usize, ptr as usize + body_len));
let func_index = module.func_index(i); let func_index = module.func_index(i);
let func_name = module
.func_names
.get(func_index)
.cloned()
.unwrap_or_else(Default::default);
let tag = jit_function_registry::JITFunctionTag { let tag = jit_function_registry::JITFunctionTag {
module_id: module.name.clone(), module_id: module.id,
func_index: func_index.index(), func_index,
func_name,
}; };
jit_function_registry::register(ptr as usize, ptr as usize + body_len, tag); jit_function_registry::register(ptr as usize, ptr as usize + body_len, tag);
} }

View File

@@ -109,13 +109,7 @@ impl Context {
self.validate(&data).map_err(SetupError::Validate)?; self.validate(&data).map_err(SetupError::Validate)?;
let debug_info = self.debug_info(); let debug_info = self.debug_info();
instantiate( instantiate(&mut *self.compiler, &data, &mut self.namespace, debug_info)
&mut *self.compiler,
&data,
None,
&mut self.namespace,
debug_info,
)
} }
/// Return the instance associated with the given name. /// Return the instance associated with the given name.
@@ -146,7 +140,7 @@ impl Context {
self.validate(&data).map_err(SetupError::Validate)?; self.validate(&data).map_err(SetupError::Validate)?;
let debug_info = self.debug_info(); let debug_info = self.debug_info();
CompiledModule::new(&mut *self.compiler, data, None, debug_info) CompiledModule::new(&mut *self.compiler, data, debug_info)
} }
/// If `name` isn't None, register it for the given instance. /// If `name` isn't None, register it for the given instance.

View File

@@ -9,13 +9,13 @@ use crate::link::link_module;
use crate::resolver::Resolver; use crate::resolver::Resolver;
use std::io::Write; use std::io::Write;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc;
use thiserror::Error; use thiserror::Error;
use wasmtime_debug::read_debuginfo; use wasmtime_debug::read_debuginfo;
use wasmtime_environ::entity::{BoxedSlice, PrimaryMap}; use wasmtime_environ::entity::{BoxedSlice, PrimaryMap};
use wasmtime_environ::wasm::{DefinedFuncIndex, SignatureIndex}; use wasmtime_environ::wasm::{DefinedFuncIndex, SignatureIndex};
use wasmtime_environ::{ use wasmtime_environ::{
CompileError, DataInitializer, DataInitializerLocation, Module, ModuleEnvironment, CompileError, DataInitializer, DataInitializerLocation, Module, ModuleEnvironment,
ModuleSyncString,
}; };
use wasmtime_runtime::{ use wasmtime_runtime::{
GdbJitImageRegistration, InstanceHandle, InstantiationError, VMFunctionBody, GdbJitImageRegistration, InstanceHandle, InstantiationError, VMFunctionBody,
@@ -59,12 +59,11 @@ impl<'data> RawCompiledModule<'data> {
fn new( fn new(
compiler: &mut Compiler, compiler: &mut Compiler,
data: &'data [u8], data: &'data [u8],
module_name: Option<&str>,
debug_info: bool, debug_info: bool,
) -> Result<Self, SetupError> { ) -> Result<Self, SetupError> {
let environ = ModuleEnvironment::new(compiler.frontend_config(), compiler.tunables()); let environ = ModuleEnvironment::new(compiler.frontend_config(), compiler.tunables());
let mut translation = environ let translation = environ
.translate(data) .translate(data)
.map_err(|error| SetupError::Compile(CompileError::Wasm(error)))?; .map_err(|error| SetupError::Compile(CompileError::Wasm(error)))?;
@@ -74,8 +73,6 @@ impl<'data> RawCompiledModule<'data> {
None None
}; };
translation.module.name = ModuleSyncString::new(module_name);
let (allocated_functions, jt_offsets, relocations, dbg_image) = compiler.compile( let (allocated_functions, jt_offsets, relocations, dbg_image) = compiler.compile(
&translation.module, &translation.module,
translation.module_translation.as_ref().unwrap(), translation.module_translation.as_ref().unwrap(),
@@ -136,7 +133,7 @@ impl<'data> RawCompiledModule<'data> {
/// A compiled wasm module, ready to be instantiated. /// A compiled wasm module, ready to be instantiated.
pub struct CompiledModule { pub struct CompiledModule {
module: Rc<Module>, module: Arc<Module>,
finished_functions: BoxedSlice<DefinedFuncIndex, *const VMFunctionBody>, finished_functions: BoxedSlice<DefinedFuncIndex, *const VMFunctionBody>,
data_initializers: Box<[OwnedDataInitializer]>, data_initializers: Box<[OwnedDataInitializer]>,
signatures: BoxedSlice<SignatureIndex, VMSharedSignatureIndex>, signatures: BoxedSlice<SignatureIndex, VMSharedSignatureIndex>,
@@ -148,10 +145,9 @@ impl CompiledModule {
pub fn new<'data>( pub fn new<'data>(
compiler: &mut Compiler, compiler: &mut Compiler,
data: &'data [u8], data: &'data [u8],
module_name: Option<&str>,
debug_info: bool, debug_info: bool,
) -> Result<Self, SetupError> { ) -> Result<Self, SetupError> {
let raw = RawCompiledModule::<'data>::new(compiler, data, module_name, debug_info)?; let raw = RawCompiledModule::<'data>::new(compiler, data, debug_info)?;
Ok(Self::from_parts( Ok(Self::from_parts(
raw.module, raw.module,
@@ -175,7 +171,7 @@ impl CompiledModule {
dbg_jit_registration: Option<GdbJitImageRegistration>, dbg_jit_registration: Option<GdbJitImageRegistration>,
) -> Self { ) -> Self {
Self { Self {
module: Rc::new(module), module: Arc::new(module),
finished_functions, finished_functions,
data_initializers, data_initializers,
signatures, signatures,
@@ -202,7 +198,7 @@ impl CompiledModule {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let imports = resolve_imports(&self.module, resolver)?; let imports = resolve_imports(&self.module, resolver)?;
InstanceHandle::new( InstanceHandle::new(
Rc::clone(&self.module), Arc::clone(&self.module),
self.finished_functions.clone(), self.finished_functions.clone(),
imports, imports,
&data_initializers, &data_initializers,
@@ -213,8 +209,8 @@ impl CompiledModule {
} }
/// Return a reference-counting pointer to a module. /// Return a reference-counting pointer to a module.
pub fn module(&self) -> Rc<Module> { pub fn module(&self) -> &Arc<Module> {
self.module.clone() &self.module
} }
/// Return a reference to a module. /// Return a reference to a module.
@@ -250,21 +246,9 @@ impl OwnedDataInitializer {
pub fn instantiate( pub fn instantiate(
compiler: &mut Compiler, compiler: &mut Compiler,
data: &[u8], data: &[u8],
module_name: Option<&str>,
resolver: &mut dyn Resolver, resolver: &mut dyn Resolver,
debug_info: bool, debug_info: bool,
) -> Result<InstanceHandle, SetupError> { ) -> Result<InstanceHandle, SetupError> {
let raw = RawCompiledModule::new(compiler, data, module_name, debug_info)?; let instance = CompiledModule::new(compiler, data, debug_info)?.instantiate(resolver)?;
let imports = resolve_imports(&raw.module, resolver) Ok(instance)
.map_err(|err| SetupError::Instantiate(InstantiationError::Link(err)))?;
InstanceHandle::new(
Rc::new(raw.module),
raw.finished_functions,
imports,
&*raw.data_initializers,
raw.signatures,
raw.dbg_jit_registration.map(Rc::new),
Box::new(()),
)
.map_err(SetupError::Instantiate)
} }

View File

@@ -23,6 +23,7 @@ use std::collections::HashSet;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::ptr::NonNull; use std::ptr::NonNull;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc;
use std::{mem, ptr, slice}; use std::{mem, ptr, slice};
use thiserror::Error; use thiserror::Error;
use wasmtime_environ::entity::{BoxedSlice, EntityRef, PrimaryMap}; use wasmtime_environ::entity::{BoxedSlice, EntityRef, PrimaryMap};
@@ -288,7 +289,7 @@ pub(crate) struct Instance {
mmap: Mmap, mmap: Mmap,
/// The `Module` this `Instance` was instantiated from. /// The `Module` this `Instance` was instantiated from.
module: Rc<Module>, module: Arc<Module>,
/// Offsets in the `vmctx` region. /// Offsets in the `vmctx` region.
offsets: VMOffsets, offsets: VMOffsets,
@@ -748,7 +749,7 @@ impl InstanceHandle {
/// Create a new `InstanceHandle` pointing at a new `Instance`. /// Create a new `InstanceHandle` pointing at a new `Instance`.
pub fn new( pub fn new(
module: Rc<Module>, module: Arc<Module>,
finished_functions: BoxedSlice<DefinedFuncIndex, *const VMFunctionBody>, finished_functions: BoxedSlice<DefinedFuncIndex, *const VMFunctionBody>,
imports: Imports, imports: Imports,
data_initializers: &[DataInitializer<'_>], data_initializers: &[DataInitializer<'_>],
@@ -895,8 +896,8 @@ impl InstanceHandle {
} }
/// Return a reference-counting pointer to a module. /// Return a reference-counting pointer to a module.
pub fn module(&self) -> Rc<Module> { pub fn module(&self) -> &Arc<Module> {
self.instance().module.clone() &self.instance().module
} }
/// Return a reference to a module. /// Return a reference to a module.
@@ -1110,7 +1111,7 @@ fn lookup_by_declaration(
} }
fn check_table_init_bounds(instance: &mut Instance) -> Result<(), InstantiationError> { fn check_table_init_bounds(instance: &mut Instance) -> Result<(), InstantiationError> {
let module = Rc::clone(&instance.module); let module = Arc::clone(&instance.module);
for init in &module.table_elements { for init in &module.table_elements {
let start = get_table_init_start(init, instance); let start = get_table_init_start(init, instance);
let slice = get_table_slice( let slice = get_table_slice(
@@ -1234,7 +1235,7 @@ fn get_table_slice<'instance>(
/// Initialize the table memory from the provided initializers. /// Initialize the table memory from the provided initializers.
fn initialize_tables(instance: &mut Instance) -> Result<(), InstantiationError> { fn initialize_tables(instance: &mut Instance) -> Result<(), InstantiationError> {
let vmctx: *mut VMContext = instance.vmctx_mut(); let vmctx: *mut VMContext = instance.vmctx_mut();
let module = Rc::clone(&instance.module); let module = Arc::clone(&instance.module);
for init in &module.table_elements { for init in &module.table_elements {
let start = get_table_init_start(init, instance); let start = get_table_init_start(init, instance);
let slice = get_table_slice( let slice = get_table_slice(
@@ -1311,7 +1312,7 @@ fn create_globals(module: &Module) -> BoxedSlice<DefinedGlobalIndex, VMGlobalDef
} }
fn initialize_globals(instance: &mut Instance) { fn initialize_globals(instance: &mut Instance) {
let module = Rc::clone(&instance.module); let module = Arc::clone(&instance.module);
let num_imports = module.imported_globals.len(); let num_imports = module.imported_globals.len();
for (index, global) in module.globals.iter().skip(num_imports) { for (index, global) in module.globals.iter().skip(num_imports) {
let def_index = module.defined_global_index(index).unwrap(); let def_index = module.defined_global_index(index).unwrap();

View File

@@ -3,7 +3,7 @@
use lazy_static::lazy_static; use lazy_static::lazy_static;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use wasmtime_environ::ModuleSyncString; use wasmtime_environ::wasm::FuncIndex;
lazy_static! { lazy_static! {
static ref REGISTRY: RwLock<JITFunctionRegistry> = RwLock::new(JITFunctionRegistry::default()); static ref REGISTRY: RwLock<JITFunctionRegistry> = RwLock::new(JITFunctionRegistry::default());
@@ -11,20 +11,8 @@ lazy_static! {
#[derive(Clone)] #[derive(Clone)]
pub struct JITFunctionTag { pub struct JITFunctionTag {
pub module_id: ModuleSyncString, pub module_id: usize,
pub func_index: usize, pub func_index: FuncIndex,
pub func_name: ModuleSyncString,
}
impl std::fmt::Debug for JITFunctionTag {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(ref module_id) = self.module_id.get() {
write!(f, "{}", module_id)?;
} else {
write!(f, "(module)")?;
}
write!(f, ":{}", self.func_index)
}
} }
struct JITFunctionRegistry { struct JITFunctionRegistry {

View File

@@ -3,7 +3,7 @@ use cranelift_codegen::{ir, isa};
use cranelift_entity::PrimaryMap; use cranelift_entity::PrimaryMap;
use cranelift_wasm::DefinedFuncIndex; use cranelift_wasm::DefinedFuncIndex;
use std::fs::File; use std::fs::File;
use std::rc::Rc; use std::sync::Arc;
use target_lexicon::HOST; use target_lexicon::HOST;
use wasi_common::hostcalls; use wasi_common::hostcalls;
use wasi_common::wasi; use wasi_common::wasi;
@@ -79,7 +79,7 @@ pub fn instantiate_wasi_with_context(
let signatures = PrimaryMap::new(); let signatures = PrimaryMap::new();
InstanceHandle::new( InstanceHandle::new(
Rc::new(module), Arc::new(module),
finished_functions.into_boxed_slice(), finished_functions.into_boxed_slice(),
imports, imports,
&data_initializers, &data_initializers,

View File

@@ -3,7 +3,7 @@ use cranelift_codegen::{ir, isa};
use cranelift_entity::PrimaryMap; use cranelift_entity::PrimaryMap;
use cranelift_wasm::DefinedFuncIndex; use cranelift_wasm::DefinedFuncIndex;
use std::fs::File; use std::fs::File;
use std::rc::Rc; use std::sync::Arc;
use target_lexicon::HOST; use target_lexicon::HOST;
use wasi_common::old::snapshot_0::hostcalls; use wasi_common::old::snapshot_0::hostcalls;
use wasi_common::old::snapshot_0::{WasiCtx, WasiCtxBuilder}; use wasi_common::old::snapshot_0::{WasiCtx, WasiCtxBuilder};
@@ -79,7 +79,7 @@ pub fn instantiate_wasi_with_context(
let signatures = PrimaryMap::new(); let signatures = PrimaryMap::new();
InstanceHandle::new( InstanceHandle::new(
Rc::new(module), Arc::new(module),
finished_functions.into_boxed_slice(), finished_functions.into_boxed_slice(),
imports, imports,
&data_initializers, &data_initializers,

View File

@@ -21,6 +21,6 @@ fn test_environ_translate() {
let mut resolver = NullResolver {}; let mut resolver = NullResolver {};
let mut compiler = Compiler::new(isa, CompilationStrategy::Auto); let mut compiler = Compiler::new(isa, CompilationStrategy::Auto);
let instance = instantiate(&mut compiler, &data, None, &mut resolver, false); let instance = instantiate(&mut compiler, &data, &mut resolver, false);
assert!(instance.is_ok()); assert!(instance.is_ok());
} }