From aef84584132afb23cf3f02b0fe79b2c0eda38f45 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Fri, 22 May 2020 17:29:22 -0500 Subject: [PATCH 01/35] mv SignatureRegistry --- crates/jit/src/compiler.rs | 28 +++-------- crates/jit/src/instantiate.rs | 49 +++++++++---------- crates/jit/src/link.rs | 2 +- crates/wasmtime/src/func.rs | 3 -- crates/wasmtime/src/instance.rs | 2 +- crates/wasmtime/src/runtime.rs | 9 +++- .../wasmtime/src/trampoline/create_handle.rs | 2 +- crates/wasmtime/src/trampoline/func.rs | 4 +- 8 files changed, 43 insertions(+), 56 deletions(-) diff --git a/crates/jit/src/compiler.rs b/crates/jit/src/compiler.rs index 0bcef5f0fce2..e0d5b07e2f63 100644 --- a/crates/jit/src/compiler.rs +++ b/crates/jit/src/compiler.rs @@ -13,16 +13,13 @@ use std::sync::Arc; use wasmtime_debug::{emit_debugsections_image, DebugInfoData}; use wasmtime_environ::entity::{EntityRef, PrimaryMap}; use wasmtime_environ::isa::{TargetFrontendConfig, TargetIsa}; -use wasmtime_environ::wasm::{DefinedFuncIndex, DefinedMemoryIndex, MemoryIndex}; +use wasmtime_environ::wasm::{DefinedFuncIndex, DefinedMemoryIndex, MemoryIndex, SignatureIndex}; use wasmtime_environ::{ CacheConfig, CompileError, CompiledFunction, Compiler as _C, ModuleAddressMap, ModuleMemoryOffset, ModuleTranslation, ModuleVmctxInfo, Relocation, RelocationTarget, Relocations, Traps, Tunables, VMOffsets, }; -use wasmtime_runtime::{ - InstantiationError, SignatureRegistry, VMFunctionBody, VMInterrupts, VMSharedSignatureIndex, - VMTrampoline, -}; +use wasmtime_runtime::{InstantiationError, VMFunctionBody, VMInterrupts, VMTrampoline}; /// Select which kind of compilation to use. #[derive(Copy, Clone, Debug)] @@ -49,7 +46,6 @@ pub enum CompilationStrategy { pub struct Compiler { isa: Box, code_memory: CodeMemory, - signatures: SignatureRegistry, strategy: CompilationStrategy, cache_config: CacheConfig, tunables: Tunables, @@ -67,7 +63,6 @@ impl Compiler { Self { isa, code_memory: CodeMemory::new(), - signatures: SignatureRegistry::new(), strategy, cache_config, tunables, @@ -80,8 +75,8 @@ impl Compiler { pub struct Compilation { pub finished_functions: PrimaryMap, pub relocations: Relocations, - pub trampolines: HashMap, - pub trampoline_relocations: HashMap>, + pub trampolines: PrimaryMap, + pub trampoline_relocations: HashMap>, pub jt_offsets: PrimaryMap, pub dbg_image: Option>, pub traps: Traps, @@ -147,13 +142,9 @@ impl Compiler { // guarantees that all functions (including indirect ones through // tables) have a trampoline when invoked through the wasmtime API. let mut cx = FunctionBuilderContext::new(); - let mut trampolines = HashMap::new(); + let mut trampolines = PrimaryMap::new(); let mut trampoline_relocations = HashMap::new(); - for sig in translation.module.local.signatures.values() { - let index = self.signatures.register(sig); - if trampolines.contains_key(&index) { - continue; - } + for (index, sig) in translation.module.local.signatures.iter() { let (trampoline, relocations) = make_trampoline( &*self.isa, &mut self.code_memory, @@ -161,7 +152,7 @@ impl Compiler { sig, std::mem::size_of::(), )?; - trampolines.insert(index, trampoline); + trampolines.push(trampoline); // Typically trampolines do not have relocations, so if one does // show up be sure to log it in case anyone's listening and there's @@ -231,11 +222,6 @@ impl Compiler { self.code_memory.publish(self.isa.as_ref()); } - /// Shared signature registry. - pub fn signatures(&self) -> &SignatureRegistry { - &self.signatures - } - /// Returns whether or not the given address falls within the JIT code /// managed by the compiler pub fn is_in_jit_code(&self, addr: usize) -> bool { diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs index e3f1a5eb9681..ebc174e9c3b3 100644 --- a/crates/jit/src/instantiate.rs +++ b/crates/jit/src/instantiate.rs @@ -24,7 +24,7 @@ use wasmtime_profiling::ProfilingAgent; use wasmtime_runtime::VMInterrupts; use wasmtime_runtime::{ GdbJitImageRegistration, InstanceHandle, InstantiationError, RuntimeMemoryCreator, - SignatureRegistry, VMFunctionBody, VMSharedSignatureIndex, VMTrampoline, + SignatureRegistry, VMFunctionBody, VMTrampoline, }; /// An error condition while setting up a wasm instance, be it validation, @@ -54,9 +54,8 @@ pub enum SetupError { struct RawCompiledModule<'data> { module: Module, finished_functions: BoxedSlice, - trampolines: HashMap, + trampolines: PrimaryMap, data_initializers: Box<[DataInitializer<'data>]>, - signatures: BoxedSlice, dbg_jit_registration: Option, traps: Traps, address_transform: ModuleAddressMap, @@ -85,18 +84,6 @@ impl<'data> RawCompiledModule<'data> { link_module(&translation.module, &compilation); - // Compute indices into the shared signature table. - let signatures = { - let signature_registry = compiler.signatures(); - translation - .module - .local - .signatures - .values() - .map(|sig| signature_registry.register(sig)) - .collect::>() - }; - // Make all code compiled thus far executable. compiler.publish_compiled_code(); @@ -121,7 +108,6 @@ impl<'data> RawCompiledModule<'data> { finished_functions: compilation.finished_functions.into_boxed_slice(), trampolines: compilation.trampolines, data_initializers: translation.data_initializers.into_boxed_slice(), - signatures: signatures.into_boxed_slice(), dbg_jit_registration, traps: compilation.traps, address_transform: compilation.address_transform, @@ -133,9 +119,8 @@ impl<'data> RawCompiledModule<'data> { pub struct CompiledModule { module: Arc, finished_functions: BoxedSlice, - trampolines: HashMap, + trampolines: PrimaryMap, data_initializers: Box<[OwnedDataInitializer]>, - signatures: BoxedSlice, dbg_jit_registration: Option>, traps: Traps, address_transform: ModuleAddressMap, @@ -160,7 +145,6 @@ impl CompiledModule { .map(OwnedDataInitializer::new) .collect::>() .into_boxed_slice(), - raw.signatures.clone(), raw.dbg_jit_registration, raw.traps, raw.address_transform, @@ -172,9 +156,8 @@ impl CompiledModule { pub fn from_parts( module: Module, finished_functions: BoxedSlice, - trampolines: HashMap, + trampolines: PrimaryMap, data_initializers: Box<[OwnedDataInitializer]>, - signatures: BoxedSlice, dbg_jit_registration: Option, traps: Traps, address_transform: ModuleAddressMap, @@ -185,7 +168,6 @@ impl CompiledModule { finished_functions, trampolines, data_initializers, - signatures, dbg_jit_registration: dbg_jit_registration.map(Rc::new), traps, address_transform, @@ -205,18 +187,33 @@ impl CompiledModule { pub unsafe fn instantiate( &self, resolver: &mut dyn Resolver, - sig_registry: &SignatureRegistry, + signature_registry: &SignatureRegistry, mem_creator: Option<&dyn RuntimeMemoryCreator>, host_state: Box, ) -> Result { - let imports = resolve_imports(&self.module, &sig_registry, resolver)?; + // Compute indices into the shared signature table. + let signatures = { + self.module + .local + .signatures + .values() + .map(|sig| signature_registry.register(sig)) + .collect::>() + }; + + let mut trampolines = HashMap::new(); + for (i, trampoline) in self.trampolines.iter() { + trampolines.insert(signatures[i], trampoline.clone()); + } + + let imports = resolve_imports(&self.module, signature_registry, resolver)?; InstanceHandle::new( Arc::clone(&self.module), self.finished_functions.clone(), - self.trampolines.clone(), + trampolines, imports, mem_creator, - self.signatures.clone(), + signatures.into_boxed_slice(), self.dbg_jit_registration.as_ref().map(|r| Rc::clone(&r)), host_state, self.interrupts.clone(), diff --git a/crates/jit/src/link.rs b/crates/jit/src/link.rs index 26a9a8833ccc..9201c4e0b015 100644 --- a/crates/jit/src/link.rs +++ b/crates/jit/src/link.rs @@ -22,7 +22,7 @@ pub fn link_module(module: &Module, compilation: &Compilation) { for (i, function_relocs) in compilation.trampoline_relocations.iter() { for r in function_relocs.iter() { println!("tramopline relocation"); - let body = compilation.trampolines[&i] as *const VMFunctionBody; + let body = compilation.trampolines[*i] as *const VMFunctionBody; apply_reloc(module, compilation, body, r); } } diff --git a/crates/wasmtime/src/func.rs b/crates/wasmtime/src/func.rs index 70bf2843bc76..59512c11e927 100644 --- a/crates/wasmtime/src/func.rs +++ b/crates/wasmtime/src/func.rs @@ -481,7 +481,6 @@ impl Func { let sig = self .instance .store - .compiler() .signatures() .lookup(self.export.signature) .expect("failed to lookup signature"); @@ -497,7 +496,6 @@ impl Func { let sig = self .instance .store - .compiler() .signatures() .lookup(self.export.signature) .expect("failed to lookup signature"); @@ -509,7 +507,6 @@ impl Func { let sig = self .instance .store - .compiler() .signatures() .lookup(self.export.signature) .expect("failed to lookup signature"); diff --git a/crates/wasmtime/src/instance.rs b/crates/wasmtime/src/instance.rs index a048eecaf5db..3faf9a023e63 100644 --- a/crates/wasmtime/src/instance.rs +++ b/crates/wasmtime/src/instance.rs @@ -169,7 +169,7 @@ impl Instance { store, module.compiled_module(), imports, - store.compiler().signatures(), + &store.signatures(), Box::new(info), )?; diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs index 2ba9f2fc4b41..b40d513a4843 100644 --- a/crates/wasmtime/src/runtime.rs +++ b/crates/wasmtime/src/runtime.rs @@ -14,7 +14,8 @@ use wasmtime_environ::{CacheConfig, Tunables}; use wasmtime_jit::{native, CompilationStrategy, Compiler}; use wasmtime_profiling::{JitDumpAgent, NullProfilerAgent, ProfilingAgent, VTuneAgent}; use wasmtime_runtime::{ - debug_builtins, InstanceHandle, RuntimeMemoryCreator, SignalHandler, VMInterrupts, + debug_builtins, InstanceHandle, RuntimeMemoryCreator, SignalHandler, SignatureRegistry, + VMInterrupts, }; // Runtime Environment @@ -730,6 +731,7 @@ pub struct Store { pub(crate) struct StoreInner { engine: Engine, compiler: RefCell, + signatures: RefCell, instances: RefCell>, signal_handler: RefCell>>>, } @@ -755,6 +757,7 @@ impl Store { inner: Rc::new(StoreInner { engine: engine.clone(), compiler: RefCell::new(compiler), + signatures: RefCell::new(SignatureRegistry::new()), instances: RefCell::new(Vec::new()), signal_handler: RefCell::new(None), }), @@ -783,6 +786,10 @@ impl Store { self.inner.compiler.borrow_mut() } + pub(crate) fn signatures(&self) -> std::cell::Ref<'_, SignatureRegistry> { + self.inner.signatures.borrow() + } + pub(crate) unsafe fn add_instance(&self, handle: InstanceHandle) -> StoreInstanceHandle { self.inner.instances.borrow_mut().push(handle.clone()); StoreInstanceHandle { diff --git a/crates/wasmtime/src/trampoline/create_handle.rs b/crates/wasmtime/src/trampoline/create_handle.rs index 428c6c35ac44..3e212e54e111 100644 --- a/crates/wasmtime/src/trampoline/create_handle.rs +++ b/crates/wasmtime/src/trampoline/create_handle.rs @@ -32,7 +32,7 @@ pub(crate) fn create_handle( .local .signatures .values() - .map(|sig| store.compiler().signatures().register(sig)) + .map(|sig| store.signatures().register(sig)) .collect::>(); unsafe { diff --git a/crates/wasmtime/src/trampoline/func.rs b/crates/wasmtime/src/trampoline/func.rs index 41d6ac61b378..cc97940739e8 100644 --- a/crates/wasmtime/src/trampoline/func.rs +++ b/crates/wasmtime/src/trampoline/func.rs @@ -244,7 +244,7 @@ pub fn create_handle_with_function( mem::size_of::(), )?; assert!(relocations.is_empty()); - let sig_id = store.compiler().signatures().register(&sig); + let sig_id = store.signatures().register(&sig); trampolines.insert(sig_id, trampoline); // Next up we wrap everything up into an `InstanceHandle` by publishing our @@ -291,7 +291,7 @@ pub unsafe fn create_handle_with_raw_function( .exports .insert("trampoline".to_string(), EntityIndex::Function(func_id)); finished_functions.push(func); - let sig_id = store.compiler().signatures().register(&sig); + let sig_id = store.signatures().register(&sig); trampolines.insert(sig_id, trampoline); create_handle(module, store, finished_functions, trampolines, state) From 050aebeb0dea36d891c4507210ca93119df29f3d Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Fri, 22 May 2020 18:46:29 -0500 Subject: [PATCH 02/35] mv code_memory --- crates/jit/src/code_memory.rs | 11 ++++----- crates/jit/src/compiler.rs | 26 +++++++++------------ crates/jit/src/instantiate.rs | 15 +++++++++++- crates/wasmtime/src/func.rs | 2 +- crates/wasmtime/src/module.rs | 7 +++++- crates/wasmtime/src/runtime.rs | 42 ++++++++++++++++++++++++++++++++++ 6 files changed, 79 insertions(+), 24 deletions(-) diff --git a/crates/jit/src/code_memory.rs b/crates/jit/src/code_memory.rs index e0b7315c4d01..9ad259f9959a 100644 --- a/crates/jit/src/code_memory.rs +++ b/crates/jit/src/code_memory.rs @@ -22,10 +22,10 @@ impl CodeMemoryEntry { Ok(Self { mmap, registry }) } - fn contains(&self, addr: usize) -> bool { + fn range(&self) -> (usize, usize) { let start = self.mmap.as_ptr() as usize; let end = start + self.mmap.len(); - start <= addr && addr < end + (start, end) } } @@ -243,11 +243,10 @@ impl CodeMemory { Ok(()) } - /// Returns whether any published segment of this code memory contains - /// `addr`. - pub fn published_contains(&self, addr: usize) -> bool { + /// Returns all published segment ranges. + pub fn published_ranges<'a>(&'a self) -> impl Iterator + 'a { self.entries[..self.published] .iter() - .any(|entry| entry.contains(addr)) + .map(|entry| entry.range()) } } diff --git a/crates/jit/src/compiler.rs b/crates/jit/src/compiler.rs index e0d5b07e2f63..3520127e67b8 100644 --- a/crates/jit/src/compiler.rs +++ b/crates/jit/src/compiler.rs @@ -45,7 +45,6 @@ pub enum CompilationStrategy { /// TODO: Consider using cranelift-module. pub struct Compiler { isa: Box, - code_memory: CodeMemory, strategy: CompilationStrategy, cache_config: CacheConfig, tunables: Tunables, @@ -62,7 +61,6 @@ impl Compiler { ) -> Self { Self { isa, - code_memory: CodeMemory::new(), strategy, cache_config, tunables, @@ -73,6 +71,7 @@ impl Compiler { #[allow(missing_docs)] pub struct Compilation { + pub code_memory: CodeMemory, pub finished_functions: PrimaryMap, pub relocations: Relocations, pub trampolines: PrimaryMap, @@ -84,6 +83,11 @@ pub struct Compilation { } impl Compiler { + /// Return the isa. + pub fn isa(&self) -> &dyn TargetIsa { + self.isa.as_ref() + } + /// Return the target's frontend configuration settings. pub fn frontend_config(&self) -> TargetFrontendConfig { self.isa.frontend_config() @@ -105,6 +109,8 @@ impl Compiler { translation: &ModuleTranslation, debug_data: Option, ) -> Result { + let mut code_memory = CodeMemory::new(); + let (compilation, relocations, address_transform, value_ranges, stack_slots, traps) = match self.strategy { // For now, interpret `Auto` as `Cranelift` since that's the most stable @@ -130,7 +136,7 @@ impl Compiler { // Allocate all of the compiled functions into executable memory, // copying over their contents. let finished_functions = - allocate_functions(&mut self.code_memory, &compilation).map_err(|message| { + allocate_functions(&mut code_memory, &compilation).map_err(|message| { SetupError::Instantiate(InstantiationError::Resource(format!( "failed to allocate memory for functions: {}", message @@ -147,7 +153,7 @@ impl Compiler { for (index, sig) in translation.module.local.signatures.iter() { let (trampoline, relocations) = make_trampoline( &*self.isa, - &mut self.code_memory, + &mut code_memory, &mut cx, sig, std::mem::size_of::(), @@ -206,6 +212,7 @@ impl Compiler { let jt_offsets = compilation.get_jt_offsets(); Ok(Compilation { + code_memory, finished_functions, relocations, trampolines, @@ -216,17 +223,6 @@ impl Compiler { address_transform, }) } - - /// Make memory containing compiled code executable. - pub(crate) fn publish_compiled_code(&mut self) { - self.code_memory.publish(self.isa.as_ref()); - } - - /// Returns whether or not the given address falls within the JIT code - /// managed by the compiler - pub fn is_in_jit_code(&self, addr: usize) -> bool { - self.code_memory.published_contains(addr) - } } /// Create a trampoline for invoking a function. diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs index ebc174e9c3b3..db969dce14cf 100644 --- a/crates/jit/src/instantiate.rs +++ b/crates/jit/src/instantiate.rs @@ -3,6 +3,7 @@ //! `CompiledModule` to allow compiling and instantiating to be done as separate //! steps. +use crate::code_memory::CodeMemory; use crate::compiler::Compiler; use crate::imports::resolve_imports; use crate::link::link_module; @@ -52,6 +53,7 @@ pub enum SetupError { /// This is similar to `CompiledModule`, but references the data initializers /// from the wasm buffer rather than holding its own copy. struct RawCompiledModule<'data> { + code_memory: CodeMemory, module: Module, finished_functions: BoxedSlice, trampolines: PrimaryMap, @@ -85,7 +87,8 @@ impl<'data> RawCompiledModule<'data> { link_module(&translation.module, &compilation); // Make all code compiled thus far executable. - compiler.publish_compiled_code(); + let mut code_memory = compilation.code_memory; + code_memory.publish(compiler.isa()); // Initialize profiler and load the wasm module profiler.module_load( @@ -104,6 +107,7 @@ impl<'data> RawCompiledModule<'data> { }; Ok(Self { + code_memory, module: translation.module, finished_functions: compilation.finished_functions.into_boxed_slice(), trampolines: compilation.trampolines, @@ -117,6 +121,7 @@ impl<'data> RawCompiledModule<'data> { /// A compiled wasm module, ready to be instantiated. pub struct CompiledModule { + code_memory: CodeMemory, module: Arc, finished_functions: BoxedSlice, trampolines: PrimaryMap, @@ -137,6 +142,7 @@ impl CompiledModule { let raw = RawCompiledModule::<'data>::new(compiler, data, profiler)?; Ok(Self::from_parts( + raw.code_memory, raw.module, raw.finished_functions, raw.trampolines, @@ -154,6 +160,7 @@ impl CompiledModule { /// Construct a `CompiledModule` from component parts. pub fn from_parts( + code_memory: CodeMemory, module: Module, finished_functions: BoxedSlice, trampolines: PrimaryMap, @@ -164,6 +171,7 @@ impl CompiledModule { interrupts: Arc, ) -> Self { Self { + code_memory, module: Arc::new(module), finished_functions, trampolines, @@ -260,6 +268,11 @@ impl CompiledModule { pub fn address_transform(&self) -> &ModuleAddressMap { &self.address_transform } + + /// Returns all ranges convered by JIT code. + pub fn jit_code_ranges<'a>(&'a self) -> impl Iterator + 'a { + self.code_memory.published_ranges() + } } /// Similar to `DataInitializer`, but owns its own copy of the data rather diff --git a/crates/wasmtime/src/func.rs b/crates/wasmtime/src/func.rs index 59512c11e927..00fe661b0273 100644 --- a/crates/wasmtime/src/func.rs +++ b/crates/wasmtime/src/func.rs @@ -740,7 +740,7 @@ pub(crate) fn catch_traps( wasmtime_runtime::catch_traps( vmctx, store.engine().config().max_wasm_stack, - |addr| store.compiler().is_in_jit_code(addr), + |addr| store.is_in_jit_code(addr), signalhandler.as_deref(), closure, ) diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs index c741d434e579..c1be5da28df6 100644 --- a/crates/wasmtime/src/module.rs +++ b/crates/wasmtime/src/module.rs @@ -1,5 +1,5 @@ use crate::frame_info::GlobalFrameInfoRegistration; -use crate::runtime::Store; +use crate::runtime::{JitCodeRegistration, Store}; use crate::types::{EntityType, ExportType, ImportType}; use anyhow::{Error, Result}; use std::path::Path; @@ -82,6 +82,8 @@ struct ModuleInner { store: Store, compiled: CompiledModule, frame_info_registration: Mutex>>>, + #[allow(dead_code)] + jit_code_registration: JitCodeRegistration, } impl Module { @@ -311,11 +313,14 @@ impl Module { &*store.engine().config().profiler, )?; + let jit_code_registration = store.register_jit_code(compiled.jit_code_ranges()); + Ok(Module { inner: Arc::new(ModuleInner { store: store.clone(), compiled, frame_info_registration: Mutex::new(None), + jit_code_registration, }), }) } diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs index b40d513a4843..670534c5b965 100644 --- a/crates/wasmtime/src/runtime.rs +++ b/crates/wasmtime/src/runtime.rs @@ -3,6 +3,7 @@ use crate::trampoline::{MemoryCreatorProxy, StoreInstanceHandle}; use anyhow::{bail, Result}; use std::cell::RefCell; use std::cmp; +use std::collections::HashSet; use std::convert::TryFrom; use std::fmt; use std::path::Path; @@ -734,6 +735,19 @@ pub(crate) struct StoreInner { signatures: RefCell, instances: RefCell>, signal_handler: RefCell>>>, + jit_code_ranges: RefCell>, +} + +pub(crate) struct JitCodeRegistration { + inner: Rc, + ends: HashSet, +} + +impl Drop for JitCodeRegistration { + fn drop(&mut self) { + let mut jit_code_ranges = self.inner.jit_code_ranges.borrow_mut(); + jit_code_ranges.retain(|(_, end)| self.ends.contains(end)); + } } impl Store { @@ -760,6 +774,7 @@ impl Store { signatures: RefCell::new(SignatureRegistry::new()), instances: RefCell::new(Vec::new()), signal_handler: RefCell::new(None), + jit_code_ranges: RefCell::new(Vec::new()), }), } } @@ -790,6 +805,33 @@ impl Store { self.inner.signatures.borrow() } + /// Returns whether or not the given address falls within the JIT code + /// managed by the compiler + pub(crate) fn is_in_jit_code(&self, addr: usize) -> bool { + self.inner + .jit_code_ranges + .borrow() + .iter() + .find(|(start, end)| *start <= addr && addr < *end) + .is_some() + } + + pub(crate) fn register_jit_code( + &self, + ranges: impl Iterator, + ) -> JitCodeRegistration { + let mut ends = HashSet::new(); + let mut jit_code_ranges = self.inner.jit_code_ranges.borrow_mut(); + for (start, end) in ranges { + jit_code_ranges.push((start, end)); + ends.insert(end); + } + JitCodeRegistration { + inner: self.inner.clone(), + ends, + } + } + pub(crate) unsafe fn add_instance(&self, handle: InstanceHandle) -> StoreInstanceHandle { self.inner.instances.borrow_mut().push(handle.clone()); StoreInstanceHandle { From d7defe2ee81fd01ac4a5cd065a91254c4ef63701 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 26 May 2020 12:10:46 -0500 Subject: [PATCH 03/35] Move Arc to CompiledModule level; unsafe Sync+Send --- Cargo.lock | 1 + crates/jit/src/instantiate.rs | 54 +++++++++++-------- crates/runtime/Cargo.toml | 1 + crates/runtime/src/debug_builtins.rs | 2 +- crates/runtime/src/instance.rs | 40 +++++--------- crates/runtime/src/jit_int.rs | 19 ++++++- crates/wasmtime/src/frame_info.rs | 10 ++-- crates/wasmtime/src/instance.rs | 10 ++-- crates/wasmtime/src/module.rs | 12 ++--- .../wasmtime/src/trampoline/create_handle.rs | 3 +- 10 files changed, 83 insertions(+), 69 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0859dec9bd46..37d2e24d5653 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2373,6 +2373,7 @@ dependencies = [ "cc", "cfg-if", "indexmap", + "lazy_static", "libc", "memoffset", "more-asserts", diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs index db969dce14cf..9ff8a38444f2 100644 --- a/crates/jit/src/instantiate.rs +++ b/crates/jit/src/instantiate.rs @@ -11,7 +11,6 @@ use crate::resolver::Resolver; use std::any::Any; use std::collections::HashMap; use std::io::Write; -use std::rc::Rc; use std::sync::Arc; use thiserror::Error; use wasmtime_debug::read_debuginfo; @@ -122,16 +121,33 @@ impl<'data> RawCompiledModule<'data> { /// A compiled wasm module, ready to be instantiated. pub struct CompiledModule { code_memory: CodeMemory, - module: Arc, + module: Module, finished_functions: BoxedSlice, trampolines: PrimaryMap, data_initializers: Box<[OwnedDataInitializer]>, - dbg_jit_registration: Option>, + #[allow(dead_code)] + dbg_jit_registration: Option, traps: Traps, address_transform: ModuleAddressMap, interrupts: Arc, } +impl std::ops::Deref for CompiledModule { + type Target = Module; + fn deref(&self) -> &Self::Target { + &self.module + } +} + +impl std::ops::DerefMut for CompiledModule { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.module + } +} + +unsafe impl Send for CompiledModule {} +unsafe impl Sync for CompiledModule {} + impl CompiledModule { /// Compile a data buffer into a `CompiledModule`, which may then be instantiated. pub fn new<'data>( @@ -172,11 +188,11 @@ impl CompiledModule { ) -> Self { Self { code_memory, - module: Arc::new(module), + module: module, finished_functions, trampolines, data_initializers, - dbg_jit_registration: dbg_jit_registration.map(Rc::new), + dbg_jit_registration, traps, address_transform, interrupts, @@ -193,7 +209,7 @@ impl CompiledModule { /// /// See `InstanceHandle::new` pub unsafe fn instantiate( - &self, + module: Arc, resolver: &mut dyn Resolver, signature_registry: &SignatureRegistry, mem_creator: Option<&dyn RuntimeMemoryCreator>, @@ -201,7 +217,7 @@ impl CompiledModule { ) -> Result { // Compute indices into the shared signature table. let signatures = { - self.module + module .local .signatures .values() @@ -210,21 +226,23 @@ impl CompiledModule { }; let mut trampolines = HashMap::new(); - for (i, trampoline) in self.trampolines.iter() { + for (i, trampoline) in module.trampolines.iter() { trampolines.insert(signatures[i], trampoline.clone()); } - let imports = resolve_imports(&self.module, signature_registry, resolver)?; + let finished_functions = module.finished_functions.clone(); + let interrupts = module.interrupts.clone(); + + let imports = resolve_imports(&module, signature_registry, resolver)?; InstanceHandle::new( - Arc::clone(&self.module), - self.finished_functions.clone(), + module, + finished_functions, trampolines, imports, mem_creator, signatures.into_boxed_slice(), - self.dbg_jit_registration.as_ref().map(|r| Rc::clone(&r)), host_state, - self.interrupts.clone(), + interrupts, ) } @@ -239,16 +257,6 @@ impl CompiledModule { .collect() } - /// Return a reference-counting pointer to a module. - pub fn module(&self) -> &Arc { - &self.module - } - - /// Return a reference-counting pointer to a module. - pub fn module_mut(&mut self) -> &mut Arc { - &mut self.module - } - /// Return a reference to a module. pub fn module_ref(&self) -> &Module { &self.module diff --git a/crates/runtime/Cargo.toml b/crates/runtime/Cargo.toml index a3ea52cc32a3..4d979c7b9d07 100644 --- a/crates/runtime/Cargo.toml +++ b/crates/runtime/Cargo.toml @@ -21,6 +21,7 @@ thiserror = "1.0.4" more-asserts = "0.2.1" cfg-if = "0.1.9" backtrace = "0.3.42" +lazy_static = "1.3.0" [target.'cfg(target_os = "windows")'.dependencies] winapi = { version = "0.3.7", features = ["winbase", "memoryapi", "errhandlingapi"] } diff --git a/crates/runtime/src/debug_builtins.rs b/crates/runtime/src/debug_builtins.rs index 3a6cfc8b81c2..57e7b16b7cac 100644 --- a/crates/runtime/src/debug_builtins.rs +++ b/crates/runtime/src/debug_builtins.rs @@ -16,7 +16,7 @@ pub unsafe extern "C" fn resolve_vmctx_memory_ptr(p: *const u32) -> *const u8 { ); let handle = InstanceHandle::from_vmctx(VMCTX_AND_MEMORY.0); assert!( - VMCTX_AND_MEMORY.1 < handle.module().local.memory_plans.len(), + VMCTX_AND_MEMORY.1 < handle.module_ref().local.memory_plans.len(), "memory index for debugger is out of bounds" ); let index = MemoryIndex::new(VMCTX_AND_MEMORY.1); diff --git a/crates/runtime/src/instance.rs b/crates/runtime/src/instance.rs index 0e0550141a42..1f4de861c3dd 100644 --- a/crates/runtime/src/instance.rs +++ b/crates/runtime/src/instance.rs @@ -4,7 +4,6 @@ use crate::export::Export; use crate::imports::Imports; -use crate::jit_int::GdbJitImageRegistration; use crate::memory::{DefaultMemoryCreator, RuntimeLinearMemory, RuntimeMemoryCreator}; use crate::table::Table; use crate::traphandlers::Trap; @@ -21,7 +20,7 @@ use std::any::Any; use std::cell::RefCell; use std::collections::HashMap; use std::convert::TryFrom; -use std::rc::Rc; +use std::ops::Deref; use std::sync::Arc; use std::{mem, ptr, slice}; use thiserror::Error; @@ -37,8 +36,8 @@ use wasmtime_environ::{ir, DataInitializer, EntityIndex, Module, TableElements, /// This is repr(C) to ensure that the vmctx field is last. #[repr(C)] pub(crate) struct Instance { - /// The `Module` this `Instance` was instantiated from. - module: Arc, + /// The `ModuleGrip` this `Instance` was instantiated from. + module: Arc>, /// Offsets in the `vmctx` region. offsets: VMOffsets, @@ -67,9 +66,6 @@ pub(crate) struct Instance { /// Hosts can store arbitrary per-instance information here. host_state: Box, - /// Optional image of JIT'ed code for debugger registration. - dbg_jit_registration: Option>, - /// Externally allocated data indicating how this instance will be /// interrupted. pub(crate) interrupts: Arc, @@ -96,12 +92,8 @@ impl Instance { unsafe { *self.signature_ids_ptr().add(index) } } - pub(crate) fn module(&self) -> &Arc { - &self.module - } - pub(crate) fn module_ref(&self) -> &Module { - &*self.module + &self.module } /// Return a pointer to the `VMSharedSignatureIndex`s. @@ -781,18 +773,19 @@ impl InstanceHandle { /// the `wasmtime` crate API rather than this type since that is vetted for /// safety. pub unsafe fn new( - module: Arc, + module: Arc>, finished_functions: BoxedSlice, trampolines: HashMap, imports: Imports, mem_creator: Option<&dyn RuntimeMemoryCreator>, vmshared_signatures: BoxedSlice, - dbg_jit_registration: Option>, host_state: Box, interrupts: Arc, ) -> Result { - let tables = create_tables(&module); - let memories = create_memories(&module, mem_creator.unwrap_or(&DefaultMemoryCreator {}))?; + let module_ref = &*module; + let tables = create_tables(module_ref); + let memories = + create_memories(module_ref, mem_creator.unwrap_or(&DefaultMemoryCreator {}))?; let vmctx_tables = tables .values() @@ -806,11 +799,11 @@ impl InstanceHandle { .collect::>() .into_boxed_slice(); - let vmctx_globals = create_globals(&module); + let vmctx_globals = create_globals(module_ref); let offsets = VMOffsets::new(mem::size_of::<*const u8>() as u8, &module.local); - let passive_data = RefCell::new(module.passive_data.clone()); + let passive_data = RefCell::new(module_ref.passive_data.clone()); let handle = { let instance = Instance { @@ -822,7 +815,6 @@ impl InstanceHandle { passive_data, finished_functions, trampolines, - dbg_jit_registration, host_state, interrupts, vmctx: VMContext {}, @@ -941,11 +933,6 @@ impl InstanceHandle { self.instance().vmctx_ptr() } - /// Return a reference-counting pointer to a module. - pub fn module(&self) -> &Arc { - self.instance().module() - } - /// Return a reference to a module. pub fn module_ref(&self) -> &Module { self.instance().module_ref() @@ -1066,7 +1053,7 @@ impl InstanceHandle { fn check_table_init_bounds(instance: &Instance) -> Result<(), InstantiationError> { let module = Arc::clone(&instance.module); - for init in &module.table_elements { + for init in &module.as_ref().table_elements { let start = get_table_init_start(init, instance); let table = instance.get_table(init.table_index); @@ -1170,7 +1157,7 @@ fn get_table_init_start(init: &TableElements, instance: &Instance) -> usize { /// Initialize the table memory from the provided initializers. fn initialize_tables(instance: &Instance) -> Result<(), InstantiationError> { - let module = Arc::clone(&instance.module); + let module = instance.module.as_ref(); for init in &module.table_elements { let start = get_table_init_start(init, instance); let table = instance.get_table(init.table_index); @@ -1208,6 +1195,7 @@ fn initialize_passive_elements(instance: &Instance) { passive_elements.extend( instance .module + .as_ref() .passive_elements .iter() .filter(|(_, segments)| !segments.is_empty()) diff --git a/crates/runtime/src/jit_int.rs b/crates/runtime/src/jit_int.rs index a8a0a44d6fdf..9a7ce68d8c47 100644 --- a/crates/runtime/src/jit_int.rs +++ b/crates/runtime/src/jit_int.rs @@ -2,7 +2,10 @@ //! the __jit_debug_register_code() and __jit_debug_descriptor to register //! or unregister generated object images with debuggers. +use lazy_static::lazy_static; +use std::pin::Pin; use std::ptr; +use std::sync::Mutex; #[repr(C)] struct JITCodeEntry { @@ -43,17 +46,25 @@ extern "C" fn __jit_debug_register_code() { } } +lazy_static! { + pub static ref GDB_REGISTRATION: Mutex = Mutex::new(Default::default()); +} + /// Registeration for JIT image pub struct GdbJitImageRegistration { entry: *mut JITCodeEntry, - file: Vec, + file: Pin>, } impl GdbJitImageRegistration { /// Registers JIT image using __jit_debug_register_code pub fn register(file: Vec) -> Self { + let file = Pin::new(file.into_boxed_slice()); Self { - entry: unsafe { register_gdb_jit_image(&file) }, + entry: unsafe { + let _ = GDB_REGISTRATION.lock().unwrap(); + register_gdb_jit_image(&file) + }, file, } } @@ -67,11 +78,15 @@ impl GdbJitImageRegistration { impl Drop for GdbJitImageRegistration { fn drop(&mut self) { unsafe { + let _ = GDB_REGISTRATION.lock().unwrap(); unregister_gdb_jit_image(self.entry); } } } +unsafe impl Send for GdbJitImageRegistration {} +unsafe impl Sync for GdbJitImageRegistration {} + unsafe fn register_gdb_jit_image(file: &[u8]) -> *mut JITCodeEntry { // Create a code entry for the file, which gives the start and size of the symbol file. let entry = Box::into_raw(Box::new(JITCodeEntry { diff --git a/crates/wasmtime/src/frame_info.rs b/crates/wasmtime/src/frame_info.rs index 0a4b2b6cf6da..3472a72ab00f 100644 --- a/crates/wasmtime/src/frame_info.rs +++ b/crates/wasmtime/src/frame_info.rs @@ -4,7 +4,7 @@ use std::sync::{Arc, RwLock}; use wasmtime_environ::entity::EntityRef; use wasmtime_environ::ir; use wasmtime_environ::wasm::FuncIndex; -use wasmtime_environ::{FunctionAddressMap, Module, TrapInformation}; +use wasmtime_environ::{FunctionAddressMap, TrapInformation}; use wasmtime_jit::CompiledModule; lazy_static::lazy_static! { @@ -41,7 +41,7 @@ pub struct GlobalFrameInfoRegistration { struct ModuleFrameInfo { start: usize, functions: BTreeMap, - module: Arc, + module: Arc, } struct FunctionInfo { @@ -146,7 +146,7 @@ impl Drop for GlobalFrameInfoRegistration { /// 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(module: &CompiledModule) -> Option { +pub fn register(module: Arc) -> Option { let mut min = usize::max_value(); let mut max = 0; let mut functions = BTreeMap::new(); @@ -165,7 +165,7 @@ pub fn register(module: &CompiledModule) -> Option max = cmp::max(max, end); let func = FunctionInfo { start, - index: module.module().local.func_index(i), + index: module.local.func_index(i), traps: traps.to_vec(), instr_map: (*instrs).clone(), }; @@ -191,7 +191,7 @@ pub fn register(module: &CompiledModule) -> Option ModuleFrameInfo { start: min, functions, - module: module.module().clone(), + module: module.clone(), }, ); assert!(prev.is_none()); diff --git a/crates/wasmtime/src/instance.rs b/crates/wasmtime/src/instance.rs index 3faf9a023e63..13a704d0720a 100644 --- a/crates/wasmtime/src/instance.rs +++ b/crates/wasmtime/src/instance.rs @@ -3,6 +3,7 @@ use crate::{Export, Extern, Func, Global, Memory, Module, Store, Table, Trap}; use anyhow::{bail, Error, Result}; use std::any::Any; use std::mem; +use std::sync::Arc; use wasmtime_environ::EntityIndex; use wasmtime_jit::{CompiledModule, Resolver}; use wasmtime_runtime::{InstantiationError, SignatureRegistry, VMContext, VMFunctionBody}; @@ -21,7 +22,7 @@ impl Resolver for SimpleResolver<'_> { fn instantiate( store: &Store, - compiled_module: &CompiledModule, + compiled_module: Arc, imports: &[Extern], sig_registry: &SignatureRegistry, host: Box, @@ -29,7 +30,8 @@ fn instantiate( let mut resolver = SimpleResolver { imports }; unsafe { let config = store.engine().config(); - let instance = compiled_module.instantiate( + let instance = CompiledModule::instantiate( + compiled_module.clone(), &mut resolver, sig_registry, config.memory_creator.as_ref().map(|a| a as _), @@ -61,7 +63,7 @@ fn instantiate( // If a start function is present, now that we've got our compiled // instance we can invoke it. Make sure we use all the trap-handling // configuration in `store` as well. - if let Some(start) = instance.module().start_func { + if let Some(start) = instance.module_ref().start_func { let f = match instance.lookup_by_declaration(&EntityIndex::Function(start)) { wasmtime_runtime::Export::Function(f) => f, _ => unreachable!(), // valid modules shouldn't hit this @@ -167,7 +169,7 @@ impl Instance { let info = module.register_frame_info(); let handle = instantiate( store, - module.compiled_module(), + module.compiled_module().clone(), imports, &store.signatures(), Box::new(info), diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs index c1be5da28df6..ba17dcd08e25 100644 --- a/crates/wasmtime/src/module.rs +++ b/crates/wasmtime/src/module.rs @@ -80,7 +80,7 @@ pub struct Module { struct ModuleInner { store: Store, - compiled: CompiledModule, + compiled: Arc, frame_info_registration: Mutex>>>, #[allow(dead_code)] jit_code_registration: JitCodeRegistration, @@ -171,7 +171,7 @@ impl Module { 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 = Arc::get_mut(&mut module.inner).unwrap(); - Arc::get_mut(inner.compiled.module_mut()).unwrap().name = Some(name.to_string()); + Arc::get_mut(&mut inner.compiled).unwrap().name = Some(name.to_string()); Ok(module) } @@ -318,14 +318,14 @@ impl Module { Ok(Module { inner: Arc::new(ModuleInner { store: store.clone(), - compiled, + compiled: Arc::new(compiled), frame_info_registration: Mutex::new(None), jit_code_registration, }), }) } - pub(crate) fn compiled_module(&self) -> &CompiledModule { + pub(crate) fn compiled_module(&self) -> &Arc { &self.inner.compiled } @@ -354,7 +354,7 @@ impl Module { /// # } /// ``` pub fn name(&self) -> Option<&str> { - self.inner.compiled.module().name.as_deref() + self.inner.compiled.name.as_deref() } /// Returns the list of imports that this [`Module`] has and must be @@ -496,7 +496,7 @@ impl Module { if let Some(info) = &*info { return info.clone(); } - let ret = super::frame_info::register(&self.inner.compiled).map(Arc::new); + let ret = super::frame_info::register(self.inner.compiled.clone()).map(Arc::new); *info = Some(ret.clone()); return ret; } diff --git a/crates/wasmtime/src/trampoline/create_handle.rs b/crates/wasmtime/src/trampoline/create_handle.rs index 3e212e54e111..f014659900a5 100644 --- a/crates/wasmtime/src/trampoline/create_handle.rs +++ b/crates/wasmtime/src/trampoline/create_handle.rs @@ -37,13 +37,12 @@ pub(crate) fn create_handle( unsafe { let handle = InstanceHandle::new( - Arc::new(module), + Arc::new(Box::new(module)), finished_functions.into_boxed_slice(), trampolines, imports, store.memory_creator(), signatures.into_boxed_slice(), - None, state, store.compiler().interrupts().clone(), )?; From 5a3a1422bf26ca7ab222539cbbb072f4f09a2bc5 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 26 May 2020 12:55:52 -0500 Subject: [PATCH 04/35] Threads example --- crates/wasmtime/src/module.rs | 24 +++++++++++- examples/threads.rs | 73 +++++++++++++++++++++++++++++++++++ examples/threads.wat | 5 +++ 3 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 examples/threads.rs create mode 100644 examples/threads.wat diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs index ba17dcd08e25..4849bdba23b9 100644 --- a/crates/wasmtime/src/module.rs +++ b/crates/wasmtime/src/module.rs @@ -78,10 +78,13 @@ pub struct Module { inner: Arc, } +unsafe impl Sync for Module {} +unsafe impl Send for Module {} + struct ModuleInner { store: Store, compiled: Arc, - frame_info_registration: Mutex>>>, + frame_info_registration: Arc>>>>, #[allow(dead_code)] jit_code_registration: JitCodeRegistration, } @@ -319,7 +322,7 @@ impl Module { inner: Arc::new(ModuleInner { store: store.clone(), compiled: Arc::new(compiled), - frame_info_registration: Mutex::new(None), + frame_info_registration: Arc::new(Mutex::new(None)), jit_code_registration, }), }) @@ -329,6 +332,23 @@ impl Module { &self.inner.compiled } + /// Returns `Module` that is usable in a different `Store`. + pub fn clone_into(&self, store: &Store) -> Result { + let compiled = self.inner.compiled.clone(); + let frame_info_registration = self.inner.frame_info_registration.clone(); + + let jit_code_registration = store.register_jit_code(compiled.jit_code_ranges()); + + Ok(Module { + inner: Arc::new(ModuleInner { + store: store.clone(), + compiled, + frame_info_registration, + jit_code_registration, + }), + }) + } + /// Returns identifier/name that this [`Module`] has. This name /// is used in traps/backtrace details. /// diff --git a/examples/threads.rs b/examples/threads.rs new file mode 100644 index 000000000000..77f6950db03e --- /dev/null +++ b/examples/threads.rs @@ -0,0 +1,73 @@ +// You can execute this example with `cargo run --example threads` + +use anyhow::{format_err, Result}; +use std::sync::Arc; +use std::thread; +use std::time; +use wasmtime::*; + +const N_THREADS: i32 = 10; +const N_REPS: i32 = 3; + +fn print_message(_: Caller<'_>, args: &[Val], _: &mut [Val]) -> Result<(), Trap> { + println!("> Thread {} is running", args[0].unwrap_i32()); + Ok(()) +} + +fn run(engine: &Engine, module: &Module, id: i32) -> Result<()> { + let store = Store::new(&engine); + let module = module.clone_into(&store)?; + + // Create external print functions. + println!("Creating callback..."); + let callback_type = FuncType::new(Box::new([ValType::I32]), Box::new([])); + let callback_func = Func::new(&store, callback_type, print_message); + + let id_type = GlobalType::new(ValType::I32, Mutability::Const); + let id_global = Global::new(&store, id_type, Val::I32(id))?; + + // Instantiate. + println!("Instantiating module..."); + let instance = Instance::new(&module, &[callback_func.into(), id_global.into()])?; + + // Extract exports. + println!("Extracting export..."); + let g = instance + .get_func("run") + .ok_or(format_err!("failed to find export `eun`"))?; + + for _ in 0..N_REPS { + thread::sleep(time::Duration::from_millis(100)); + // Call `$run`. + drop(g.call(&[])?); + } + + Ok(()) +} + +fn main() -> Result<()> { + println!("Initializing..."); + let engine = Arc::new(Engine::default()); + let store = Store::new(&engine); + + // Compile. + println!("Compiling module..."); + let module = Module::from_file(&store, "examples/threads.wat")?; + + let mut children = Vec::new(); + for id in 0..N_THREADS { + let engine = engine.clone(); + let module = module.clone(); + children.push(thread::spawn(move || { + run(&engine, &module, id).expect("Success"); + })); + } + + for (i, child) in children.into_iter().enumerate() { + if let Err(_) = child.join() { + println!("Thread #{} errors", i); + } + } + + Ok(()) +} diff --git a/examples/threads.wat b/examples/threads.wat new file mode 100644 index 000000000000..228f99f2b564 --- /dev/null +++ b/examples/threads.wat @@ -0,0 +1,5 @@ +(module + (func $message (import "" "hello") (param i32)) + (global $id (import "" "id") i32) + (func (export "run") (call $message (global.get $id))) +) From 9b08221bfc4250ede8c3605912c50a82be3b217a Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 26 May 2020 14:08:07 -0500 Subject: [PATCH 05/35] rm interrupts from Compiler --- crates/jit/src/compiler.rs | 12 ++---------- crates/jit/src/instantiate.rs | 10 +++------- crates/wasmtime/src/instance.rs | 2 ++ crates/wasmtime/src/module.rs | 2 +- crates/wasmtime/src/runtime.rs | 12 +++++++----- crates/wasmtime/src/trampoline/create_handle.rs | 2 +- 6 files changed, 16 insertions(+), 24 deletions(-) diff --git a/crates/jit/src/compiler.rs b/crates/jit/src/compiler.rs index 3520127e67b8..c88161cc5db6 100644 --- a/crates/jit/src/compiler.rs +++ b/crates/jit/src/compiler.rs @@ -9,7 +9,6 @@ use cranelift_codegen::Context; use cranelift_codegen::{binemit, ir}; use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; use std::collections::HashMap; -use std::sync::Arc; use wasmtime_debug::{emit_debugsections_image, DebugInfoData}; use wasmtime_environ::entity::{EntityRef, PrimaryMap}; use wasmtime_environ::isa::{TargetFrontendConfig, TargetIsa}; @@ -19,7 +18,7 @@ use wasmtime_environ::{ ModuleMemoryOffset, ModuleTranslation, ModuleVmctxInfo, Relocation, RelocationTarget, Relocations, Traps, Tunables, VMOffsets, }; -use wasmtime_runtime::{InstantiationError, VMFunctionBody, VMInterrupts, VMTrampoline}; +use wasmtime_runtime::{InstantiationError, VMFunctionBody, VMTrampoline}; /// Select which kind of compilation to use. #[derive(Copy, Clone, Debug)] @@ -48,7 +47,6 @@ pub struct Compiler { strategy: CompilationStrategy, cache_config: CacheConfig, tunables: Tunables, - interrupts: Arc, } impl Compiler { @@ -64,7 +62,6 @@ impl Compiler { strategy, cache_config, tunables, - interrupts: Arc::new(VMInterrupts::default()), } } } @@ -98,14 +95,9 @@ impl Compiler { &self.tunables } - /// Return the handle by which to interrupt instances - pub fn interrupts(&self) -> &Arc { - &self.interrupts - } - /// Compile the given function bodies. pub(crate) fn compile<'data>( - &mut self, + &self, translation: &ModuleTranslation, debug_data: Option, ) -> Result { diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs index 9ff8a38444f2..2680b1630682 100644 --- a/crates/jit/src/instantiate.rs +++ b/crates/jit/src/instantiate.rs @@ -65,7 +65,7 @@ struct RawCompiledModule<'data> { impl<'data> RawCompiledModule<'data> { /// Create a new `RawCompiledModule` by compiling the wasm module in `data` and instatiating it. fn new( - compiler: &mut Compiler, + compiler: &Compiler, data: &'data [u8], profiler: &dyn ProfilingAgent, ) -> Result { @@ -129,7 +129,6 @@ pub struct CompiledModule { dbg_jit_registration: Option, traps: Traps, address_transform: ModuleAddressMap, - interrupts: Arc, } impl std::ops::Deref for CompiledModule { @@ -151,7 +150,7 @@ unsafe impl Sync for CompiledModule {} impl CompiledModule { /// Compile a data buffer into a `CompiledModule`, which may then be instantiated. pub fn new<'data>( - compiler: &mut Compiler, + compiler: &Compiler, data: &'data [u8], profiler: &dyn ProfilingAgent, ) -> Result { @@ -170,7 +169,6 @@ impl CompiledModule { raw.dbg_jit_registration, raw.traps, raw.address_transform, - compiler.interrupts().clone(), )) } @@ -184,7 +182,6 @@ impl CompiledModule { dbg_jit_registration: Option, traps: Traps, address_transform: ModuleAddressMap, - interrupts: Arc, ) -> Self { Self { code_memory, @@ -195,7 +192,6 @@ impl CompiledModule { dbg_jit_registration, traps, address_transform, - interrupts, } } @@ -213,6 +209,7 @@ impl CompiledModule { resolver: &mut dyn Resolver, signature_registry: &SignatureRegistry, mem_creator: Option<&dyn RuntimeMemoryCreator>, + interrupts: Arc, host_state: Box, ) -> Result { // Compute indices into the shared signature table. @@ -231,7 +228,6 @@ impl CompiledModule { } let finished_functions = module.finished_functions.clone(); - let interrupts = module.interrupts.clone(); let imports = resolve_imports(&module, signature_registry, resolver)?; InstanceHandle::new( diff --git a/crates/wasmtime/src/instance.rs b/crates/wasmtime/src/instance.rs index 13a704d0720a..e84adf7bdf15 100644 --- a/crates/wasmtime/src/instance.rs +++ b/crates/wasmtime/src/instance.rs @@ -30,11 +30,13 @@ fn instantiate( let mut resolver = SimpleResolver { imports }; unsafe { let config = store.engine().config(); + let interrupts = store.interrupts().clone(); let instance = CompiledModule::instantiate( compiled_module.clone(), &mut resolver, sig_registry, config.memory_creator.as_ref().map(|a| a as _), + interrupts, host, )?; diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs index 4849bdba23b9..17ba2b7e5438 100644 --- a/crates/wasmtime/src/module.rs +++ b/crates/wasmtime/src/module.rs @@ -311,7 +311,7 @@ impl Module { unsafe fn compile(store: &Store, binary: &[u8]) -> Result { let compiled = CompiledModule::new( - &mut store.compiler_mut(), + &store.compiler(), binary, &*store.engine().config().profiler, )?; diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs index 670534c5b965..23a2b7d3f84a 100644 --- a/crates/wasmtime/src/runtime.rs +++ b/crates/wasmtime/src/runtime.rs @@ -732,6 +732,7 @@ pub struct Store { pub(crate) struct StoreInner { engine: Engine, compiler: RefCell, + interrupts: Arc, signatures: RefCell, instances: RefCell>, signal_handler: RefCell>>>, @@ -771,6 +772,7 @@ impl Store { inner: Rc::new(StoreInner { engine: engine.clone(), compiler: RefCell::new(compiler), + interrupts: Arc::new(Default::default()), signatures: RefCell::new(SignatureRegistry::new()), instances: RefCell::new(Vec::new()), signal_handler: RefCell::new(None), @@ -797,10 +799,6 @@ impl Store { self.inner.compiler.borrow() } - pub(crate) fn compiler_mut(&self) -> std::cell::RefMut<'_, Compiler> { - self.inner.compiler.borrow_mut() - } - pub(crate) fn signatures(&self) -> std::cell::Ref<'_, SignatureRegistry> { self.inner.signatures.borrow() } @@ -867,6 +865,10 @@ impl Store { self.inner.signal_handler.borrow_mut() } + pub(crate) fn interrupts(&self) -> &Arc { + &self.inner.interrupts + } + /// Returns whether the stores `a` and `b` refer to the same underlying /// `Store`. /// @@ -961,7 +963,7 @@ impl Store { pub fn interrupt_handle(&self) -> Result { if self.engine().config.tunables.interruptable { Ok(InterruptHandle { - interrupts: self.compiler().interrupts().clone(), + interrupts: self.interrupts().clone(), }) } else { bail!("interrupts aren't enabled for this `Store`") diff --git a/crates/wasmtime/src/trampoline/create_handle.rs b/crates/wasmtime/src/trampoline/create_handle.rs index f014659900a5..73993f1eb184 100644 --- a/crates/wasmtime/src/trampoline/create_handle.rs +++ b/crates/wasmtime/src/trampoline/create_handle.rs @@ -44,7 +44,7 @@ pub(crate) fn create_handle( store.memory_creator(), signatures.into_boxed_slice(), state, - store.compiler().interrupts().clone(), + store.interrupts().clone(), )?; Ok(store.add_instance(handle)) } From 45717c39734762d667665f1dc072f7c076bc54b2 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 26 May 2020 14:41:25 -0500 Subject: [PATCH 06/35] rm Sync+Send from Module --- crates/wasmtime/src/lib.rs | 2 +- crates/wasmtime/src/module.rs | 53 +++++++++++++++++++++++------------ examples/threads.rs | 8 +++--- 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/crates/wasmtime/src/lib.rs b/crates/wasmtime/src/lib.rs index e08fbb15f990..5449e93682fa 100644 --- a/crates/wasmtime/src/lib.rs +++ b/crates/wasmtime/src/lib.rs @@ -28,7 +28,7 @@ pub use crate::frame_info::FrameInfo; pub use crate::func::*; pub use crate::instance::Instance; pub use crate::linker::*; -pub use crate::module::Module; +pub use crate::module::{Module, SendableModule}; pub use crate::r#ref::{ExternRef, HostRef}; pub use crate::runtime::*; pub use crate::trap::Trap; diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs index 17ba2b7e5438..6264c32391af 100644 --- a/crates/wasmtime/src/module.rs +++ b/crates/wasmtime/src/module.rs @@ -78,9 +78,6 @@ pub struct Module { inner: Arc, } -unsafe impl Sync for Module {} -unsafe impl Send for Module {} - struct ModuleInner { store: Store, compiled: Arc, @@ -332,21 +329,12 @@ impl Module { &self.inner.compiled } - /// Returns `Module` that is usable in a different `Store`. - pub fn clone_into(&self, store: &Store) -> Result { - let compiled = self.inner.compiled.clone(); - let frame_info_registration = self.inner.frame_info_registration.clone(); - - let jit_code_registration = store.register_jit_code(compiled.jit_code_ranges()); - - Ok(Module { - inner: Arc::new(ModuleInner { - store: store.clone(), - compiled, - frame_info_registration, - jit_code_registration, - }), - }) + /// Returns the module that can be used in different thread. + pub fn share(&self) -> SendableModule { + SendableModule { + compiled: self.inner.compiled.clone(), + frame_info_registration: self.inner.frame_info_registration.clone(), + } } /// Returns identifier/name that this [`Module`] has. This name @@ -521,3 +509,32 @@ impl Module { return ret; } } + +/// Shareable portion of the `Module` that can be instantiated in +/// deferent `Store`. +#[derive(Clone)] +pub struct SendableModule { + compiled: Arc, + frame_info_registration: Arc>>>>, +} + +unsafe impl Send for SendableModule {} + +impl SendableModule { + /// Returns `Module` that is belong to diffrent `Store`. + pub fn place_into(self, store: &Store) -> Module { + let compiled = self.compiled; + let frame_info_registration = self.frame_info_registration; + + let jit_code_registration = store.register_jit_code(compiled.jit_code_ranges()); + + Module { + inner: Arc::new(ModuleInner { + store: store.clone(), + compiled, + frame_info_registration, + jit_code_registration, + }), + } + } +} diff --git a/examples/threads.rs b/examples/threads.rs index 77f6950db03e..5566f7fd4f79 100644 --- a/examples/threads.rs +++ b/examples/threads.rs @@ -14,9 +14,9 @@ fn print_message(_: Caller<'_>, args: &[Val], _: &mut [Val]) -> Result<(), Trap> Ok(()) } -fn run(engine: &Engine, module: &Module, id: i32) -> Result<()> { +fn run(engine: &Engine, module: SendableModule, id: i32) -> Result<()> { let store = Store::new(&engine); - let module = module.clone_into(&store)?; + let module = module.place_into(&store); // Create external print functions. println!("Creating callback..."); @@ -57,9 +57,9 @@ fn main() -> Result<()> { let mut children = Vec::new(); for id in 0..N_THREADS { let engine = engine.clone(); - let module = module.clone(); + let module = module.share(); children.push(thread::spawn(move || { - run(&engine, &module, id).expect("Success"); + run(&engine, module, id).expect("Success"); })); } From d47371fd8aa5ec358d333f06ef0164fc40b6078e Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 26 May 2020 16:21:34 -0500 Subject: [PATCH 07/35] c api --- crates/c-api/src/module.rs | 41 ++++++++- examples/threads.c | 175 +++++++++++++++++++++++++++++++++++++ 2 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 examples/threads.c diff --git a/crates/c-api/src/module.rs b/crates/c-api/src/module.rs index 23c5eae36489..bc88d1d70808 100644 --- a/crates/c-api/src/module.rs +++ b/crates/c-api/src/module.rs @@ -2,7 +2,7 @@ use crate::{handle_result, wasmtime_error_t}; use crate::{wasm_byte_vec_t, wasm_exporttype_vec_t, wasm_importtype_vec_t}; use crate::{wasm_exporttype_t, wasm_importtype_t, wasm_store_t}; use std::ptr; -use wasmtime::{HostRef, Module}; +use wasmtime::{HostRef, Module, SendableModule}; #[repr(C)] #[derive(Clone)] @@ -20,6 +20,14 @@ impl wasm_module_t { } } +#[repr(C)] +#[derive(Clone)] +pub struct wasm_shared_module_t { + module: SendableModule, +} + +wasmtime_c_api_macros::declare_own!(wasm_shared_module_t); + #[no_mangle] pub extern "C" fn wasm_module_new( store: &wasm_store_t, @@ -95,3 +103,34 @@ pub extern "C" fn wasm_module_imports(module: &wasm_module_t, out: &mut wasm_imp .collect::>(); out.set_buffer(buffer); } + +#[no_mangle] +pub extern "C" fn wasm_module_share(module: &wasm_module_t) -> Box { + Box::new(wasm_shared_module_t { + module: module.module.borrow().share(), + }) +} + +#[no_mangle] +pub extern "C" fn wasm_module_obtain( + store: &wasm_store_t, + shared_module: &wasm_shared_module_t, +) -> Box { + let module = shared_module + .module + .clone() + .place_into(&store.store.borrow()); + let imports = module + .imports() + .map(|i| wasm_importtype_t::new(i.module().to_owned(), i.name().to_owned(), i.ty())) + .collect::>(); + let exports = module + .exports() + .map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty())) + .collect::>(); + Box::new(wasm_module_t { + module: HostRef::new(module), + imports, + exports, + }) +} diff --git a/examples/threads.c b/examples/threads.c new file mode 100644 index 000000000000..9d854605bd31 --- /dev/null +++ b/examples/threads.c @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define own + +static void exit_with_error(const char *message, wasmtime_error_t *error, wasm_trap_t *trap); + +const int N_THREADS = 10; +const int N_REPS = 3; + +// A function to be called from Wasm code. +own wasm_trap_t* callback(const wasm_val_t args[], wasm_val_t results[]) { + assert(args[0].kind == WASM_I32); + printf("> Thread %d running\n", args[0].of.i32); + return NULL; +} + + +typedef struct { + wasm_engine_t* engine; + wasm_shared_module_t* module; + int id; +} thread_args; + +void* run(void* args_abs) { + thread_args* args = (thread_args*)args_abs; + + // Rereate store and module. + own wasm_store_t* store = wasm_store_new(args->engine); + own wasm_module_t* module = wasm_module_obtain(store, args->module); + + // Run the example N times. + for (int i = 0; i < N_REPS; ++i) { + usleep(100000); + + // Create imports. + own wasm_functype_t* func_type = wasm_functype_new_1_0(wasm_valtype_new_i32()); + own wasm_func_t* func = wasm_func_new(store, func_type, callback); + wasm_functype_delete(func_type); + + wasm_val_t val = {.kind = WASM_I32, .of = {.i32 = (int32_t)args->id}}; + own wasm_globaltype_t* global_type = + wasm_globaltype_new(wasm_valtype_new_i32(), WASM_CONST); + own wasm_global_t* global = wasm_global_new(store, global_type, &val); + wasm_globaltype_delete(global_type); + + // Instantiate. + const wasm_extern_t* imports[] = { + wasm_func_as_extern(func), wasm_global_as_extern(global), + }; + own wasm_instance_t* instance = + wasm_instance_new(store, module, imports, NULL); + if (!instance) { + printf("> Error instantiating module!\n"); + return NULL; + } + + wasm_func_delete(func); + wasm_global_delete(global); + + // Extract export. + own wasm_extern_vec_t exports; + wasm_instance_exports(instance, &exports); + if (exports.size == 0) { + printf("> Error accessing exports!\n"); + return NULL; + } + const wasm_func_t *run_func = wasm_extern_as_func(exports.data[0]); + if (run_func == NULL) { + printf("> Error accessing export!\n"); + return NULL; + } + + wasm_instance_delete(instance); + + // Call. + if (wasm_func_call(run_func, NULL, NULL)) { + printf("> Error calling function!\n"); + return NULL; + } + + wasm_extern_vec_delete(&exports); + } + + wasm_module_delete(module); + wasm_store_delete(store); + + free(args_abs); + + return NULL; +} + +int main(int argc, const char *argv[]) { + // Initialize. + wasm_engine_t* engine = wasm_engine_new(); + + // Load our input file to parse it next + FILE* file = fopen("examples/threads.wat", "r"); + if (!file) { + printf("> Error loading file!\n"); + return 1; + } + fseek(file, 0L, SEEK_END); + size_t file_size = ftell(file); + fseek(file, 0L, SEEK_SET); + wasm_byte_vec_t wat; + wasm_byte_vec_new_uninitialized(&wat, file_size); + if (fread(wat.data, file_size, 1, file) != 1) { + printf("> Error loading module!\n"); + return 1; + } + fclose(file); + + // Parse the wat into the binary wasm format + wasm_byte_vec_t binary; + wasmtime_error_t *error = wasmtime_wat2wasm(&wat, &binary); + if (error != NULL) + exit_with_error("failed to parse wat", error, NULL); + wasm_byte_vec_delete(&wat); + + // Compile and share. + own wasm_store_t* store = wasm_store_new(engine); + own wasm_module_t* module = wasm_module_new(store, &binary); + if (!module) { + printf("> Error compiling module!\n"); + return 1; + } + + wasm_byte_vec_delete(&binary); + + own wasm_shared_module_t* shared = wasm_module_share(module); + + wasm_module_delete(module); + wasm_store_delete(store); + + // Spawn threads. + pthread_t threads[N_THREADS]; + for (int i = 0; i < N_THREADS; i++) { + thread_args* args = malloc(sizeof(thread_args)); + args->id = i; + args->engine = engine; + args->module = shared; + printf("Initializing thread %d...\n", i); + pthread_create(&threads[i], NULL, &run, args); + } + + for (int i = 0; i < N_THREADS; i++) { + printf("Waiting for thread: %d\n", i); + pthread_join(threads[i], NULL); + } + + wasm_shared_module_delete(shared); + wasm_engine_delete(engine); + + return 0; +} + +static void exit_with_error(const char *message, wasmtime_error_t *error, wasm_trap_t *trap) { + fprintf(stderr, "error: %s\n", message); + wasm_byte_vec_t error_message; + if (error != NULL) { + wasmtime_error_message(error, &error_message); + } else { + wasm_trap_message(trap, &error_message); + } + fprintf(stderr, "%.*s\n", (int) error_message.size, error_message.data); + wasm_byte_vec_delete(&error_message); + exit(1); +} From d4e4ade181003042a0fe5bdea93363be2787e5b7 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 26 May 2020 16:30:11 -0500 Subject: [PATCH 08/35] rn module_ref() --- crates/jit/src/instantiate.rs | 2 +- crates/runtime/src/debug_builtins.rs | 2 +- crates/runtime/src/instance.rs | 21 +++++++++------------ crates/wasmtime/src/instance.rs | 6 +++--- crates/wasmtime/src/module.rs | 6 +++--- 5 files changed, 17 insertions(+), 20 deletions(-) diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs index 2680b1630682..e8ffc7550b7b 100644 --- a/crates/jit/src/instantiate.rs +++ b/crates/jit/src/instantiate.rs @@ -254,7 +254,7 @@ impl CompiledModule { } /// Return a reference to a module. - pub fn module_ref(&self) -> &Module { + pub fn module(&self) -> &Module { &self.module } diff --git a/crates/runtime/src/debug_builtins.rs b/crates/runtime/src/debug_builtins.rs index 57e7b16b7cac..3a6cfc8b81c2 100644 --- a/crates/runtime/src/debug_builtins.rs +++ b/crates/runtime/src/debug_builtins.rs @@ -16,7 +16,7 @@ pub unsafe extern "C" fn resolve_vmctx_memory_ptr(p: *const u32) -> *const u8 { ); let handle = InstanceHandle::from_vmctx(VMCTX_AND_MEMORY.0); assert!( - VMCTX_AND_MEMORY.1 < handle.module_ref().local.memory_plans.len(), + VMCTX_AND_MEMORY.1 < handle.module().local.memory_plans.len(), "memory index for debugger is out of bounds" ); let index = MemoryIndex::new(VMCTX_AND_MEMORY.1); diff --git a/crates/runtime/src/instance.rs b/crates/runtime/src/instance.rs index ba5600a296f7..61e0a6fbb771 100644 --- a/crates/runtime/src/instance.rs +++ b/crates/runtime/src/instance.rs @@ -92,7 +92,7 @@ impl Instance { unsafe { *self.signature_ids_ptr().add(index) } } - pub(crate) fn module_ref(&self) -> &Module { + pub(crate) fn module(&self) -> &Module { &self.module } @@ -782,10 +782,8 @@ impl InstanceHandle { host_state: Box, interrupts: Arc, ) -> Result { - let module_ref = &*module; - let tables = create_tables(module_ref); - let memories = - create_memories(module_ref, mem_creator.unwrap_or(&DefaultMemoryCreator {}))?; + let tables = create_tables(&module); + let memories = create_memories(&module, mem_creator.unwrap_or(&DefaultMemoryCreator {}))?; let vmctx_tables = tables .values() @@ -799,11 +797,11 @@ impl InstanceHandle { .collect::>() .into_boxed_slice(); - let vmctx_globals = create_globals(module_ref); + let vmctx_globals = create_globals(&module); let offsets = VMOffsets::new(mem::size_of::<*const u8>() as u8, &module.local); - let passive_data = RefCell::new(module_ref.passive_data.clone()); + let passive_data = RefCell::new(module.passive_data.clone()); let handle = { let instance = Instance { @@ -934,8 +932,8 @@ impl InstanceHandle { } /// Return a reference to a module. - pub fn module_ref(&self) -> &Module { - self.instance().module_ref() + pub fn module(&self) -> &Module { + self.instance().module() } /// Lookup an export with the given name. @@ -1053,7 +1051,7 @@ impl InstanceHandle { fn check_table_init_bounds(instance: &Instance) -> Result<(), InstantiationError> { let module = Arc::clone(&instance.module); - for init in &module.as_ref().table_elements { + for init in &module.table_elements { let start = get_table_init_start(init, instance); let table = instance.get_table(init.table_index); @@ -1157,7 +1155,7 @@ fn get_table_init_start(init: &TableElements, instance: &Instance) -> usize { /// Initialize the table memory from the provided initializers. fn initialize_tables(instance: &Instance) -> Result<(), InstantiationError> { - let module = instance.module.as_ref(); + let module = &instance.module; for init in &module.table_elements { let start = get_table_init_start(init, instance); let table = instance.get_table(init.table_index); @@ -1195,7 +1193,6 @@ fn initialize_passive_elements(instance: &Instance) { passive_elements.extend( instance .module - .as_ref() .passive_elements .iter() .filter(|(_, segments)| !segments.is_empty()) diff --git a/crates/wasmtime/src/instance.rs b/crates/wasmtime/src/instance.rs index 3c38fce4ad1c..3eaa04b8deba 100644 --- a/crates/wasmtime/src/instance.rs +++ b/crates/wasmtime/src/instance.rs @@ -35,11 +35,11 @@ fn instantiate( } } - if imports.len() != compiled_module.module_ref().imports.len() { + if imports.len() != compiled_module.module().imports.len() { bail!( "wrong number of imports provided, {} != {}", imports.len(), - compiled_module.module_ref().imports.len() + compiled_module.module().imports.len() ); } @@ -79,7 +79,7 @@ fn instantiate( instance }; - let start_func = instance.handle.module_ref().start_func; + let start_func = instance.handle.module().start_func; // If a start function is present, invoke it. Make sure we use all the // trap-handling configuration in `store` as well. diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs index 36dcc23a1d50..d9180f96def5 100644 --- a/crates/wasmtime/src/module.rs +++ b/crates/wasmtime/src/module.rs @@ -417,7 +417,7 @@ impl Module { pub fn imports<'module>( &'module self, ) -> impl ExactSizeIterator> + 'module { - let module = self.inner.compiled.module_ref(); + let module = self.inner.compiled.module(); module .imports .iter() @@ -484,7 +484,7 @@ impl Module { pub fn exports<'module>( &'module self, ) -> impl ExactSizeIterator> + 'module { - let module = self.inner.compiled.module_ref(); + let module = self.inner.compiled.module(); module.exports.iter().map(move |(name, entity_index)| { let r#type = EntityType::new(entity_index, module); ExportType::new(name, r#type) @@ -535,7 +535,7 @@ impl Module { /// # } /// ``` pub fn get_export<'module>(&'module self, name: &'module str) -> Option { - let module = self.inner.compiled.module_ref(); + let module = self.inner.compiled.module(); let entity_index = module.exports.get(name)?; Some(EntityType::new(entity_index, module).extern_type()) } From a2b432bfed79a8ac20c50767fd177c55af3cfcf2 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 26 May 2020 17:13:08 -0500 Subject: [PATCH 09/35] small fixes --- crates/wasmtime/src/instance.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/crates/wasmtime/src/instance.rs b/crates/wasmtime/src/instance.rs index 3eaa04b8deba..1aa9475b3bf8 100644 --- a/crates/wasmtime/src/instance.rs +++ b/crates/wasmtime/src/instance.rs @@ -6,7 +6,7 @@ use std::mem; use std::sync::Arc; use wasmtime_environ::EntityIndex; use wasmtime_jit::{CompiledModule, Resolver}; -use wasmtime_runtime::{InstantiationError, SignatureRegistry, VMContext, VMFunctionBody}; +use wasmtime_runtime::{InstantiationError, VMContext, VMFunctionBody}; struct SimpleResolver<'a> { imports: &'a [Extern], @@ -22,9 +22,8 @@ impl Resolver for SimpleResolver<'_> { fn instantiate( store: &Store, - compiled_module: Arc, + compiled_module: &Arc, imports: &[Extern], - sig_registry: &SignatureRegistry, host: Box, ) -> Result { // For now we have a restriction that the `Store` that we're working @@ -46,13 +45,12 @@ fn instantiate( let mut resolver = SimpleResolver { imports }; let config = store.engine().config(); let instance = unsafe { - let interrupts = store.interrupts().clone(); let instance = CompiledModule::instantiate( compiled_module.clone(), &mut resolver, - sig_registry, + &store.signatures(), config.memory_creator.as_ref().map(|a| a as _), - interrupts, + store.interrupts().clone(), host, )?; @@ -182,13 +180,11 @@ impl Instance { /// [issue]: https://github.com/bytecodealliance/wasmtime/issues/727 /// [`ExternType`]: crate::ExternType pub fn new(module: &Module, imports: &[Extern]) -> Result { - let store = module.store(); let info = module.register_frame_info(); let handle = instantiate( - store, - module.compiled_module().clone(), + module.store(), + module.compiled_module(), imports, - &store.signatures(), Box::new(info), )?; From ede93def6bc116b7379ee06fd8a41b6aec629b24 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 26 May 2020 17:23:04 -0500 Subject: [PATCH 10/35] rm Send+Sync from CompiledModule --- crates/jit/src/instantiate.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs index e8ffc7550b7b..f0ca95c2930d 100644 --- a/crates/jit/src/instantiate.rs +++ b/crates/jit/src/instantiate.rs @@ -118,11 +118,16 @@ impl<'data> RawCompiledModule<'data> { } } +struct FinishedFunctions(BoxedSlice); + +unsafe impl Send for FinishedFunctions {} +unsafe impl Sync for FinishedFunctions {} + /// A compiled wasm module, ready to be instantiated. pub struct CompiledModule { code_memory: CodeMemory, module: Module, - finished_functions: BoxedSlice, + finished_functions: FinishedFunctions, trampolines: PrimaryMap, data_initializers: Box<[OwnedDataInitializer]>, #[allow(dead_code)] @@ -144,9 +149,6 @@ impl std::ops::DerefMut for CompiledModule { } } -unsafe impl Send for CompiledModule {} -unsafe impl Sync for CompiledModule {} - impl CompiledModule { /// Compile a data buffer into a `CompiledModule`, which may then be instantiated. pub fn new<'data>( @@ -186,7 +188,7 @@ impl CompiledModule { Self { code_memory, module: module, - finished_functions, + finished_functions: FinishedFunctions(finished_functions), trampolines, data_initializers, dbg_jit_registration, @@ -227,7 +229,7 @@ impl CompiledModule { trampolines.insert(signatures[i], trampoline.clone()); } - let finished_functions = module.finished_functions.clone(); + let finished_functions = module.finished_functions.0.clone(); let imports = resolve_imports(&module, signature_registry, resolver)?; InstanceHandle::new( @@ -260,7 +262,7 @@ impl CompiledModule { /// Returns the map of all finished JIT functions compiled for this module pub fn finished_functions(&self) -> &BoxedSlice { - &self.finished_functions + &self.finished_functions.0 } /// Returns the a map for all traps in this module. From 2e73c4a98a0ab3a245b2bf3ef8ce914a3dc5f9f0 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 26 May 2020 17:50:28 -0500 Subject: [PATCH 11/35] rm RawCompiledModule --- crates/jit/src/instantiate.rs | 138 +++++++++++----------------------- 1 file changed, 44 insertions(+), 94 deletions(-) diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs index f0ca95c2930d..db642834ca10 100644 --- a/crates/jit/src/instantiate.rs +++ b/crates/jit/src/instantiate.rs @@ -49,22 +49,40 @@ pub enum SetupError { DebugInfo(#[from] anyhow::Error), } -/// This is similar to `CompiledModule`, but references the data initializers -/// from the wasm buffer rather than holding its own copy. -struct RawCompiledModule<'data> { +struct FinishedFunctions(BoxedSlice); + +unsafe impl Send for FinishedFunctions {} +unsafe impl Sync for FinishedFunctions {} + +/// A compiled wasm module, ready to be instantiated. +pub struct CompiledModule { code_memory: CodeMemory, module: Module, - finished_functions: BoxedSlice, + finished_functions: FinishedFunctions, trampolines: PrimaryMap, - data_initializers: Box<[DataInitializer<'data>]>, + data_initializers: Box<[OwnedDataInitializer]>, + #[allow(dead_code)] dbg_jit_registration: Option, traps: Traps, address_transform: ModuleAddressMap, } -impl<'data> RawCompiledModule<'data> { - /// Create a new `RawCompiledModule` by compiling the wasm module in `data` and instatiating it. - fn new( +impl std::ops::Deref for CompiledModule { + type Target = Module; + fn deref(&self) -> &Self::Target { + &self.module + } +} + +impl std::ops::DerefMut for CompiledModule { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.module + } +} + +impl CompiledModule { + /// Compile a data buffer into a `CompiledModule`, which may then be instantiated. + pub fn new<'data>( compiler: &Compiler, data: &'data [u8], profiler: &dyn ProfilingAgent, @@ -83,15 +101,24 @@ impl<'data> RawCompiledModule<'data> { let compilation = compiler.compile(&translation, debug_data)?; - link_module(&translation.module, &compilation); + let module = translation.module; + + link_module(&module, &compilation); // Make all code compiled thus far executable. let mut code_memory = compilation.code_memory; code_memory.publish(compiler.isa()); + let data_initializers = translation + .data_initializers + .into_iter() + .map(OwnedDataInitializer::new) + .collect::>() + .into_boxed_slice(); + // Initialize profiler and load the wasm module profiler.module_load( - &translation.module, + &module, &compilation.finished_functions, compilation.dbg_image.as_deref(), ); @@ -105,97 +132,20 @@ impl<'data> RawCompiledModule<'data> { None }; + let finished_functions = + FinishedFunctions(compilation.finished_functions.into_boxed_slice()); + Ok(Self { code_memory, - module: translation.module, - finished_functions: compilation.finished_functions.into_boxed_slice(), + module, + finished_functions, trampolines: compilation.trampolines, - data_initializers: translation.data_initializers.into_boxed_slice(), + data_initializers, dbg_jit_registration, traps: compilation.traps, address_transform: compilation.address_transform, }) } -} - -struct FinishedFunctions(BoxedSlice); - -unsafe impl Send for FinishedFunctions {} -unsafe impl Sync for FinishedFunctions {} - -/// A compiled wasm module, ready to be instantiated. -pub struct CompiledModule { - code_memory: CodeMemory, - module: Module, - finished_functions: FinishedFunctions, - trampolines: PrimaryMap, - data_initializers: Box<[OwnedDataInitializer]>, - #[allow(dead_code)] - dbg_jit_registration: Option, - traps: Traps, - address_transform: ModuleAddressMap, -} - -impl std::ops::Deref for CompiledModule { - type Target = Module; - fn deref(&self) -> &Self::Target { - &self.module - } -} - -impl std::ops::DerefMut for CompiledModule { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.module - } -} - -impl CompiledModule { - /// Compile a data buffer into a `CompiledModule`, which may then be instantiated. - pub fn new<'data>( - compiler: &Compiler, - data: &'data [u8], - profiler: &dyn ProfilingAgent, - ) -> Result { - let raw = RawCompiledModule::<'data>::new(compiler, data, profiler)?; - - Ok(Self::from_parts( - raw.code_memory, - raw.module, - raw.finished_functions, - raw.trampolines, - raw.data_initializers - .iter() - .map(OwnedDataInitializer::new) - .collect::>() - .into_boxed_slice(), - raw.dbg_jit_registration, - raw.traps, - raw.address_transform, - )) - } - - /// Construct a `CompiledModule` from component parts. - pub fn from_parts( - code_memory: CodeMemory, - module: Module, - finished_functions: BoxedSlice, - trampolines: PrimaryMap, - data_initializers: Box<[OwnedDataInitializer]>, - dbg_jit_registration: Option, - traps: Traps, - address_transform: ModuleAddressMap, - ) -> Self { - Self { - code_memory, - module: module, - finished_functions: FinishedFunctions(finished_functions), - trampolines, - data_initializers, - dbg_jit_registration, - traps, - address_transform, - } - } /// Crate an `Instance` from this `CompiledModule`. /// @@ -292,7 +242,7 @@ pub struct OwnedDataInitializer { } impl OwnedDataInitializer { - fn new(borrowed: &DataInitializer<'_>) -> Self { + fn new(borrowed: DataInitializer<'_>) -> Self { Self { location: borrowed.location.clone(), data: borrowed.data.to_vec().into_boxed_slice(), From edcf487d7123f79bcd5397d0df6549b281926f80 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 27 May 2020 11:03:21 -0500 Subject: [PATCH 12/35] rm jit_code_registration; win32 test; any --- crates/wasmtime/src/module.rs | 10 +++------- crates/wasmtime/src/runtime.rs | 31 +++---------------------------- examples/threads.c | 9 +++++++++ 3 files changed, 15 insertions(+), 35 deletions(-) diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs index d9180f96def5..f291a80dea13 100644 --- a/crates/wasmtime/src/module.rs +++ b/crates/wasmtime/src/module.rs @@ -1,5 +1,5 @@ use crate::frame_info::GlobalFrameInfoRegistration; -use crate::runtime::{JitCodeRegistration, Store}; +use crate::runtime::Store; use crate::types::{EntityType, ExportType, ExternType, ImportType}; use anyhow::{Error, Result}; use std::path::Path; @@ -82,8 +82,6 @@ struct ModuleInner { store: Store, compiled: Arc, frame_info_registration: Arc>>>>, - #[allow(dead_code)] - jit_code_registration: JitCodeRegistration, } impl Module { @@ -313,14 +311,13 @@ impl Module { &*store.engine().config().profiler, )?; - let jit_code_registration = store.register_jit_code(compiled.jit_code_ranges()); + store.register_jit_code(compiled.jit_code_ranges()); Ok(Module { inner: Arc::new(ModuleInner { store: store.clone(), compiled: Arc::new(compiled), frame_info_registration: Arc::new(Mutex::new(None)), - jit_code_registration, }), }) } @@ -575,14 +572,13 @@ impl SendableModule { let compiled = self.compiled; let frame_info_registration = self.frame_info_registration; - let jit_code_registration = store.register_jit_code(compiled.jit_code_ranges()); + store.register_jit_code(compiled.jit_code_ranges()); Module { inner: Arc::new(ModuleInner { store: store.clone(), compiled, frame_info_registration, - jit_code_registration, }), } } diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs index 23a2b7d3f84a..ccd6c537f48c 100644 --- a/crates/wasmtime/src/runtime.rs +++ b/crates/wasmtime/src/runtime.rs @@ -3,7 +3,6 @@ use crate::trampoline::{MemoryCreatorProxy, StoreInstanceHandle}; use anyhow::{bail, Result}; use std::cell::RefCell; use std::cmp; -use std::collections::HashSet; use std::convert::TryFrom; use std::fmt; use std::path::Path; @@ -739,18 +738,6 @@ pub(crate) struct StoreInner { jit_code_ranges: RefCell>, } -pub(crate) struct JitCodeRegistration { - inner: Rc, - ends: HashSet, -} - -impl Drop for JitCodeRegistration { - fn drop(&mut self) { - let mut jit_code_ranges = self.inner.jit_code_ranges.borrow_mut(); - jit_code_ranges.retain(|(_, end)| self.ends.contains(end)); - } -} - impl Store { /// Creates a new store to be associated with the given [`Engine`]. pub fn new(engine: &Engine) -> Store { @@ -810,24 +797,12 @@ impl Store { .jit_code_ranges .borrow() .iter() - .find(|(start, end)| *start <= addr && addr < *end) - .is_some() + .any(|(start, end)| *start <= addr && addr < *end) } - pub(crate) fn register_jit_code( - &self, - ranges: impl Iterator, - ) -> JitCodeRegistration { - let mut ends = HashSet::new(); + pub(crate) fn register_jit_code(&self, ranges: impl Iterator) { let mut jit_code_ranges = self.inner.jit_code_ranges.borrow_mut(); - for (start, end) in ranges { - jit_code_ranges.push((start, end)); - ends.insert(end); - } - JitCodeRegistration { - inner: self.inner.clone(), - ends, - } + jit_code_ranges.extend(ranges); } pub(crate) unsafe fn add_instance(&self, handle: InstanceHandle) -> StoreInstanceHandle { diff --git a/examples/threads.c b/examples/threads.c index 9d854605bd31..2f210006ef22 100644 --- a/examples/threads.c +++ b/examples/threads.c @@ -1,3 +1,5 @@ +#ifndef _WIN32 + #include #include #include @@ -161,6 +163,13 @@ int main(int argc, const char *argv[]) { return 0; } +#else +// TODO implement example for Windows +int main(int argc, const char *argv[]) { + return 0; +} +#endif // _WIN32 + static void exit_with_error(const char *message, wasmtime_error_t *error, wasm_trap_t *trap) { fprintf(stderr, "error: %s\n", message); wasm_byte_vec_t error_message; From 3f7c2a58a836e5a11c3f7ff429cc550352eb8de1 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 27 May 2020 11:22:18 -0500 Subject: [PATCH 13/35] rm SignatureRegistry lock --- crates/jit/src/instantiate.rs | 2 +- crates/runtime/src/sig_registry.rs | 36 ++++--------------- crates/wasmtime/src/instance.rs | 2 +- crates/wasmtime/src/runtime.rs | 6 +++- .../wasmtime/src/trampoline/create_handle.rs | 2 +- crates/wasmtime/src/trampoline/func.rs | 4 +-- 6 files changed, 16 insertions(+), 36 deletions(-) diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs index db642834ca10..c85a97724f05 100644 --- a/crates/jit/src/instantiate.rs +++ b/crates/jit/src/instantiate.rs @@ -159,7 +159,7 @@ impl CompiledModule { pub unsafe fn instantiate( module: Arc, resolver: &mut dyn Resolver, - signature_registry: &SignatureRegistry, + signature_registry: &mut SignatureRegistry, mem_creator: Option<&dyn RuntimeMemoryCreator>, interrupts: Arc, host_state: Box, diff --git a/crates/runtime/src/sig_registry.rs b/crates/runtime/src/sig_registry.rs index 7ad66149acbf..85aceef8f604 100644 --- a/crates/runtime/src/sig_registry.rs +++ b/crates/runtime/src/sig_registry.rs @@ -5,42 +5,23 @@ use crate::vmcontext::VMSharedSignatureIndex; use more_asserts::{assert_lt, debug_assert_lt}; use std::collections::{hash_map, HashMap}; use std::convert::TryFrom; -use std::sync::RwLock; use wasmtime_environ::ir; /// WebAssembly requires that the caller and callee signatures in an indirect /// call must match. To implement this efficiently, keep a registry of all /// signatures, shared by all instances, so that call sites can just do an /// index comparison. -#[derive(Debug)] -pub struct SignatureRegistry { - // This structure is stored in a `Compiler` and is intended to be shared - // across many instances. Ideally instances can themselves be sent across - // threads, and ideally we can compile across many threads. As a result we - // use interior mutability here with a lock to avoid having callers to - // externally synchronize calls to compilation. - inner: RwLock, -} - #[derive(Debug, Default)] -struct Inner { +pub struct SignatureRegistry { signature2index: HashMap, index2signature: HashMap, } impl SignatureRegistry { - /// Create a new `SignatureRegistry`. - pub fn new() -> Self { - Self { - inner: Default::default(), - } - } - /// Register a signature and return its unique index. - pub fn register(&self, sig: &ir::Signature) -> VMSharedSignatureIndex { - let mut inner = self.inner.write().unwrap(); - let len = inner.signature2index.len(); - match inner.signature2index.entry(sig.clone()) { + pub fn register(&mut self, sig: &ir::Signature) -> VMSharedSignatureIndex { + let len = self.signature2index.len(); + match self.signature2index.entry(sig.clone()) { hash_map::Entry::Occupied(entry) => *entry.get(), hash_map::Entry::Vacant(entry) => { // Keep `signature_hash` len under 2**32 -- VMSharedSignatureIndex::new(std::u32::MAX) @@ -52,7 +33,7 @@ impl SignatureRegistry { ); let sig_id = VMSharedSignatureIndex::new(u32::try_from(len).unwrap()); entry.insert(sig_id); - inner.index2signature.insert(sig_id, sig.clone()); + self.index2signature.insert(sig_id, sig.clone()); sig_id } } @@ -63,11 +44,6 @@ impl SignatureRegistry { /// Note that for this operation to be semantically correct the `idx` must /// have previously come from a call to `register` of this same object. pub fn lookup(&self, idx: VMSharedSignatureIndex) -> Option { - self.inner - .read() - .unwrap() - .index2signature - .get(&idx) - .cloned() + self.index2signature.get(&idx).cloned() } } diff --git a/crates/wasmtime/src/instance.rs b/crates/wasmtime/src/instance.rs index 1aa9475b3bf8..4705d845d08b 100644 --- a/crates/wasmtime/src/instance.rs +++ b/crates/wasmtime/src/instance.rs @@ -48,7 +48,7 @@ fn instantiate( let instance = CompiledModule::instantiate( compiled_module.clone(), &mut resolver, - &store.signatures(), + &mut store.signatures_mut(), config.memory_creator.as_ref().map(|a| a as _), store.interrupts().clone(), host, diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs index ccd6c537f48c..fdc902e51a9e 100644 --- a/crates/wasmtime/src/runtime.rs +++ b/crates/wasmtime/src/runtime.rs @@ -760,7 +760,7 @@ impl Store { engine: engine.clone(), compiler: RefCell::new(compiler), interrupts: Arc::new(Default::default()), - signatures: RefCell::new(SignatureRegistry::new()), + signatures: RefCell::new(Default::default()), instances: RefCell::new(Vec::new()), signal_handler: RefCell::new(None), jit_code_ranges: RefCell::new(Vec::new()), @@ -790,6 +790,10 @@ impl Store { self.inner.signatures.borrow() } + pub(crate) fn signatures_mut(&self) -> std::cell::RefMut<'_, SignatureRegistry> { + self.inner.signatures.borrow_mut() + } + /// Returns whether or not the given address falls within the JIT code /// managed by the compiler pub(crate) fn is_in_jit_code(&self, addr: usize) -> bool { diff --git a/crates/wasmtime/src/trampoline/create_handle.rs b/crates/wasmtime/src/trampoline/create_handle.rs index 73993f1eb184..a1cfc0ceb69f 100644 --- a/crates/wasmtime/src/trampoline/create_handle.rs +++ b/crates/wasmtime/src/trampoline/create_handle.rs @@ -32,7 +32,7 @@ pub(crate) fn create_handle( .local .signatures .values() - .map(|sig| store.signatures().register(sig)) + .map(|sig| store.signatures_mut().register(sig)) .collect::>(); unsafe { diff --git a/crates/wasmtime/src/trampoline/func.rs b/crates/wasmtime/src/trampoline/func.rs index cc97940739e8..ea826d163b9a 100644 --- a/crates/wasmtime/src/trampoline/func.rs +++ b/crates/wasmtime/src/trampoline/func.rs @@ -244,7 +244,7 @@ pub fn create_handle_with_function( mem::size_of::(), )?; assert!(relocations.is_empty()); - let sig_id = store.signatures().register(&sig); + let sig_id = store.signatures_mut().register(&sig); trampolines.insert(sig_id, trampoline); // Next up we wrap everything up into an `InstanceHandle` by publishing our @@ -291,7 +291,7 @@ pub unsafe fn create_handle_with_raw_function( .exports .insert("trampoline".to_string(), EntityIndex::Function(func_id)); finished_functions.push(func); - let sig_id = store.signatures().register(&sig); + let sig_id = store.signatures_mut().register(&sig); trampolines.insert(sig_id, trampoline); create_handle(module, store, finished_functions, trampolines, state) From 1ccdee7f218738efe0ec2731625d901085738465 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 27 May 2020 12:16:42 -0500 Subject: [PATCH 14/35] replace Deref with InstanceContext --- crates/jit/src/instantiate.rs | 23 +++--- crates/runtime/src/instance.rs | 79 ++++++++++--------- crates/runtime/src/lib.rs | 2 +- crates/wasmtime/src/frame_info.rs | 6 +- crates/wasmtime/src/module.rs | 4 +- .../wasmtime/src/trampoline/create_handle.rs | 12 ++- 6 files changed, 69 insertions(+), 57 deletions(-) diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs index c85a97724f05..f6ce9c85003f 100644 --- a/crates/jit/src/instantiate.rs +++ b/crates/jit/src/instantiate.rs @@ -23,8 +23,8 @@ use wasmtime_environ::{ use wasmtime_profiling::ProfilingAgent; use wasmtime_runtime::VMInterrupts; use wasmtime_runtime::{ - GdbJitImageRegistration, InstanceHandle, InstantiationError, RuntimeMemoryCreator, - SignatureRegistry, VMFunctionBody, VMTrampoline, + GdbJitImageRegistration, InstanceContext, InstanceHandle, InstantiationError, + RuntimeMemoryCreator, SignatureRegistry, VMFunctionBody, VMTrampoline, }; /// An error condition while setting up a wasm instance, be it validation, @@ -67,19 +67,12 @@ pub struct CompiledModule { address_transform: ModuleAddressMap, } -impl std::ops::Deref for CompiledModule { - type Target = Module; - fn deref(&self) -> &Self::Target { +impl InstanceContext for CompiledModule { + fn module(&self) -> &Module { &self.module } } -impl std::ops::DerefMut for CompiledModule { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.module - } -} - impl CompiledModule { /// Compile a data buffer into a `CompiledModule`, which may then be instantiated. pub fn new<'data>( @@ -167,6 +160,7 @@ impl CompiledModule { // Compute indices into the shared signature table. let signatures = { module + .module() .local .signatures .values() @@ -181,7 +175,7 @@ impl CompiledModule { let finished_functions = module.finished_functions.0.clone(); - let imports = resolve_imports(&module, signature_registry, resolver)?; + let imports = resolve_imports(module.module(), signature_registry, resolver)?; InstanceHandle::new( module, finished_functions, @@ -210,6 +204,11 @@ impl CompiledModule { &self.module } + /// Return a reference to a module. + pub fn module_mut(&mut self) -> &mut Module { + &mut self.module + } + /// Returns the map of all finished JIT functions compiled for this module pub fn finished_functions(&self) -> &BoxedSlice { &self.finished_functions.0 diff --git a/crates/runtime/src/instance.rs b/crates/runtime/src/instance.rs index 61e0a6fbb771..4b42f6f31f63 100644 --- a/crates/runtime/src/instance.rs +++ b/crates/runtime/src/instance.rs @@ -20,7 +20,6 @@ use std::any::Any; use std::cell::RefCell; use std::collections::HashMap; use std::convert::TryFrom; -use std::ops::Deref; use std::sync::Arc; use std::{mem, ptr, slice}; use thiserror::Error; @@ -31,13 +30,19 @@ use wasmtime_environ::wasm::{ }; use wasmtime_environ::{ir, DataInitializer, EntityIndex, Module, TableElements, VMOffsets}; +/// Trait that exposes required instance resources. +pub trait InstanceContext { + /// Returns Module module. + fn module(&self) -> &Module; +} + /// A WebAssembly instance. /// /// This is repr(C) to ensure that the vmctx field is last. #[repr(C)] pub(crate) struct Instance { /// The `ModuleGrip` this `Instance` was instantiated from. - module: Arc>, + context: Arc, /// Offsets in the `vmctx` region. offsets: VMOffsets, @@ -93,7 +98,7 @@ impl Instance { } pub(crate) fn module(&self) -> &Module { - &self.module + self.context.module() } /// Return a pointer to the `VMSharedSignatureIndex`s. @@ -171,7 +176,7 @@ impl Instance { /// Get a locally defined or imported memory. pub(crate) fn get_memory(&self, index: MemoryIndex) -> VMMemoryDefinition { - if let Some(defined_index) = self.module.local.defined_memory_index(index) { + if let Some(defined_index) = self.module().local.defined_memory_index(index) { self.memory(defined_index) } else { let import = self.imported_memory(index); @@ -248,7 +253,7 @@ impl Instance { /// Lookup an export with the given name. pub fn lookup(&self, field: &str) -> Option { - let export = if let Some(export) = self.module.exports.get(field) { + let export = if let Some(export) = self.module().exports.get(field) { export.clone() } else { return None; @@ -260,9 +265,9 @@ impl Instance { pub fn lookup_by_declaration(&self, export: &EntityIndex) -> Export { match export { EntityIndex::Function(index) => { - let signature = self.signature_id(self.module.local.functions[*index]); + let signature = self.signature_id(self.module().local.functions[*index]); let (address, vmctx) = - if let Some(def_index) = self.module.local.defined_func_index(*index) { + if let Some(def_index) = self.module().local.defined_func_index(*index) { ( self.finished_functions[def_index] as *const _, self.vmctx_ptr(), @@ -280,7 +285,7 @@ impl Instance { } EntityIndex::Table(index) => { let (definition, vmctx) = - if let Some(def_index) = self.module.local.defined_table_index(*index) { + if let Some(def_index) = self.module().local.defined_table_index(*index) { (self.table_ptr(def_index), self.vmctx_ptr()) } else { let import = self.imported_table(*index); @@ -289,13 +294,13 @@ impl Instance { ExportTable { definition, vmctx, - table: self.module.local.table_plans[*index].clone(), + table: self.module().local.table_plans[*index].clone(), } .into() } EntityIndex::Memory(index) => { let (definition, vmctx) = - if let Some(def_index) = self.module.local.defined_memory_index(*index) { + if let Some(def_index) = self.module().local.defined_memory_index(*index) { (self.memory_ptr(def_index), self.vmctx_ptr()) } else { let import = self.imported_memory(*index); @@ -304,19 +309,20 @@ impl Instance { ExportMemory { definition, vmctx, - memory: self.module.local.memory_plans[*index].clone(), + memory: self.module().local.memory_plans[*index].clone(), } .into() } EntityIndex::Global(index) => ExportGlobal { - definition: if let Some(def_index) = self.module.local.defined_global_index(*index) + definition: if let Some(def_index) = + self.module().local.defined_global_index(*index) { self.global_ptr(def_index) } else { self.imported_global(*index).from }, vmctx: self.vmctx_ptr(), - global: self.module.local.globals[*index], + global: self.module().local.globals[*index], } .into(), } @@ -328,7 +334,7 @@ impl Instance { /// are export names, and the values are export declarations which can be /// resolved `lookup_by_declaration`. pub fn exports(&self) -> indexmap::map::Iter { - self.module.exports.iter() + self.module().exports.iter() } /// Return a reference to the custom state attached to this instance. @@ -490,19 +496,19 @@ impl Instance { return VMCallerCheckedAnyfunc::default(); } - let sig = self.module.local.functions[index]; + let sig = self.module().local.functions[index]; let type_index = self.signature_id(sig); - let (func_ptr, vmctx) = if let Some(def_index) = self.module.local.defined_func_index(index) - { - ( - self.finished_functions[def_index] as *const _, - self.vmctx_ptr(), - ) - } else { - let import = self.imported_function(index); - (import.body, import.vmctx) - }; + let (func_ptr, vmctx) = + if let Some(def_index) = self.module().local.defined_func_index(index) { + ( + self.finished_functions[def_index] as *const _, + self.vmctx_ptr(), + ) + } else { + let import = self.imported_function(index); + (import.body, import.vmctx) + }; VMCallerCheckedAnyfunc { func_ptr, type_index, @@ -728,7 +734,7 @@ impl Instance { /// Get a table by index regardless of whether it is locally-defined or an /// imported, foreign table. pub(crate) fn get_table(&self, table_index: TableIndex) -> &Table { - if let Some(defined_table_index) = self.module.local.defined_table_index(table_index) { + if let Some(defined_table_index) = self.module().local.defined_table_index(table_index) { self.get_defined_table(defined_table_index) } else { self.get_foreign_table(table_index) @@ -773,7 +779,7 @@ impl InstanceHandle { /// the `wasmtime` crate API rather than this type since that is vetted for /// safety. pub unsafe fn new( - module: Arc>, + context: Arc, finished_functions: BoxedSlice, trampolines: HashMap, imports: Imports, @@ -782,6 +788,7 @@ impl InstanceHandle { host_state: Box, interrupts: Arc, ) -> Result { + let module = context.module(); let tables = create_tables(&module); let memories = create_memories(&module, mem_creator.unwrap_or(&DefaultMemoryCreator {}))?; @@ -805,7 +812,7 @@ impl InstanceHandle { let handle = { let instance = Instance { - module, + context, offsets, memories, tables, @@ -1050,8 +1057,7 @@ impl InstanceHandle { } fn check_table_init_bounds(instance: &Instance) -> Result<(), InstantiationError> { - let module = Arc::clone(&instance.module); - for init in &module.table_elements { + for init in &instance.module().table_elements { let start = get_table_init_start(init, instance); let table = instance.get_table(init.table_index); @@ -1072,7 +1078,7 @@ fn get_memory_init_start(init: &DataInitializer<'_>, instance: &Instance) -> usi if let Some(base) = init.location.base { let val = unsafe { - if let Some(def_index) = instance.module.local.defined_global_index(base) { + if let Some(def_index) = instance.module().local.defined_global_index(base) { *instance.global(def_index).as_u32() } else { *(*instance.imported_global(base).from).as_u32() @@ -1090,7 +1096,7 @@ unsafe fn get_memory_slice<'instance>( instance: &'instance Instance, ) -> &'instance mut [u8] { let memory = if let Some(defined_memory_index) = instance - .module + .module() .local .defined_memory_index(init.location.memory_index) { @@ -1141,7 +1147,7 @@ fn get_table_init_start(init: &TableElements, instance: &Instance) -> usize { if let Some(base) = init.base { let val = unsafe { - if let Some(def_index) = instance.module.local.defined_global_index(base) { + if let Some(def_index) = instance.module().local.defined_global_index(base) { *instance.global(def_index).as_u32() } else { *(*instance.imported_global(base).from).as_u32() @@ -1155,8 +1161,7 @@ fn get_table_init_start(init: &TableElements, instance: &Instance) -> usize { /// Initialize the table memory from the provided initializers. fn initialize_tables(instance: &Instance) -> Result<(), InstantiationError> { - let module = &instance.module; - for init in &module.table_elements { + for init in &instance.module().table_elements { let start = get_table_init_start(init, instance); let table = instance.get_table(init.table_index); @@ -1192,7 +1197,7 @@ fn initialize_passive_elements(instance: &Instance) { passive_elements.extend( instance - .module + .module() .passive_elements .iter() .filter(|(_, segments)| !segments.is_empty()) @@ -1269,7 +1274,7 @@ fn create_globals(module: &Module) -> BoxedSlice func.instr_map.start_srcloc, }; Some(FrameInfo { - module_name: module.module.name.clone(), + module_name: module.module.module().name.clone(), func_index: func.index.index() as u32, - func_name: module.module.func_names.get(&func.index).cloned(), + func_name: module.module.module().func_names.get(&func.index).cloned(), instr, func_start: func.instr_map.start_srcloc, }) @@ -165,7 +165,7 @@ pub fn register(module: Arc) -> Option, name: &str) -> Result { let mut module = Module::new(store, bytes.as_ref())?; let inner = Arc::get_mut(&mut module.inner).unwrap(); - Arc::get_mut(&mut inner.compiled).unwrap().name = Some(name.to_string()); + Arc::get_mut(&mut inner.compiled).unwrap().module_mut().name = Some(name.to_string()); Ok(module) } @@ -359,7 +359,7 @@ impl Module { /// # } /// ``` pub fn name(&self) -> Option<&str> { - self.inner.compiled.name.as_deref() + self.inner.compiled.module().name.as_deref() } /// Returns the list of imports that this [`Module`] has and must be diff --git a/crates/wasmtime/src/trampoline/create_handle.rs b/crates/wasmtime/src/trampoline/create_handle.rs index a1cfc0ceb69f..ad8a94c39b3b 100644 --- a/crates/wasmtime/src/trampoline/create_handle.rs +++ b/crates/wasmtime/src/trampoline/create_handle.rs @@ -10,9 +10,17 @@ use wasmtime_environ::entity::PrimaryMap; use wasmtime_environ::wasm::DefinedFuncIndex; use wasmtime_environ::Module; use wasmtime_runtime::{ - Imports, InstanceHandle, VMFunctionBody, VMSharedSignatureIndex, VMTrampoline, + Imports, InstanceContext, InstanceHandle, VMFunctionBody, VMSharedSignatureIndex, VMTrampoline, }; +struct ModuleWrapper(Module); + +impl InstanceContext for ModuleWrapper { + fn module(&self) -> &Module { + &self.0 + } +} + pub(crate) fn create_handle( module: Module, store: &Store, @@ -37,7 +45,7 @@ pub(crate) fn create_handle( unsafe { let handle = InstanceHandle::new( - Arc::new(Box::new(module)), + Arc::new(ModuleWrapper(module)), finished_functions.into_boxed_slice(), trampolines, imports, From 810ec8a8156e0d606748560145ae82c3055e153a Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 27 May 2020 12:17:40 -0500 Subject: [PATCH 15/35] fix test --- examples/threads.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/threads.c b/examples/threads.c index 2f210006ef22..bc04ba69c634 100644 --- a/examples/threads.c +++ b/examples/threads.c @@ -163,13 +163,6 @@ int main(int argc, const char *argv[]) { return 0; } -#else -// TODO implement example for Windows -int main(int argc, const char *argv[]) { - return 0; -} -#endif // _WIN32 - static void exit_with_error(const char *message, wasmtime_error_t *error, wasm_trap_t *trap) { fprintf(stderr, "error: %s\n", message); wasm_byte_vec_t error_message; @@ -182,3 +175,10 @@ static void exit_with_error(const char *message, wasmtime_error_t *error, wasm_t wasm_byte_vec_delete(&error_message); exit(1); } + +#else +// TODO implement example for Windows +int main(int argc, const char *argv[]) { + return 0; +} +#endif // _WIN32 From 3ab0e3cc5a7c73eaadd2a0ab0fa3ace0f11171cd Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 27 May 2020 14:37:19 -0500 Subject: [PATCH 16/35] Redesign API to remove Store from Module::new --- crates/c-api/src/instance.rs | 11 +- crates/c-api/src/module.rs | 56 ++--- crates/fuzzing/src/oracles.rs | 17 +- crates/misc/rust/macro/src/lib.rs | 4 +- .../test-programs/tests/wasm_tests/runtime.rs | 2 +- crates/wasmtime/src/externals.rs | 21 +- crates/wasmtime/src/func.rs | 31 +-- crates/wasmtime/src/instance.rs | 15 +- crates/wasmtime/src/lib.rs | 2 +- crates/wasmtime/src/linker.rs | 31 +-- crates/wasmtime/src/module.rs | 202 +++++++----------- crates/wasmtime/src/runtime.rs | 97 +++++---- crates/wast/src/wast.rs | 2 +- docs/lang-rust.md | 18 +- docs/wasm-wat.md | 7 +- examples/fib-debug/main.rs | 4 +- examples/gcd.rs | 4 +- examples/hello.rs | 4 +- examples/interrupt.rs | 4 +- examples/linking.rs | 7 +- examples/memory.rs | 4 +- examples/multi.rs | 7 +- examples/threads.rs | 13 +- examples/wasi/main.rs | 2 +- src/commands/run.rs | 4 +- tests/all/custom_signal_handler.rs | 18 +- tests/all/externals.rs | 23 +- tests/all/func.rs | 26 +-- tests/all/globals.rs | 6 +- tests/all/iloop.rs | 14 +- tests/all/import_calling_export.rs | 8 +- tests/all/import_indexes.rs | 4 +- tests/all/instance.rs | 6 +- tests/all/invoke_func_via_table.rs | 4 +- tests/all/linker.rs | 15 +- tests/all/memory_creator.rs | 10 +- tests/all/name.rs | 10 +- tests/all/stack_overflow.rs | 4 +- tests/all/traps.rs | 59 ++--- tests/host_segfault.rs | 21 +- 40 files changed, 390 insertions(+), 407 deletions(-) diff --git a/crates/c-api/src/instance.rs b/crates/c-api/src/instance.rs index 6d528530d647..fce0b8d36cbd 100644 --- a/crates/c-api/src/instance.rs +++ b/crates/c-api/src/instance.rs @@ -35,8 +35,8 @@ pub unsafe extern "C" fn wasm_instance_new( result: Option<&mut *mut wasm_trap_t>, ) -> Option> { let store = &store.store.borrow(); - let module = &wasm_module.module.borrow(); - if !Store::same(&store, module.store()) { + let module_store = &wasm_module.store.borrow(); + if !Store::same(&store, module_store) { if let Some(result) = result { let trap = Trap::new("wasm_store_t must match store in wasm_module_t"); let trap = Box::new(wasm_trap_t::new(trap)); @@ -110,8 +110,13 @@ fn _wasmtime_instance_new( ExternHost::Memory(e) => Extern::Memory(e.borrow().clone()), }) .collect::>(); + let store = &module.store.borrow(); let module = &module.module.borrow(); - handle_instantiate(Instance::new(module, &imports), instance_ptr, trap_ptr) + handle_instantiate( + Instance::new(store, module, &imports), + instance_ptr, + trap_ptr, + ) } pub fn handle_instantiate( diff --git a/crates/c-api/src/module.rs b/crates/c-api/src/module.rs index bc88d1d70808..e7e6a1331a64 100644 --- a/crates/c-api/src/module.rs +++ b/crates/c-api/src/module.rs @@ -2,11 +2,12 @@ use crate::{handle_result, wasmtime_error_t}; use crate::{wasm_byte_vec_t, wasm_exporttype_vec_t, wasm_importtype_vec_t}; use crate::{wasm_exporttype_t, wasm_importtype_t, wasm_store_t}; use std::ptr; -use wasmtime::{HostRef, Module, SendableModule}; +use wasmtime::{HostRef, Module, Store}; #[repr(C)] #[derive(Clone)] pub struct wasm_module_t { + pub(crate) store: HostRef, pub(crate) module: HostRef, pub(crate) imports: Vec, pub(crate) exports: Vec, @@ -23,7 +24,7 @@ impl wasm_module_t { #[repr(C)] #[derive(Clone)] pub struct wasm_shared_module_t { - module: SendableModule, + module: Module, } wasmtime_c_api_macros::declare_own!(wasm_shared_module_t); @@ -50,23 +51,26 @@ pub extern "C" fn wasmtime_module_new( ret: &mut *mut wasm_module_t, ) -> Option> { let binary = binary.as_slice(); - let store = &store.store.borrow(); - handle_result(Module::from_binary(store, binary), |module| { - let imports = module - .imports() - .map(|i| wasm_importtype_t::new(i.module().to_owned(), i.name().to_owned(), i.ty())) - .collect::>(); - let exports = module - .exports() - .map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty())) - .collect::>(); - let module = Box::new(wasm_module_t { - module: HostRef::new(module), - imports, - exports, - }); - *ret = Box::into_raw(module); - }) + handle_result( + Module::from_binary(store.store.borrow().engine(), binary), + |module| { + let imports = module + .imports() + .map(|i| wasm_importtype_t::new(i.module().to_owned(), i.name().to_owned(), i.ty())) + .collect::>(); + let exports = module + .exports() + .map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty())) + .collect::>(); + let module = Box::new(wasm_module_t { + store: store.store.clone(), + module: HostRef::new(module), + imports, + exports, + }); + *ret = Box::into_raw(module); + }, + ) } #[no_mangle] @@ -80,8 +84,10 @@ pub extern "C" fn wasmtime_module_validate( binary: &wasm_byte_vec_t, ) -> Option> { let binary = binary.as_slice(); - let store = &store.store.borrow(); - handle_result(Module::validate(store, binary), |()| {}) + handle_result( + Module::validate(store.store.borrow().engine(), binary), + |()| {}, + ) } #[no_mangle] @@ -107,7 +113,7 @@ pub extern "C" fn wasm_module_imports(module: &wasm_module_t, out: &mut wasm_imp #[no_mangle] pub extern "C" fn wasm_module_share(module: &wasm_module_t) -> Box { Box::new(wasm_shared_module_t { - module: module.module.borrow().share(), + module: module.module.borrow().clone(), }) } @@ -116,10 +122,7 @@ pub extern "C" fn wasm_module_obtain( store: &wasm_store_t, shared_module: &wasm_shared_module_t, ) -> Box { - let module = shared_module - .module - .clone() - .place_into(&store.store.borrow()); + let module = shared_module.module.clone(); let imports = module .imports() .map(|i| wasm_importtype_t::new(i.module().to_owned(), i.name().to_owned(), i.ty())) @@ -129,6 +132,7 @@ pub extern "C" fn wasm_module_obtain( .map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty())) .collect::>(); Box::new(wasm_module_t { + store: store.store.clone(), module: HostRef::new(module), imports, exports, diff --git a/crates/fuzzing/src/oracles.rs b/crates/fuzzing/src/oracles.rs index a3d960843755..ecd6453ffb1b 100644 --- a/crates/fuzzing/src/oracles.rs +++ b/crates/fuzzing/src/oracles.rs @@ -56,7 +56,7 @@ pub fn instantiate_with_config(wasm: &[u8], config: Config) { let store = Store::new(&engine); log_wasm(wasm); - let module = match Module::new(&store, wasm) { + let module = match Module::new(&engine, wasm) { Ok(module) => module, Err(_) => return, }; @@ -75,7 +75,7 @@ pub fn instantiate_with_config(wasm: &[u8], config: Config) { // aren't caught during validation or compilation. For example, an imported // table might not have room for an element segment that we want to // initialize into it. - let _result = Instance::new(&module, &imports); + let _result = Instance::new(&store, &module, &imports); } /// Compile the Wasm buffer, and implicitly fail if we have an unexpected @@ -88,9 +88,8 @@ pub fn compile(wasm: &[u8], strategy: Strategy) { crate::init_fuzzing(); let engine = Engine::new(&crate::fuzz_default_config(strategy).unwrap()); - let store = Store::new(&engine); log_wasm(wasm); - let _ = Module::new(&store, wasm); + let _ = Module::new(&engine, wasm); } /// Instantiate the given Wasm module with each `Config` and call all of its @@ -128,7 +127,7 @@ pub fn differential_execution( let engine = Engine::new(config); let store = Store::new(&engine); - let module = match Module::new(&store, &ttf.wasm) { + let module = match Module::new(&engine, &ttf.wasm) { Ok(module) => module, // The module might rely on some feature that our config didn't // enable or something like that. @@ -158,7 +157,7 @@ pub fn differential_execution( // aren't caught during validation or compilation. For example, an imported // table might not have room for an element segment that we want to // initialize into it. - let instance = match Instance::new(&module, &imports) { + let instance = match Instance::new(&store, &module, &imports) { Ok(instance) => instance, Err(e) => { eprintln!( @@ -324,7 +323,9 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) { None => continue, }; - let imports = match dummy_imports(store.as_ref().unwrap(), module.imports()) { + let store = store.as_ref().unwrap(); + + let imports = match dummy_imports(store, module.imports()) { Ok(imps) => imps, Err(_) => { // There are some value types that we can't synthesize a @@ -338,7 +339,7 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) { // aren't caught during validation or compilation. For example, an imported // table might not have room for an element segment that we want to // initialize into it. - if let Ok(instance) = Instance::new(&module, &imports) { + if let Ok(instance) = Instance::new(store, &module, &imports) { instances.insert(id, instance); } } diff --git a/crates/misc/rust/macro/src/lib.rs b/crates/misc/rust/macro/src/lib.rs index 9c980d91bd64..b6cd8fc54d49 100644 --- a/crates/misc/rust/macro/src/lib.rs +++ b/crates/misc/rust/macro/src/lib.rs @@ -57,7 +57,7 @@ fn generate_load(item: &syn::ItemTrait) -> syn::Result { let data = #root::wasmtime_interface_types::ModuleData::new(bytes.as_ref())?; - let module = Module::new(&store, bytes.as_ref())?; + let module = Module::new(&engine, bytes.as_ref())?; let mut imports: Vec = Vec::new(); if let Some(module_name) = data.find_wasi_module_name() { @@ -75,7 +75,7 @@ fn generate_load(item: &syn::ItemTrait) -> syn::Result { } } let instance = - Instance::new(&module, &imports).map_err(|t| format_err!("instantiation trap: {:?}", t))?; + Instance::new(&store, &module, &imports).map_err(|t| format_err!("instantiation trap: {:?}", t))?; Ok(#name { instance, data }) } diff --git a/crates/test-programs/tests/wasm_tests/runtime.rs b/crates/test-programs/tests/wasm_tests/runtime.rs index de465d1309cd..0b4ba305e098 100644 --- a/crates/test-programs/tests/wasm_tests/runtime.rs +++ b/crates/test-programs/tests/wasm_tests/runtime.rs @@ -53,7 +53,7 @@ pub fn instantiate( snapshot1.add_to_linker(&mut linker)?; - let module = Module::new(&store, &data).context("failed to create wasm module")?; + let module = Module::new(store.engine(), &data).context("failed to create wasm module")?; linker .module("", &module) diff --git a/crates/wasmtime/src/externals.rs b/crates/wasmtime/src/externals.rs index d97ccb22f94e..0aed6429fabe 100644 --- a/crates/wasmtime/src/externals.rs +++ b/crates/wasmtime/src/externals.rs @@ -659,13 +659,14 @@ impl Memory { /// ``` /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { - /// let store = Store::default(); + /// let engine = Engine::default(); + /// let store = Store::new(&engine); /// /// let memory_ty = MemoryType::new(Limits::new(1, None)); /// let memory = Memory::new(&store, memory_ty); /// - /// let module = Module::new(&store, "(module (memory (import \"\" \"\") 1))")?; - /// let instance = Instance::new(&module, &[memory.into()])?; + /// let module = Module::new(&engine, "(module (memory (import \"\" \"\") 1))")?; + /// let instance = Instance::new(&store, &module, &[memory.into()])?; /// // ... /// # Ok(()) /// # } @@ -686,9 +687,10 @@ impl Memory { /// ``` /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { - /// let store = Store::default(); - /// let module = Module::new(&store, "(module (memory (export \"mem\") 1))")?; - /// let instance = Instance::new(&module, &[])?; + /// let engine = Engine::default(); + /// let store = Store::new(&engine); + /// let module = Module::new(&engine, "(module (memory (export \"mem\") 1))")?; + /// let instance = Instance::new(&store, &module, &[])?; /// let memory = instance.get_memory("mem").unwrap(); /// let ty = memory.ty(); /// assert_eq!(ty.limits().min(), 1); @@ -798,9 +800,10 @@ impl Memory { /// ``` /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { - /// let store = Store::default(); - /// let module = Module::new(&store, "(module (memory (export \"mem\") 1 2))")?; - /// let instance = Instance::new(&module, &[])?; + /// let engine = Engine::default(); + /// let store = Store::new(&engine); + /// let module = Module::new(&engine, "(module (memory (export \"mem\") 1 2))")?; + /// let instance = Instance::new(&store, &module, &[])?; /// let memory = instance.get_memory("mem").unwrap(); /// /// assert_eq!(memory.size(), 1); diff --git a/crates/wasmtime/src/func.rs b/crates/wasmtime/src/func.rs index 00fe661b0273..86daeae100cb 100644 --- a/crates/wasmtime/src/func.rs +++ b/crates/wasmtime/src/func.rs @@ -38,9 +38,10 @@ use wasmtime_runtime::{Export, InstanceHandle, VMContext, VMFunctionBody}; /// ``` /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { -/// let store = Store::default(); -/// let module = Module::new(&store, r#"(module (func (export "foo")))"#)?; -/// let instance = Instance::new(&module, &[])?; +/// let engine = Engine::default(); +/// let store = Store::new(&engine); +/// let module = Module::new(&engine, r#"(module (func (export "foo")))"#)?; +/// let instance = Instance::new(&store, &module, &[])?; /// let foo = instance.get_func("foo").expect("export wasn't a function"); /// /// // Work with `foo` as a `Func` at this point, such as calling it @@ -76,7 +77,7 @@ use wasmtime_runtime::{Export, InstanceHandle, VMContext, VMFunctionBody}; /// /// // Next we can hook that up to a wasm module which uses it. /// let module = Module::new( -/// &store, +/// store.engine(), /// r#" /// (module /// (import "" "" (func $add (param i32 i32) (result i32))) @@ -90,7 +91,7 @@ use wasmtime_runtime::{Export, InstanceHandle, VMContext, VMFunctionBody}; /// i32.add)) /// "#, /// )?; -/// let instance = Instance::new(&module, &[add.into()])?; +/// let instance = Instance::new(&store, &module, &[add.into()])?; /// let call_add_twice = instance.get_func("call_add_twice").expect("export wasn't a function"); /// let call_add_twice = call_add_twice.get0::()?; /// @@ -120,7 +121,7 @@ use wasmtime_runtime::{Export, InstanceHandle, VMContext, VMFunctionBody}; /// }); /// /// let module = Module::new( -/// &store, +/// store.engine(), /// r#" /// (module /// (import "" "" (func $double (param i32) (result i32))) @@ -131,7 +132,7 @@ use wasmtime_runtime::{Export, InstanceHandle, VMContext, VMFunctionBody}; /// (start $start)) /// "#, /// )?; -/// let instance = Instance::new(&module, &[double.into()])?; +/// let instance = Instance::new(&store, &module, &[double.into()])?; /// // .. work with `instance` if necessary /// # Ok(()) /// # } @@ -334,7 +335,7 @@ impl Func { /// # let store = Store::default(); /// let add = Func::wrap(&store, |a: i32, b: i32| a + b); /// let module = Module::new( - /// &store, + /// store.engine(), /// r#" /// (module /// (import "" "" (func $add (param i32 i32) (result i32))) @@ -344,7 +345,7 @@ impl Func { /// call $add)) /// "#, /// )?; - /// let instance = Instance::new(&module, &[add.into()])?; + /// let instance = Instance::new(&store, &module, &[add.into()])?; /// let foo = instance.get_func("foo").unwrap().get2::()?; /// assert_eq!(foo(1, 2)?, 3); /// # Ok(()) @@ -365,7 +366,7 @@ impl Func { /// } /// }); /// let module = Module::new( - /// &store, + /// store.engine(), /// r#" /// (module /// (import "" "" (func $add (param i32 i32) (result i32))) @@ -375,7 +376,7 @@ impl Func { /// call $add)) /// "#, /// )?; - /// let instance = Instance::new(&module, &[add.into()])?; + /// let instance = Instance::new(&store, &module, &[add.into()])?; /// let foo = instance.get_func("foo").unwrap().get2::()?; /// assert_eq!(foo(1, 2)?, 3); /// assert!(foo(i32::max_value(), 1).is_err()); @@ -396,7 +397,7 @@ impl Func { /// println!("d={}", d); /// }); /// let module = Module::new( - /// &store, + /// store.engine(), /// r#" /// (module /// (import "" "" (func $debug (param i32 f32 i64 f64))) @@ -408,7 +409,7 @@ impl Func { /// call $debug)) /// "#, /// )?; - /// let instance = Instance::new(&module, &[debug.into()])?; + /// let instance = Instance::new(&store, &module, &[debug.into()])?; /// let foo = instance.get_func("foo").unwrap().get0::<()>()?; /// foo()?; /// # Ok(()) @@ -452,7 +453,7 @@ impl Func { /// Ok(()) /// }); /// let module = Module::new( - /// &store, + /// store.engine(), /// r#" /// (module /// (import "" "" (func $log_str (param i32 i32))) @@ -464,7 +465,7 @@ impl Func { /// (data (i32.const 4) "Hello, world!")) /// "#, /// )?; - /// let instance = Instance::new(&module, &[log_str.into()])?; + /// let instance = Instance::new(&store, &module, &[log_str.into()])?; /// let foo = instance.get_func("foo").unwrap().get0::<()>()?; /// foo()?; /// # Ok(()) diff --git a/crates/wasmtime/src/instance.rs b/crates/wasmtime/src/instance.rs index 4705d845d08b..3458ad2bffae 100644 --- a/crates/wasmtime/src/instance.rs +++ b/crates/wasmtime/src/instance.rs @@ -122,6 +122,7 @@ fn instantiate( #[derive(Clone)] pub struct Instance { pub(crate) handle: StoreInstanceHandle, + store: Store, module: Module, } @@ -179,17 +180,15 @@ impl Instance { /// [inst]: https://webassembly.github.io/spec/core/exec/modules.html#exec-instantiation /// [issue]: https://github.com/bytecodealliance/wasmtime/issues/727 /// [`ExternType`]: crate::ExternType - pub fn new(module: &Module, imports: &[Extern]) -> Result { + pub fn new(store: &Store, module: &Module, imports: &[Extern]) -> Result { let info = module.register_frame_info(); - let handle = instantiate( - module.store(), - module.compiled_module(), - imports, - Box::new(info), - )?; + store.register_jit_code(module.compiled_module().jit_code_ranges()); + + let handle = instantiate(store, module.compiled_module(), imports, Box::new(info))?; Ok(Instance { handle, + store: store.clone(), module: module.clone(), }) } @@ -199,7 +198,7 @@ impl Instance { /// This is the [`Store`] that generally serves as a sort of global cache /// for various instance-related things. pub fn store(&self) -> &Store { - self.module.store() + &self.store } /// Returns the list of exported items from this [`Instance`]. diff --git a/crates/wasmtime/src/lib.rs b/crates/wasmtime/src/lib.rs index 5449e93682fa..e08fbb15f990 100644 --- a/crates/wasmtime/src/lib.rs +++ b/crates/wasmtime/src/lib.rs @@ -28,7 +28,7 @@ pub use crate::frame_info::FrameInfo; pub use crate::func::*; pub use crate::instance::Instance; pub use crate::linker::*; -pub use crate::module::{Module, SendableModule}; +pub use crate::module::Module; pub use crate::r#ref::{ExternRef, HostRef}; pub use crate::runtime::*; pub use crate::trap::Trap; diff --git a/crates/wasmtime/src/linker.rs b/crates/wasmtime/src/linker.rs index ed9aacdd5676..ac06df781675 100644 --- a/crates/wasmtime/src/linker.rs +++ b/crates/wasmtime/src/linker.rs @@ -149,7 +149,7 @@ impl Linker { /// (data (global.get 0) "foo") /// ) /// "#; - /// let module = Module::new(&store, wat)?; + /// let module = Module::new(store.engine(), wat)?; /// linker.instantiate(&module)?; /// # Ok(()) /// # } @@ -202,7 +202,7 @@ impl Linker { /// (import "host" "log_str" (func (param i32 i32))) /// ) /// "#; - /// let module = Module::new(&store, wat)?; + /// let module = Module::new(store.engine(), wat)?; /// linker.instantiate(&module)?; /// # Ok(()) /// # } @@ -240,7 +240,7 @@ impl Linker { /// /// // Instantiate a small instance... /// let wat = r#"(module (func (export "run") ))"#; - /// let module = Module::new(&store, wat)?; + /// let module = Module::new(store.engine(), wat)?; /// let instance = linker.instantiate(&module)?; /// /// // ... and inform the linker that the name of this instance is @@ -256,7 +256,7 @@ impl Linker { /// ) /// ) /// "#; - /// let module = Module::new(&store, wat)?; + /// let module = Module::new(store.engine(), wat)?; /// let instance = linker.instantiate(&module)?; /// # Ok(()) /// # } @@ -311,7 +311,7 @@ impl Linker { /// // this instance is `instance1`. This defines the `instance1::run` name /// // for our next module to use. /// let wat = r#"(module (func (export "run") ))"#; - /// let module = Module::new(&store, wat)?; + /// let module = Module::new(store.engine(), wat)?; /// linker.module("instance1", &module)?; /// /// let wat = r#" @@ -322,7 +322,7 @@ impl Linker { /// ) /// ) /// "#; - /// let module = Module::new(&store, wat)?; + /// let module = Module::new(store.engine(), wat)?; /// let instance = linker.instantiate(&module)?; /// # Ok(()) /// # } @@ -349,7 +349,7 @@ impl Linker { /// ) /// ) /// "#; - /// let module = Module::new(&store, wat)?; + /// let module = Module::new(store.engine(), wat)?; /// linker.module("commander", &module)?; /// let run = linker.get_default("")?.get0::<()>()?; /// run()?; @@ -368,7 +368,7 @@ impl Linker { /// ) /// ) /// "#; - /// let module = Module::new(&store, wat)?; + /// let module = Module::new(store.engine(), wat)?; /// linker.module("", &module)?; /// let count = linker.get_one_by_name("", "run")?.into_func().unwrap().get0::()?()?; /// assert_eq!(count, 0, "a Command should get a fresh instance on each invocation"); @@ -399,15 +399,16 @@ impl Linker { for export in module.exports() { if let Some(func_ty) = export.ty().func() { let imports = self.compute_imports(module)?; + let store = self.store.clone(); let module = module.clone(); let export_name = export.name().to_owned(); let func = Func::new(&self.store, func_ty.clone(), move |_, params, results| { // Create a new instance for this command execution. - let instance = Instance::new(&module, &imports).map_err(|error| match error - .downcast::() - { - Ok(trap) => trap, - Err(error) => Trap::new(format!("{:?}", error)), + let instance = Instance::new(&store, &module, &imports).map_err(|error| { + match error.downcast::() { + Ok(trap) => trap, + Err(error) => Trap::new(format!("{:?}", error)), + } })?; // `unwrap()` everything here because we know the instance contains a @@ -556,7 +557,7 @@ impl Linker { /// (import "host" "double" (func (param i32) (result i32))) /// ) /// "#; - /// let module = Module::new(&store, wat)?; + /// let module = Module::new(store.engine(), wat)?; /// linker.instantiate(&module)?; /// # Ok(()) /// # } @@ -564,7 +565,7 @@ impl Linker { pub fn instantiate(&self, module: &Module) -> Result { let imports = self.compute_imports(module)?; - Instance::new(module, &imports) + Instance::new(&self.store, module, &imports) } fn compute_imports(&self, module: &Module) -> Result> { diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs index 4b51b3a23318..7c1ed068c348 100644 --- a/crates/wasmtime/src/module.rs +++ b/crates/wasmtime/src/module.rs @@ -1,5 +1,5 @@ use crate::frame_info::GlobalFrameInfoRegistration; -use crate::runtime::Store; +use crate::runtime::Engine; use crate::types::{EntityType, ExportType, ExternType, ImportType}; use anyhow::{Error, Result}; use std::path::Path; @@ -38,8 +38,8 @@ use wasmtime_jit::CompiledModule; /// ```no_run /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { -/// let store = Store::default(); -/// let module = Module::from_file(&store, "path/to/foo.wasm")?; +/// let engine = Engine::default(); +/// let module = Module::from_file(&engine, "path/to/foo.wasm")?; /// # Ok(()) /// # } /// ``` @@ -49,9 +49,9 @@ use wasmtime_jit::CompiledModule; /// ```no_run /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { -/// let store = Store::default(); +/// let engine = Engine::default(); /// // Now we're using the WebAssembly text extension: `.wat`! -/// let module = Module::from_file(&store, "path/to/foo.wat")?; +/// let module = Module::from_file(&engine, "path/to/foo.wat")?; /// # Ok(()) /// # } /// ``` @@ -62,12 +62,12 @@ use wasmtime_jit::CompiledModule; /// ```no_run /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { -/// let store = Store::default(); +/// let engine = Engine::default(); /// # let wasm_bytes: Vec = Vec::new(); -/// let module = Module::new(&store, &wasm_bytes)?; +/// let module = Module::new(&engine, &wasm_bytes)?; /// /// // It also works with the text format! -/// let module = Module::new(&store, "(module (func))")?; +/// let module = Module::new(&engine, "(module (func))")?; /// # Ok(()) /// # } /// ``` @@ -75,11 +75,7 @@ use wasmtime_jit::CompiledModule; /// [`Config`]: crate::Config #[derive(Clone)] pub struct Module { - inner: Arc, -} - -struct ModuleInner { - store: Store, + engine: Engine, compiled: Arc, frame_info_registration: Arc>>>>, } @@ -103,12 +99,7 @@ impl Module { /// compilation of a module. /// /// The WebAssembly binary will be decoded and validated. It will also be - /// compiled according to the configuration of the provided `store` and - /// cached in this type. - /// - /// The provided `store` is a global cache for compiled resources as well as - /// configuration for what wasm features are enabled. It's recommended to - /// share a `store` among modules if possible. + /// compiled according to the configuration of the provided `engine`. /// /// # Errors /// @@ -121,7 +112,7 @@ impl Module { /// * Implementation-specific limits were exceeded with a valid binary (for /// example too many locals) /// * The wasm binary may use features that are not enabled in the - /// configuration of `store` + /// configuration of `enging` /// * If the `wat` feature is enabled and the input is text, then it may be /// rejected if it fails to parse. /// @@ -138,9 +129,9 @@ impl Module { /// ```no_run /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let engine = Engine::default(); /// # let wasm_bytes: Vec = Vec::new(); - /// let module = Module::new(&store, &wasm_bytes)?; + /// let module = Module::new(&engine, &wasm_bytes)?; /// # Ok(()) /// # } /// ``` @@ -151,25 +142,27 @@ impl Module { /// ``` /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); - /// let module = Module::new(&store, "(module (func))")?; + /// # let engine = Engine::default(); + /// let module = Module::new(&engine, "(module (func))")?; /// # Ok(()) /// # } /// ``` - pub fn new(store: &Store, bytes: impl AsRef<[u8]>) -> Result { + pub fn new(engine: &Engine, bytes: impl AsRef<[u8]>) -> Result { #[cfg(feature = "wat")] let bytes = wat::parse_bytes(bytes.as_ref())?; - Module::from_binary(store, bytes.as_ref()) + Module::from_binary(engine, bytes.as_ref()) } /// Creates a new WebAssembly `Module` from the given in-memory `binary` /// data. The provided `name` will be used in traps/backtrace details. /// /// 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 = Arc::get_mut(&mut module.inner).unwrap(); - Arc::get_mut(&mut inner.compiled).unwrap().module_mut().name = Some(name.to_string()); + pub fn new_with_name(engine: &Engine, bytes: impl AsRef<[u8]>, name: &str) -> Result { + let mut module = Module::new(engine, bytes.as_ref())?; + Arc::get_mut(&mut module.compiled) + .unwrap() + .module_mut() + .name = Some(name.to_string()); Ok(module) } @@ -185,8 +178,8 @@ impl Module { /// ```no_run /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { - /// let store = Store::default(); - /// let module = Module::from_file(&store, "./path/to/foo.wasm")?; + /// let engine = Engine::default(); + /// let module = Module::from_file(&engine, "./path/to/foo.wasm")?; /// # Ok(()) /// # } /// ``` @@ -196,17 +189,17 @@ impl Module { /// ```no_run /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); - /// let module = Module::from_file(&store, "./path/to/foo.wat")?; + /// # let engine = Engine::default(); + /// let module = Module::from_file(&engine, "./path/to/foo.wat")?; /// # Ok(()) /// # } /// ``` - pub fn from_file(store: &Store, file: impl AsRef) -> Result { + pub fn from_file(engine: &Engine, file: impl AsRef) -> Result { #[cfg(feature = "wat")] let wasm = wat::parse_file(file)?; #[cfg(not(feature = "wat"))] let wasm = std::fs::read(file)?; - Module::new(store, &wasm) + Module::new(engine, &wasm) } /// Creates a new WebAssembly `Module` from the given in-memory `binary` @@ -223,9 +216,9 @@ impl Module { /// ``` /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let engine = Engine::default(); /// let wasm = b"\0asm\x01\0\0\0"; - /// let module = Module::from_binary(&store, wasm)?; + /// let module = Module::from_binary(&engine, wasm)?; /// # Ok(()) /// # } /// ``` @@ -235,17 +228,17 @@ impl Module { /// ``` /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); - /// assert!(Module::from_binary(&store, b"(module)").is_err()); + /// # let engine = Engine::default(); + /// assert!(Module::from_binary(&engine, b"(module)").is_err()); /// # Ok(()) /// # } /// ``` - pub fn from_binary(store: &Store, binary: &[u8]) -> Result { - Module::validate(store, binary)?; + pub fn from_binary(engine: &Engine, binary: &[u8]) -> Result { + Module::validate(engine, binary)?; // 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) } + // to pass a valid binary for `engine`. + unsafe { Module::from_binary_unchecked(engine, binary) } } /// Creates a new WebAssembly `Module` from the given in-memory `binary` @@ -257,7 +250,7 @@ impl Module { /// WebAssembly. The WebAssembly binary is not validated for /// correctness and it is simply assumed as valid. /// - /// For more information about creation of a module and the `store` argument + /// For more information about creation of a module and the `engine` argument /// see the documentation of [`Module::new`]. /// /// # Unsafety @@ -275,17 +268,17 @@ impl Module { /// While this assumes that the binary is valid it still needs to actually /// be somewhat valid for decoding purposes, and the basics of decoding can /// still fail. - pub unsafe fn from_binary_unchecked(store: &Store, binary: &[u8]) -> Result { - Module::compile(store, binary) + pub unsafe fn from_binary_unchecked(engine: &Engine, binary: &[u8]) -> Result { + Module::compile(engine, binary) } /// Validates `binary` input data as a WebAssembly binary given the - /// configuration in `store`. + /// configuration in `engine`. /// /// This function will perform a speedy validation of the `binary` input /// WebAssembly module (which is in [binary form][binary], the text format /// is not accepted by this function) and return either `Ok` or `Err` - /// depending on the results of validation. The `store` argument indicates + /// depending on the results of validation. The `engine` argument indicates /// configuration for WebAssembly features, for example, which are used to /// indicate what should be valid and what shouldn't be. /// @@ -299,39 +292,24 @@ impl Module { /// validation issue will be returned. /// /// [binary]: https://webassembly.github.io/spec/core/binary/index.html - pub fn validate(store: &Store, binary: &[u8]) -> Result<()> { - let config = store.engine().config().validating_config.clone(); + pub fn validate(engine: &Engine, binary: &[u8]) -> Result<()> { + let config = engine.config().validating_config.clone(); validate(binary, Some(config)).map_err(Error::new) } - unsafe fn compile(store: &Store, binary: &[u8]) -> Result { - let compiled = CompiledModule::new( - &store.compiler(), - binary, - &*store.engine().config().profiler, - )?; - - store.register_jit_code(compiled.jit_code_ranges()); + unsafe fn compile(engine: &Engine, binary: &[u8]) -> Result { + let compiled = + CompiledModule::new(&engine.get_compiler(), binary, &*engine.config().profiler)?; Ok(Module { - inner: Arc::new(ModuleInner { - store: store.clone(), - compiled: Arc::new(compiled), - frame_info_registration: Arc::new(Mutex::new(None)), - }), + engine: engine.clone(), + compiled: Arc::new(compiled), + frame_info_registration: Arc::new(Mutex::new(None)), }) } pub(crate) fn compiled_module(&self) -> &Arc { - &self.inner.compiled - } - - /// Returns the module that can be used in different thread. - pub fn share(&self) -> SendableModule { - SendableModule { - compiled: self.inner.compiled.clone(), - frame_info_registration: self.inner.frame_info_registration.clone(), - } + &self.compiled } /// Returns identifier/name that this [`Module`] has. This name @@ -346,20 +324,20 @@ impl Module { /// ``` /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); - /// let module = Module::new(&store, "(module $foo)")?; + /// # let engine = Engine::default(); + /// let module = Module::new(&engine, "(module $foo)")?; /// assert_eq!(module.name(), Some("foo")); /// - /// let module = Module::new(&store, "(module)")?; + /// let module = Module::new(&engine, "(module)")?; /// assert_eq!(module.name(), None); /// - /// let module = Module::new_with_name(&store, "(module)", "bar")?; + /// let module = Module::new_with_name(&engine, "(module)", "bar")?; /// assert_eq!(module.name(), Some("bar")); /// # Ok(()) /// # } /// ``` pub fn name(&self) -> Option<&str> { - self.inner.compiled.module().name.as_deref() + self.compiled.module().name.as_deref() } /// Returns the list of imports that this [`Module`] has and must be @@ -381,8 +359,8 @@ impl Module { /// ``` /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); - /// let module = Module::new(&store, "(module)")?; + /// # let engine = Engine::default(); + /// let module = Module::new(&engine, "(module)")?; /// assert_eq!(module.imports().len(), 0); /// # Ok(()) /// # } @@ -393,13 +371,13 @@ impl Module { /// ``` /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let engine = Engine::default(); /// let wat = r#" /// (module /// (import "host" "foo" (func)) /// ) /// "#; - /// let module = Module::new(&store, wat)?; + /// let module = Module::new(&engine, wat)?; /// assert_eq!(module.imports().len(), 1); /// let import = module.imports().next().unwrap(); /// assert_eq!(import.module(), "host"); @@ -414,7 +392,7 @@ impl Module { pub fn imports<'module>( &'module self, ) -> impl ExactSizeIterator> + 'module { - let module = self.inner.compiled.module(); + let module = self.compiled.module(); module .imports .iter() @@ -439,8 +417,8 @@ impl Module { /// ``` /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); - /// let module = Module::new(&store, "(module)")?; + /// # let engine = Engine::default(); + /// let module = Module::new(&engine, "(module)")?; /// assert!(module.exports().next().is_none()); /// # Ok(()) /// # } @@ -451,14 +429,14 @@ impl Module { /// ``` /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let engine = Engine::default(); /// let wat = r#" /// (module /// (func (export "foo")) /// (memory (export "memory") 1) /// ) /// "#; - /// let module = Module::new(&store, wat)?; + /// let module = Module::new(&engine, wat)?; /// assert_eq!(module.exports().len(), 2); /// /// let mut exports = module.exports(); @@ -481,7 +459,7 @@ impl Module { pub fn exports<'module>( &'module self, ) -> impl ExactSizeIterator> + 'module { - let module = self.inner.compiled.module(); + let module = self.compiled.module(); module.exports.iter().map(move |(name, entity_index)| { let r#type = EntityType::new(entity_index, module); ExportType::new(name, r#type) @@ -499,8 +477,8 @@ impl Module { /// ``` /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); - /// let module = Module::new(&store, "(module)")?; + /// # let engine = Engine::default(); + /// let module = Module::new(&engine, "(module)")?; /// assert!(module.get_export("foo").is_none()); /// # Ok(()) /// # } @@ -511,14 +489,14 @@ impl Module { /// ``` /// # use wasmtime::*; /// # fn main() -> anyhow::Result<()> { - /// # let store = Store::default(); + /// # let engine = Engine::default(); /// let wat = r#" /// (module /// (func (export "foo")) /// (memory (export "memory") 1) /// ) /// "#; - /// let module = Module::new(&store, wat)?; + /// let module = Module::new(&engine, wat)?; /// let foo = module.get_export("foo"); /// assert!(foo.is_some()); /// @@ -532,54 +510,26 @@ impl Module { /// # } /// ``` pub fn get_export<'module>(&'module self, name: &'module str) -> Option { - let module = self.inner.compiled.module(); + let module = self.compiled.module(); let entity_index = module.exports.get(name)?; Some(EntityType::new(entity_index, module).extern_type()) } - /// Returns the [`Store`] that this [`Module`] was compiled into. - pub fn store(&self) -> &Store { - &self.inner.store + /// Returns the [`Engine`] that this [`Module`] was compiled by. + pub fn engine(&self) -> &Engine { + &self.engine } /// 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_frame_info(&self) -> Option> { - let mut info = self.inner.frame_info_registration.lock().unwrap(); + let mut info = self.frame_info_registration.lock().unwrap(); if let Some(info) = &*info { return info.clone(); } - let ret = super::frame_info::register(self.inner.compiled.clone()).map(Arc::new); + let ret = super::frame_info::register(self.compiled.clone()).map(Arc::new); *info = Some(ret.clone()); return ret; } } - -/// Shareable portion of the `Module` that can be instantiated in -/// deferent `Store`. -#[derive(Clone)] -pub struct SendableModule { - compiled: Arc, - frame_info_registration: Arc>>>>, -} - -unsafe impl Send for SendableModule {} - -impl SendableModule { - /// Returns `Module` that is belong to diffrent `Store`. - pub fn place_into(self, store: &Store) -> Module { - let compiled = self.compiled; - let frame_info_registration = self.frame_info_registration; - - store.register_jit_code(compiled.jit_code_ranges()); - - Module { - inner: Arc::new(ModuleInner { - store: store.clone(), - compiled, - frame_info_registration, - }), - } - } -} diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs index fdc902e51a9e..f9a552b84dde 100644 --- a/crates/wasmtime/src/runtime.rs +++ b/crates/wasmtime/src/runtime.rs @@ -702,6 +702,16 @@ impl Engine { pub fn config(&self) -> &Config { &self.config } + + pub(crate) fn get_compiler(&self) -> Compiler { + let isa = native::builder().finish(settings::Flags::new(self.config.flags.clone())); + Compiler::new( + isa, + self.config.strategy, + self.config.cache_config.clone(), + self.config.tunables.clone(), + ) + } } // Store @@ -730,7 +740,6 @@ pub struct Store { pub(crate) struct StoreInner { engine: Engine, - compiler: RefCell, interrupts: Arc, signatures: RefCell, instances: RefCell>, @@ -748,17 +757,9 @@ impl Store { // each one that's not relevant just won't do anything. wasmtime_runtime::init_traps(); - let isa = native::builder().finish(settings::Flags::new(engine.config.flags.clone())); - let compiler = Compiler::new( - isa, - engine.config.strategy, - engine.config.cache_config.clone(), - engine.config.tunables.clone(), - ); Store { inner: Rc::new(StoreInner { engine: engine.clone(), - compiler: RefCell::new(compiler), interrupts: Arc::new(Default::default()), signatures: RefCell::new(Default::default()), instances: RefCell::new(Vec::new()), @@ -782,10 +783,6 @@ impl Store { self.engine().config.memory_creator.as_ref().map(|x| x as _) } - pub(crate) fn compiler(&self) -> std::cell::Ref<'_, Compiler> { - self.inner.compiler.borrow() - } - pub(crate) fn signatures(&self) -> std::cell::Ref<'_, SignatureRegistry> { self.inner.signatures.borrow() } @@ -804,9 +801,17 @@ impl Store { .any(|(start, end)| *start <= addr && addr < *end) } - pub(crate) fn register_jit_code(&self, ranges: impl Iterator) { - let mut jit_code_ranges = self.inner.jit_code_ranges.borrow_mut(); - jit_code_ranges.extend(ranges); + pub(crate) fn register_jit_code(&self, mut ranges: impl Iterator) { + match ranges.next() { + None => (), + Some(first) => { + if !self.is_in_jit_code(first.0) { + let mut jit_code_ranges = self.inner.jit_code_ranges.borrow_mut(); + jit_code_ranges.push(first); + jit_code_ranges.extend(ranges); + } + } + } } pub(crate) unsafe fn add_instance(&self, handle: InstanceHandle) -> StoreInstanceHandle { @@ -919,10 +924,10 @@ impl Store { /// let interrupt_handle = store.interrupt_handle()?; /// /// // Compile and instantiate a small example with an infinite loop. - /// let module = Module::new(&store, r#" + /// let module = Module::new(&engine, r#" /// (func (export "run") (loop br 0)) /// "#)?; - /// let instance = Instance::new(&module, &[])?; + /// let instance = Instance::new(&store, &module, &[])?; /// let run = instance /// .get_func("run") /// .ok_or(anyhow::format_err!("failed to find `run` function export"))? @@ -1018,47 +1023,47 @@ mod tests { let mut cfg = Config::new(); cfg.cranelift_opt_level(OptLevel::None) .cache_config_load(&config_path)?; - let store = Store::new(&Engine::new(&cfg)); - Module::new(&store, "(module (func))")?; - assert_eq!(store.engine().config.cache_config.cache_hits(), 0); - assert_eq!(store.engine().config.cache_config.cache_misses(), 1); - Module::new(&store, "(module (func))")?; - assert_eq!(store.engine().config.cache_config.cache_hits(), 1); - assert_eq!(store.engine().config.cache_config.cache_misses(), 1); + let engine = Engine::new(&cfg); + Module::new(&engine, "(module (func))")?; + assert_eq!(engine.config.cache_config.cache_hits(), 0); + assert_eq!(engine.config.cache_config.cache_misses(), 1); + Module::new(&engine, "(module (func))")?; + assert_eq!(engine.config.cache_config.cache_hits(), 1); + assert_eq!(engine.config.cache_config.cache_misses(), 1); let mut cfg = Config::new(); cfg.cranelift_opt_level(OptLevel::Speed) .cache_config_load(&config_path)?; - let store = Store::new(&Engine::new(&cfg)); - Module::new(&store, "(module (func))")?; - assert_eq!(store.engine().config.cache_config.cache_hits(), 0); - assert_eq!(store.engine().config.cache_config.cache_misses(), 1); - Module::new(&store, "(module (func))")?; - assert_eq!(store.engine().config.cache_config.cache_hits(), 1); - assert_eq!(store.engine().config.cache_config.cache_misses(), 1); + let engine = Engine::new(&cfg); + Module::new(&engine, "(module (func))")?; + assert_eq!(engine.config.cache_config.cache_hits(), 0); + assert_eq!(engine.config.cache_config.cache_misses(), 1); + Module::new(&engine, "(module (func))")?; + assert_eq!(engine.config.cache_config.cache_hits(), 1); + assert_eq!(engine.config.cache_config.cache_misses(), 1); let mut cfg = Config::new(); cfg.cranelift_opt_level(OptLevel::SpeedAndSize) .cache_config_load(&config_path)?; - let store = Store::new(&Engine::new(&cfg)); - Module::new(&store, "(module (func))")?; - assert_eq!(store.engine().config.cache_config.cache_hits(), 0); - assert_eq!(store.engine().config.cache_config.cache_misses(), 1); - Module::new(&store, "(module (func))")?; - assert_eq!(store.engine().config.cache_config.cache_hits(), 1); - assert_eq!(store.engine().config.cache_config.cache_misses(), 1); + let engine = Engine::new(&cfg); + Module::new(&engine, "(module (func))")?; + assert_eq!(engine.config.cache_config.cache_hits(), 0); + assert_eq!(engine.config.cache_config.cache_misses(), 1); + Module::new(&engine, "(module (func))")?; + assert_eq!(engine.config.cache_config.cache_hits(), 1); + assert_eq!(engine.config.cache_config.cache_misses(), 1); // FIXME(#1523) need debuginfo on aarch64 before we run this test there if !cfg!(target_arch = "aarch64") { let mut cfg = Config::new(); cfg.debug_info(true).cache_config_load(&config_path)?; - let store = Store::new(&Engine::new(&cfg)); - Module::new(&store, "(module (func))")?; - assert_eq!(store.engine().config.cache_config.cache_hits(), 0); - assert_eq!(store.engine().config.cache_config.cache_misses(), 1); - Module::new(&store, "(module (func))")?; - assert_eq!(store.engine().config.cache_config.cache_hits(), 1); - assert_eq!(store.engine().config.cache_config.cache_misses(), 1); + let engine = Engine::new(&cfg); + Module::new(&engine, "(module (func))")?; + assert_eq!(engine.config.cache_config.cache_hits(), 0); + assert_eq!(engine.config.cache_config.cache_misses(), 1); + Module::new(&engine, "(module (func))")?; + assert_eq!(engine.config.cache_config.cache_hits(), 1); + assert_eq!(engine.config.cache_config.cache_misses(), 1); } Ok(()) diff --git a/crates/wast/src/wast.rs b/crates/wast/src/wast.rs index 5c3c2253111f..55e54dbcd65c 100644 --- a/crates/wast/src/wast.rs +++ b/crates/wast/src/wast.rs @@ -79,7 +79,7 @@ impl WastContext { } fn instantiate(&mut self, module: &[u8]) -> Result> { - let module = Module::new(&self.store, module)?; + let module = Module::new(self.store.engine(), module)?; self.modules.push(module.clone()); let instance = match self.linker.instantiate(&module) { Ok(i) => i, diff --git a/docs/lang-rust.md b/docs/lang-rust.md index 85aef3dbefa7..e19b644fe7bd 100644 --- a/docs/lang-rust.md +++ b/docs/lang-rust.md @@ -55,21 +55,22 @@ use std::error::Error; use wasmtime::*; fn main() -> Result<(), Box> { + let engine = Engine::default() // A `Store` is a sort of "global object" in a sense, but for now it suffices // to say that it's generally passed to most constructors. - let store = Store::default(); + let store = Store::new(&engine); # if false { // We start off by creating a `Module` which represents a compiled form // of our input wasm module. In this case it'll be JIT-compiled after // we parse the text format. - let module = Module::from_file(&store, "hello.wat")?; + let module = Module::from_file(&engine, "hello.wat")?; # } -# let module = Module::new(&store, r#"(module (func (export "answer") (result i32) i32.const 42))"#)?; +# let module = Module::new(&engine, r#"(module (func (export "answer") (result i32) i32.const 42))"#)?; // After we have a compiled `Module` we can then instantiate it, creating // an `Instance` which we can actually poke at functions on. - let instance = Instance::new(&module, &[])?; + let instance = Instance::new(&store, &module, &[])?; // The `Instance` gives us access to various exported functions and items, // which we access here to pull out our `answer` exported function and @@ -142,11 +143,12 @@ use std::error::Error; use wasmtime::*; fn main() -> Result<(), Box> { - let store = Store::default(); + let engine = Engine::default(); + let store = Store::new(&engine); # if false { - let module = Module::from_file(&store, "hello.wat")?; + let module = Module::from_file(&engine, "hello.wat")?; # } -# let module = Module::new(&store, r#"(module (import "" "log" (func $log (param i32))) (import "" "double" (func $double (param i32) (result i32))) (func (export "run") i32.const 0 call $log i32.const 1 call $log i32.const 2 call $double call $log))"#)?; +# let module = Module::new(&engine, r#"(module (import "" "log" (func $log (param i32))) (import "" "double" (func $double (param i32) (result i32))) (func (export "run") i32.const 0 call $log i32.const 1 call $log i32.const 2 call $double call $log))"#)?; // First we can create our `log` function, which will simply print out the // parameter it receives. @@ -160,7 +162,7 @@ fn main() -> Result<(), Box> { // When instantiating the module we now need to provide the imports to the // instantiation process. This is the second slice argument, where each // entry in the slice must line up with the imports in the module. - let instance = Instance::new(&module, &[log.into(), double.into()])?; + let instance = Instance::new(&store, &module, &[log.into(), double.into()])?; let run = instance .get_func("run") diff --git a/docs/wasm-wat.md b/docs/wasm-wat.md index 0f9153771696..9210e67c572d 100644 --- a/docs/wasm-wat.md +++ b/docs/wasm-wat.md @@ -37,7 +37,8 @@ You can also see how this works in the Rust API like so: use wasmtime::*; # fn main() -> anyhow::Result<()> { -let store = Store::default(); +let engine = Engine::default(); +let store = Store::new(&engine); let wat = r#" (module (func (export "add") (param i32 i32) (result i32) @@ -45,8 +46,8 @@ let wat = r#" local.get 1 i32.add)) "#; -let module = Module::new(&store, wat)?; -let instance = Instance::new(&module, &[])?; +let module = Module::new(&engine, wat)?; +let instance = Instance::new(&store, &module, &[])?; let add = instance.get_func("add").unwrap(); let add = add.get2::()?; println!("1 + 2 = {}", add(1, 2)?); diff --git a/examples/fib-debug/main.rs b/examples/fib-debug/main.rs index ff35b8c83c10..8cc2d9cd8f1a 100644 --- a/examples/fib-debug/main.rs +++ b/examples/fib-debug/main.rs @@ -17,8 +17,8 @@ fn main() -> Result<()> { // debugged in GDB. let engine = Engine::new(Config::new().debug_info(true)); let store = Store::new(&engine); - let module = Module::from_file(&store, "target/wasm32-unknown-unknown/debug/fib.wasm")?; - let instance = Instance::new(&module, &[])?; + let module = Module::from_file(&engine, "target/wasm32-unknown-unknown/debug/fib.wasm")?; + let instance = Instance::new(&store, &module, &[])?; // Invoke `fib` export let fib = instance diff --git a/examples/gcd.rs b/examples/gcd.rs index 067ab7b2dff8..45c87d7f2619 100644 --- a/examples/gcd.rs +++ b/examples/gcd.rs @@ -11,8 +11,8 @@ fn main() -> Result<()> { // `Module` which is attached to a `Store` cache. After we've got that we // can instantiate it. let store = Store::default(); - let module = Module::from_file(&store, "examples/gcd.wat")?; - let instance = Instance::new(&module, &[])?; + let module = Module::from_file(store.engine(), "examples/gcd.wat")?; + let instance = Instance::new(&store, &module, &[])?; // Invoke `gcd` export let gcd = instance diff --git a/examples/hello.rs b/examples/hello.rs index 00772b22eb01..89f904670be5 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -15,7 +15,7 @@ fn main() -> Result<()> { // Compile the wasm binary into an in-memory instance of a `Module`. println!("Compiling module..."); - let module = Module::from_file(&store, "examples/hello.wat")?; + let module = Module::from_file(store.engine(), "examples/hello.wat")?; // Here we handle the imports of the module, which in this case is our // `HelloCallback` type and its associated implementation of `Callback. @@ -30,7 +30,7 @@ fn main() -> Result<()> { // Note that this is where the wasm `start` function, if any, would run. println!("Instantiating module..."); let imports = [hello_func.into()]; - let instance = Instance::new(&module, &imports)?; + let instance = Instance::new(&store, &module, &imports)?; // Next we poke around a bit to extract the `run` function from the module. println!("Extracting export..."); diff --git a/examples/interrupt.rs b/examples/interrupt.rs index 696d8a2d952d..4d41413c8d5b 100644 --- a/examples/interrupt.rs +++ b/examples/interrupt.rs @@ -14,8 +14,8 @@ fn main() -> Result<()> { let interrupt_handle = store.interrupt_handle()?; // Compile and instantiate a small example with an infinite loop. - let module = Module::from_file(&store, "examples/interrupt.wat")?; - let instance = Instance::new(&module, &[])?; + let module = Module::from_file(&engine, "examples/interrupt.wat")?; + let instance = Instance::new(&store, &module, &[])?; let run = instance .get_func("run") .ok_or(anyhow::format_err!("failed to find `run` function export"))? diff --git a/examples/linking.rs b/examples/linking.rs index 4f9548739e6c..f46e7a4f89f0 100644 --- a/examples/linking.rs +++ b/examples/linking.rs @@ -7,7 +7,8 @@ use wasmtime::*; use wasmtime_wasi::{Wasi, WasiCtx}; fn main() -> Result<()> { - let store = Store::default(); + let engine = Engine::default(); + let store = Store::new(&engine); // First set up our linker which is going to be linking modules together. We // want our linker to have wasi available, so we set that up here as well. @@ -16,8 +17,8 @@ fn main() -> Result<()> { wasi.add_to_linker(&mut linker)?; // Load and compile our two modules - let linking1 = Module::from_file(&store, "examples/linking1.wat")?; - let linking2 = Module::from_file(&store, "examples/linking2.wat")?; + let linking1 = Module::from_file(&engine, "examples/linking1.wat")?; + let linking2 = Module::from_file(&engine, "examples/linking2.wat")?; // Instantiate our first module which only uses WASI, then register that // instance with the linker since the next linking will use it. diff --git a/examples/memory.rs b/examples/memory.rs index 6f952dbb21b1..9de8488ae2b4 100644 --- a/examples/memory.rs +++ b/examples/memory.rs @@ -13,8 +13,8 @@ fn main() -> Result<()> { // Create our `Store` context and then compile a module and create an // instance from the compiled module all in one go. let wasmtime_store = Store::default(); - let module = Module::from_file(&wasmtime_store, "examples/memory.wat")?; - let instance = Instance::new(&module, &[])?; + let module = Module::from_file(wasmtime_store.engine(), "examples/memory.wat")?; + let instance = Instance::new(&wasmtime_store, &module, &[])?; // Load up our exports from the instance let memory = instance diff --git a/examples/multi.rs b/examples/multi.rs index 2fe75b0311c1..ebdbb9101cfc 100644 --- a/examples/multi.rs +++ b/examples/multi.rs @@ -12,11 +12,12 @@ use wasmtime::*; fn main() -> Result<()> { println!("Initializing..."); - let store = Store::default(); + let engine = Engine::default(); + let store = Store::new(&engine); // Compile. println!("Compiling module..."); - let module = Module::from_file(&store, "examples/multi.wat")?; + let module = Module::from_file(&engine, "examples/multi.wat")?; // Create external print functions. println!("Creating callback..."); @@ -35,7 +36,7 @@ fn main() -> Result<()> { // Instantiate. println!("Instantiating module..."); - let instance = Instance::new(&module, &[callback_func.into()])?; + let instance = Instance::new(&store, &module, &[callback_func.into()])?; // Extract exports. println!("Extracting export..."); diff --git a/examples/threads.rs b/examples/threads.rs index 5566f7fd4f79..3d3ffe8e573a 100644 --- a/examples/threads.rs +++ b/examples/threads.rs @@ -1,7 +1,6 @@ // You can execute this example with `cargo run --example threads` use anyhow::{format_err, Result}; -use std::sync::Arc; use std::thread; use std::time; use wasmtime::*; @@ -14,9 +13,8 @@ fn print_message(_: Caller<'_>, args: &[Val], _: &mut [Val]) -> Result<(), Trap> Ok(()) } -fn run(engine: &Engine, module: SendableModule, id: i32) -> Result<()> { +fn run(engine: &Engine, module: Module, id: i32) -> Result<()> { let store = Store::new(&engine); - let module = module.place_into(&store); // Create external print functions. println!("Creating callback..."); @@ -28,7 +26,7 @@ fn run(engine: &Engine, module: SendableModule, id: i32) -> Result<()> { // Instantiate. println!("Instantiating module..."); - let instance = Instance::new(&module, &[callback_func.into(), id_global.into()])?; + let instance = Instance::new(&store, &module, &[callback_func.into(), id_global.into()])?; // Extract exports. println!("Extracting export..."); @@ -47,17 +45,16 @@ fn run(engine: &Engine, module: SendableModule, id: i32) -> Result<()> { fn main() -> Result<()> { println!("Initializing..."); - let engine = Arc::new(Engine::default()); - let store = Store::new(&engine); + let engine = Engine::default(); // Compile. println!("Compiling module..."); - let module = Module::from_file(&store, "examples/threads.wat")?; + let module = Module::from_file(&engine, "examples/threads.wat")?; let mut children = Vec::new(); for id in 0..N_THREADS { let engine = engine.clone(); - let module = module.share(); + let module = module.clone(); children.push(thread::spawn(move || { run(&engine, module, id).expect("Success"); })); diff --git a/examples/wasi/main.rs b/examples/wasi/main.rs index c663e9527751..35cb94813567 100644 --- a/examples/wasi/main.rs +++ b/examples/wasi/main.rs @@ -18,7 +18,7 @@ fn main() -> Result<()> { wasi.add_to_linker(&mut linker)?; // Instantiate our module with the imports we've created, and run it. - let module = Module::from_file(&store, "target/wasm32-wasi/debug/wasi.wasm")?; + let module = Module::from_file(store.engine(), "target/wasm32-wasi/debug/wasi.wasm")?; linker.module("", &module)?; linker.get_default("")?.get0::<()>()?()?; diff --git a/src/commands/run.rs b/src/commands/run.rs index 0e3d3e466111..d81ba5669188 100644 --- a/src/commands/run.rs +++ b/src/commands/run.rs @@ -141,7 +141,7 @@ impl RunCommand { // Load the preload wasm modules. for (name, path) in self.preloads.iter() { // Read the wasm module binary either as `*.wat` or a raw binary - let module = Module::from_file(linker.store(), path)?; + let module = Module::from_file(&engine, path)?; // Add the module's functions to the linker. linker.module(name, &module).context(format!( @@ -247,7 +247,7 @@ impl RunCommand { // Read the wasm module binary either as `*.wat` or a raw binary. // Use "" as a default module name. - let module = Module::from_file(linker.store(), &self.module)?; + let module = Module::from_file(linker.store().engine(), &self.module)?; linker .module("", &module) .context(format!("failed to instantiate {:?}", self.module))?; diff --git a/tests/all/custom_signal_handler.rs b/tests/all/custom_signal_handler.rs index 990c2af3781b..99049f888636 100644 --- a/tests/all/custom_signal_handler.rs +++ b/tests/all/custom_signal_handler.rs @@ -90,8 +90,8 @@ mod tests { fn test_custom_signal_handler_single_instance() -> Result<()> { let engine = Engine::new(&Config::default()); let store = Store::new(&engine); - let module = Module::new(&store, WAT1)?; - let instance = Instance::new(&module, &[])?; + let module = Module::new(&engine, WAT1)?; + let instance = Instance::new(&store, &module, &[])?; let (base, length) = set_up_memory(&instance); unsafe { @@ -150,11 +150,11 @@ mod tests { fn test_custom_signal_handler_multiple_instances() -> Result<()> { let engine = Engine::new(&Config::default()); let store = Store::new(&engine); - let module = Module::new(&store, WAT1)?; + let module = Module::new(&engine, WAT1)?; // Set up multiple instances - let instance1 = Instance::new(&module, &[])?; + let instance1 = Instance::new(&store, &module, &[])?; let instance1_handler_triggered = Rc::new(AtomicBool::new(false)); unsafe { @@ -196,7 +196,7 @@ mod tests { ); } - let instance2 = Instance::new(&module, &[]).expect("failed to instantiate module"); + let instance2 = Instance::new(&store, &module, &[]).expect("failed to instantiate module"); let instance2_handler_triggered = Rc::new(AtomicBool::new(false)); unsafe { @@ -244,8 +244,8 @@ mod tests { let store = Store::new(&engine); // instance1 which defines 'read' - let module1 = Module::new(&store, WAT1)?; - let instance1 = Instance::new(&module1, &[])?; + let module1 = Module::new(&engine, WAT1)?; + let instance1 = Instance::new(&store, &module1, &[])?; let (base1, length1) = set_up_memory(&instance1); unsafe { store.set_signal_handler(move |signum, siginfo, _| { @@ -258,8 +258,8 @@ mod tests { let instance1_read = instance1_exports.next().unwrap(); // instance2 which calls 'instance1.read' - let module2 = Module::new(&store, WAT2)?; - let instance2 = Instance::new(&module2, &[instance1_read.into_extern()])?; + let module2 = Module::new(&engine, WAT2)?; + let instance2 = Instance::new(&store, &module2, &[instance1_read.into_extern()])?; // since 'instance2.run' calls 'instance1.read' we need to set up the signal handler to handle // SIGSEGV originating from within the memory of instance1 unsafe { diff --git a/tests/all/externals.rs b/tests/all/externals.rs index 0919f1368544..60498005bf4e 100644 --- a/tests/all/externals.rs +++ b/tests/all/externals.rs @@ -77,8 +77,9 @@ fn bad_tables() { fn cross_store() -> anyhow::Result<()> { let mut cfg = Config::new(); cfg.wasm_reference_types(true); - let store1 = Store::new(&Engine::new(&cfg)); - let store2 = Store::new(&Engine::new(&cfg)); + let engine = Engine::new(&cfg); + let store1 = Store::new(&engine); + let store2 = Store::new(&engine); // ============ Cross-store instantiation ============== @@ -90,17 +91,17 @@ fn cross_store() -> anyhow::Result<()> { let ty = TableType::new(ValType::FuncRef, Limits::new(1, None)); let table = Table::new(&store2, ty, Val::ExternRef(ExternRef::Null))?; - let need_func = Module::new(&store1, r#"(module (import "" "" (func)))"#)?; - assert!(Instance::new(&need_func, &[func.into()]).is_err()); + let need_func = Module::new(&engine, r#"(module (import "" "" (func)))"#)?; + assert!(Instance::new(&store1, &need_func, &[func.into()]).is_err()); - let need_global = Module::new(&store1, r#"(module (import "" "" (global i32)))"#)?; - assert!(Instance::new(&need_global, &[global.into()]).is_err()); + let need_global = Module::new(&engine, r#"(module (import "" "" (global i32)))"#)?; + assert!(Instance::new(&store1, &need_global, &[global.into()]).is_err()); - let need_table = Module::new(&store1, r#"(module (import "" "" (table 1 funcref)))"#)?; - assert!(Instance::new(&need_table, &[table.into()]).is_err()); + let need_table = Module::new(&engine, r#"(module (import "" "" (table 1 funcref)))"#)?; + assert!(Instance::new(&store1, &need_table, &[table.into()]).is_err()); - let need_memory = Module::new(&store1, r#"(module (import "" "" (memory 1)))"#)?; - assert!(Instance::new(&need_memory, &[memory.into()]).is_err()); + let need_memory = Module::new(&engine, r#"(module (import "" "" (memory 1)))"#)?; + assert!(Instance::new(&store1, &need_memory, &[memory.into()]).is_err()); // ============ Cross-store globals ============== @@ -126,7 +127,7 @@ fn cross_store() -> anyhow::Result<()> { // ============ Cross-store funcs ============== // TODO: need to actually fill this out once we support externref params/locals - // let module = Module::new(&store1, r#"(module (func (export "a") (param funcref)))"#)?; + // let module = Module::new(&engine, r#"(module (func (export "a") (param funcref)))"#)?; Ok(()) } diff --git a/tests/all/func.rs b/tests/all/func.rs index 16da165bab56..7aee8b4a64af 100644 --- a/tests/all/func.rs +++ b/tests/all/func.rs @@ -61,8 +61,8 @@ fn dtor_delayed() -> Result<()> { assert_eq!(HITS.load(SeqCst), 0); let wasm = wat::parse_str(r#"(import "" "" (func))"#)?; - let module = Module::new(&store, &wasm)?; - let instance = Instance::new(&module, &[func.into()])?; + let module = Module::new(store.engine(), &wasm)?; + let instance = Instance::new(&store, &module, &[func.into()])?; assert_eq!(HITS.load(SeqCst), 0); drop((instance, module, store)); assert_eq!(HITS.load(SeqCst), 1); @@ -142,8 +142,9 @@ fn import_works() -> Result<()> { "#, )?; let store = Store::default(); - let module = Module::new(&store, &wasm)?; + let module = Module::new(store.engine(), &wasm)?; Instance::new( + &store, &module, &[ Func::wrap(&store, || { @@ -195,8 +196,9 @@ fn trap_import() -> Result<()> { "#, )?; let store = Store::default(); - let module = Module::new(&store, &wasm)?; + let module = Module::new(store.engine(), &wasm)?; let trap = Instance::new( + &store, &module, &[Func::wrap(&store, || -> Result<(), Trap> { Err(Trap::new("foo")) }).into()], ) @@ -261,7 +263,7 @@ fn get_from_signature() { fn get_from_module() -> anyhow::Result<()> { let store = Store::default(); let module = Module::new( - &store, + store.engine(), r#" (module (func (export "f0")) @@ -272,7 +274,7 @@ fn get_from_module() -> anyhow::Result<()> { "#, )?; - let instance = Instance::new(&module, &[])?; + let instance = Instance::new(&store, &module, &[])?; let f0 = instance.get_func("f0").unwrap(); assert!(f0.get0::<()>().is_ok()); assert!(f0.get0::().is_err()); @@ -340,7 +342,7 @@ fn caller_memory() -> anyhow::Result<()> { assert!(c.get_export("x").is_none()); }); let module = Module::new( - &store, + store.engine(), r#" (module (import "" "" (func $f)) @@ -349,13 +351,13 @@ fn caller_memory() -> anyhow::Result<()> { "#, )?; - Instance::new(&module, &[f.into()])?; + Instance::new(&store, &module, &[f.into()])?; let f = Func::wrap(&store, |c: Caller<'_>| { assert!(c.get_export("memory").is_some()); }); let module = Module::new( - &store, + store.engine(), r#" (module (import "" "" (func $f)) @@ -365,7 +367,7 @@ fn caller_memory() -> anyhow::Result<()> { "#, )?; - Instance::new(&module, &[f.into()])?; + Instance::new(&store, &module, &[f.into()])?; let f = Func::wrap(&store, |c: Caller<'_>| { assert!(c.get_export("m").is_some()); @@ -374,7 +376,7 @@ fn caller_memory() -> anyhow::Result<()> { assert!(c.get_export("t").is_none()); }); let module = Module::new( - &store, + store.engine(), r#" (module (import "" "" (func $f)) @@ -387,7 +389,7 @@ fn caller_memory() -> anyhow::Result<()> { "#, )?; - Instance::new(&module, &[f.into()])?; + Instance::new(&store, &module, &[f.into()])?; Ok(()) } diff --git a/tests/all/globals.rs b/tests/all/globals.rs index d0e6896c1b98..3a7c8b488cf1 100644 --- a/tests/all/globals.rs +++ b/tests/all/globals.rs @@ -63,19 +63,19 @@ fn mutability() -> anyhow::Result<()> { fn use_after_drop() -> anyhow::Result<()> { let store = Store::default(); let module = Module::new( - &store, + store.engine(), r#" (module (global (export "foo") (mut i32) (i32.const 100))) "#, )?; - let instance = Instance::new(&module, &[])?; + let instance = Instance::new(&store, &module, &[])?; let g = instance.get_global("foo").unwrap(); assert_eq!(g.get().i32(), Some(100)); g.set(101.into())?; drop(instance); assert_eq!(g.get().i32(), Some(101)); - Instance::new(&module, &[])?; + Instance::new(&store, &module, &[])?; assert_eq!(g.get().i32(), Some(101)); drop(module); assert_eq!(g.get().i32(), Some(101)); diff --git a/tests/all/iloop.rs b/tests/all/iloop.rs index abfe5e4b3de2..23e6f85aa8d3 100644 --- a/tests/all/iloop.rs +++ b/tests/all/iloop.rs @@ -19,14 +19,14 @@ fn hugely_recursive_module(store: &Store) -> anyhow::Result { } wat.push_str("(func call 0)\n"); - Module::new(&store, &wat) + Module::new(store.engine(), &wat) } #[test] fn loops_interruptable() -> anyhow::Result<()> { let store = interruptable_store(); - let module = Module::new(&store, r#"(func (export "loop") (loop br 0))"#)?; - let instance = Instance::new(&module, &[])?; + let module = Module::new(store.engine(), r#"(func (export "loop") (loop br 0))"#)?; + let instance = Instance::new(&store, &module, &[])?; let iloop = instance.get_func("loop").unwrap().get0::<()>()?; store.interrupt_handle()?.interrupt(); let trap = iloop().unwrap_err(); @@ -39,7 +39,7 @@ fn functions_interruptable() -> anyhow::Result<()> { let store = interruptable_store(); let module = hugely_recursive_module(&store)?; let func = Func::wrap(&store, || {}); - let instance = Instance::new(&module, &[func.into()])?; + let instance = Instance::new(&store, &module, &[func.into()])?; let iloop = instance.get_func("loop").unwrap().get0::<()>()?; store.interrupt_handle()?.interrupt(); let trap = iloop().unwrap_err(); @@ -59,7 +59,7 @@ fn loop_interrupt_from_afar() -> anyhow::Result<()> { static HITS: AtomicUsize = AtomicUsize::new(0); let store = interruptable_store(); let module = Module::new( - &store, + store.engine(), r#" (import "" "" (func)) @@ -73,7 +73,7 @@ fn loop_interrupt_from_afar() -> anyhow::Result<()> { let func = Func::wrap(&store, || { HITS.fetch_add(1, SeqCst); }); - let instance = Instance::new(&module, &[func.into()])?; + let instance = Instance::new(&store, &module, &[func.into()])?; // Use the instance's interrupt handle to wait for it to enter the loop long // enough and then we signal an interrupt happens. @@ -109,7 +109,7 @@ fn function_interrupt_from_afar() -> anyhow::Result<()> { let func = Func::wrap(&store, || { HITS.fetch_add(1, SeqCst); }); - let instance = Instance::new(&module, &[func.into()])?; + let instance = Instance::new(&store, &module, &[func.into()])?; // Use the instance's interrupt handle to wait for it to enter the loop long // enough and then we signal an interrupt happens. diff --git a/tests/all/import_calling_export.rs b/tests/all/import_calling_export.rs index 7affdd8759bc..6305af2e3406 100644 --- a/tests/all/import_calling_export.rs +++ b/tests/all/import_calling_export.rs @@ -17,7 +17,7 @@ fn test_import_calling_export() { "#; let store = Store::default(); - let module = Module::new(&store, WAT).expect("failed to create module"); + let module = Module::new(store.engine(), WAT).expect("failed to create module"); let other = Rc::new(RefCell::new(None::)); let other2 = Rc::downgrade(&other); @@ -40,7 +40,7 @@ fn test_import_calling_export() { let imports = vec![callback_func.into()]; let instance = - Instance::new(&module, imports.as_slice()).expect("failed to instantiate module"); + Instance::new(&store, &module, imports.as_slice()).expect("failed to instantiate module"); let run_func = instance .get_func("run") @@ -67,7 +67,7 @@ fn test_returns_incorrect_type() -> Result<()> { "#; let store = Store::default(); - let module = Module::new(&store, WAT)?; + let module = Module::new(store.engine(), WAT)?; let callback_func = Func::new( &store, @@ -80,7 +80,7 @@ fn test_returns_incorrect_type() -> Result<()> { ); let imports = vec![callback_func.into()]; - let instance = Instance::new(&module, imports.as_slice())?; + let instance = Instance::new(&store, &module, imports.as_slice())?; let run_func = instance .get_func("run") diff --git a/tests/all/import_indexes.rs b/tests/all/import_indexes.rs index d13d100a9f0f..d9cd06cd6694 100644 --- a/tests/all/import_indexes.rs +++ b/tests/all/import_indexes.rs @@ -15,7 +15,7 @@ fn same_import_names_still_distinct() -> anyhow::Result<()> { "#; let store = Store::default(); - let module = Module::new(&store, WAT)?; + let module = Module::new(store.engine(), WAT)?; let imports = [ Func::new( @@ -41,7 +41,7 @@ fn same_import_names_still_distinct() -> anyhow::Result<()> { ) .into(), ]; - let instance = Instance::new(&module, &imports)?; + let instance = Instance::new(&store, &module, &imports)?; let func = instance.get_func("foo").unwrap(); let results = func.call(&[])?; diff --git a/tests/all/instance.rs b/tests/all/instance.rs index c0f3db86a296..83ee52b22744 100644 --- a/tests/all/instance.rs +++ b/tests/all/instance.rs @@ -4,10 +4,10 @@ use wasmtime::*; #[test] fn wrong_import_numbers() -> Result<()> { let store = Store::default(); - let module = Module::new(&store, r#"(module (import "" "" (func)))"#)?; + let module = Module::new(store.engine(), r#"(module (import "" "" (func)))"#)?; - assert!(Instance::new(&module, &[]).is_err()); + assert!(Instance::new(&store, &module, &[]).is_err()); let func = Func::wrap(&store, || {}); - assert!(Instance::new(&module, &[func.clone().into(), func.into()]).is_err()); + assert!(Instance::new(&store, &module, &[func.clone().into(), func.into()]).is_err()); Ok(()) } diff --git a/tests/all/invoke_func_via_table.rs b/tests/all/invoke_func_via_table.rs index 8f59fb17d8d5..a73f7c1c404d 100644 --- a/tests/all/invoke_func_via_table.rs +++ b/tests/all/invoke_func_via_table.rs @@ -13,8 +13,8 @@ fn test_invoke_func_via_table() -> Result<()> { (elem (i32.const 0) $f) ) "#; - let module = Module::new(&store, wat).context("> Error compiling module!")?; - let instance = Instance::new(&module, &[]).context("> Error instantiating module!")?; + let module = Module::new(store.engine(), wat).context("> Error compiling module!")?; + let instance = Instance::new(&store, &module, &[]).context("> Error instantiating module!")?; let f = instance .get_table("table") diff --git a/tests/all/linker.rs b/tests/all/linker.rs index b84d7e9c1d36..286ad40230e8 100644 --- a/tests/all/linker.rs +++ b/tests/all/linker.rs @@ -5,13 +5,16 @@ use wasmtime::*; fn link_undefined() -> Result<()> { let store = Store::default(); let linker = Linker::new(&store); - let module = Module::new(&store, r#"(module (import "" "" (func)))"#)?; + let module = Module::new(store.engine(), r#"(module (import "" "" (func)))"#)?; assert!(linker.instantiate(&module).is_err()); - let module = Module::new(&store, r#"(module (import "" "" (global i32)))"#)?; + let module = Module::new(store.engine(), r#"(module (import "" "" (global i32)))"#)?; assert!(linker.instantiate(&module).is_err()); - let module = Module::new(&store, r#"(module (import "" "" (memory 1)))"#)?; + let module = Module::new(store.engine(), r#"(module (import "" "" (memory 1)))"#)?; assert!(linker.instantiate(&module).is_err()); - let module = Module::new(&store, r#"(module (import "" "" (table 1 funcref)))"#)?; + let module = Module::new( + store.engine(), + r#"(module (import "" "" (table 1 funcref)))"#, + )?; assert!(linker.instantiate(&module).is_err()); Ok(()) } @@ -71,7 +74,7 @@ fn interposition() -> Result<()> { let mut linker = Linker::new(&store); linker.allow_shadowing(true); let mut module = Module::new( - &store, + store.engine(), r#"(module (func (export "export") (result i32) (i32.const 7)))"#, )?; for _ in 0..4 { @@ -82,7 +85,7 @@ fn interposition() -> Result<()> { instance.get_export("export").unwrap().clone(), )?; module = Module::new( - &store, + store.engine(), r#"(module (import "red" "green" (func (result i32))) (func (export "export") (result i32) (i32.mul (call 0) (i32.const 2))) diff --git a/tests/all/memory_creator.rs b/tests/all/memory_creator.rs index 013b68b02f1e..9fa8a647ba5d 100644 --- a/tests/all/memory_creator.rs +++ b/tests/all/memory_creator.rs @@ -143,14 +143,14 @@ mod not_for_windows { fn host_memory() -> anyhow::Result<()> { let (store, mem_creator) = config(); let module = Module::new( - &store, + store.engine(), r#" (module (memory (export "memory") 1) ) "#, )?; - Instance::new(&module, &[])?; + Instance::new(&store, &module, &[])?; assert_eq!(*mem_creator.num_created_memories.lock().unwrap(), 1); @@ -161,7 +161,7 @@ mod not_for_windows { fn host_memory_grow() -> anyhow::Result<()> { let (store, mem_creator) = config(); let module = Module::new( - &store, + store.engine(), r#" (module (func $f (drop (memory.grow (i32.const 1)))) @@ -171,8 +171,8 @@ mod not_for_windows { "#, )?; - let instance1 = Instance::new(&module, &[])?; - let instance2 = Instance::new(&module, &[])?; + let instance1 = Instance::new(&store, &module, &[])?; + let instance2 = Instance::new(&store, &module, &[])?; assert_eq!(*mem_creator.num_created_memories.lock().unwrap(), 2); diff --git a/tests/all/name.rs b/tests/all/name.rs index d6cea5a50c65..0b1c6e5e8645 100644 --- a/tests/all/name.rs +++ b/tests/all/name.rs @@ -2,14 +2,14 @@ use wasmtime::*; #[test] fn test_module_no_name() -> anyhow::Result<()> { - let store = Store::default(); + let engine = Engine::default(); let wat = r#" (module (func (export "run") (nop)) ) "#; - let module = Module::new(&store, wat)?; + let module = Module::new(&engine, wat)?; assert_eq!(module.name(), None); Ok(()) @@ -17,17 +17,17 @@ fn test_module_no_name() -> anyhow::Result<()> { #[test] fn test_module_name() -> anyhow::Result<()> { - let store = Store::default(); + let engine = Engine::default(); let wat = r#" (module $from_name_section (func (export "run") (nop)) ) "#; - let module = Module::new(&store, wat)?; + let module = Module::new(&engine, wat)?; assert_eq!(module.name(), Some("from_name_section")); - let module = Module::new_with_name(&store, wat, "override")?; + let module = Module::new_with_name(&engine, wat, "override")?; assert_eq!(module.name(), Some("override")); Ok(()) diff --git a/tests/all/stack_overflow.rs b/tests/all/stack_overflow.rs index 9d63dbdc4ca8..97e9dc1a0882 100644 --- a/tests/all/stack_overflow.rs +++ b/tests/all/stack_overflow.rs @@ -12,7 +12,7 @@ fn host_always_has_some_stack() -> anyhow::Result<()> { // Create a module that's infinitely recursive, but calls the host on each // level of wasm stack to always test how much host stack we have left. let module = Module::new( - &store, + store.engine(), r#" (module (import "" "" (func $host)) @@ -23,7 +23,7 @@ fn host_always_has_some_stack() -> anyhow::Result<()> { "#, )?; let func = Func::wrap(&store, test_host_stack); - let instance = Instance::new(&module, &[func.into()])?; + let instance = Instance::new(&store, &module, &[func.into()])?; let foo = instance.get_func("foo").unwrap().get0::<()>()?; // Make sure that our function traps and the trap says that the call stack diff --git a/tests/all/traps.rs b/tests/all/traps.rs index f4ae458f4804..ed181f1ddd64 100644 --- a/tests/all/traps.rs +++ b/tests/all/traps.rs @@ -12,11 +12,11 @@ fn test_trap_return() -> Result<()> { ) "#; - let module = Module::new(&store, wat)?; + let module = Module::new(store.engine(), wat)?; let hello_type = FuncType::new(Box::new([]), Box::new([])); let hello_func = Func::new(&store, hello_type, |_, _, _| Err(Trap::new("test 123"))); - let instance = Instance::new(&module, &[hello_func.into()])?; + let instance = Instance::new(&store, &module, &[hello_func.into()])?; let run_func = instance.get_func("run").expect("expected function export"); let e = run_func @@ -41,8 +41,8 @@ fn test_trap_trace() -> Result<()> { ) "#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &[])?; + let module = Module::new(store.engine(), wat)?; + let instance = Instance::new(&store, &module, &[])?; let run_func = instance.get_func("run").expect("expected function export"); let e = run_func @@ -87,8 +87,8 @@ fn test_trap_trace_cb() -> Result<()> { let fn_type = FuncType::new(Box::new([]), Box::new([])); let fn_func = Func::new(&store, fn_type, |_, _, _| Err(Trap::new("cb throw"))); - let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &[fn_func.into()])?; + let module = Module::new(store.engine(), wat)?; + let instance = Instance::new(&store, &module, &[fn_func.into()])?; let run_func = instance.get_func("run").expect("expected function export"); let e = run_func @@ -118,8 +118,8 @@ fn test_trap_stack_overflow() -> Result<()> { ) "#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &[])?; + let module = Module::new(store.engine(), wat)?; + let instance = Instance::new(&store, &module, &[])?; let run_func = instance.get_func("run").expect("expected function export"); let e = run_func @@ -153,8 +153,8 @@ fn trap_display_pretty() -> Result<()> { ) "#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &[])?; + let module = Module::new(store.engine(), wat)?; + let instance = Instance::new(&store, &module, &[])?; let run_func = instance.get_func("bar").expect("expected function export"); let e = run_func.call(&[]).err().expect("error calling function"); @@ -185,8 +185,8 @@ fn trap_display_multi_module() -> Result<()> { ) "#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &[])?; + let module = Module::new(store.engine(), wat)?; + let instance = Instance::new(&store, &module, &[])?; let bar = instance.get_export("bar").unwrap(); let wat = r#" @@ -196,8 +196,8 @@ fn trap_display_multi_module() -> Result<()> { (func (export "bar2") call $middle) ) "#; - let module = Module::new(&store, wat)?; - let instance = Instance::new(&module, &[bar])?; + let module = Module::new(store.engine(), wat)?; + let instance = Instance::new(&store, &module, &[bar])?; let bar2 = instance.get_func("bar2").expect("expected function export"); let e = bar2.call(&[]).err().expect("error calling function"); @@ -230,10 +230,12 @@ fn trap_start_function_import() -> Result<()> { "#, )?; - let module = Module::new(&store, &binary)?; + let module = Module::new(store.engine(), &binary)?; let sig = FuncType::new(Box::new([]), Box::new([])); let func = Func::new(&store, sig, |_, _, _| Err(Trap::new("user trap"))); - let err = Instance::new(&module, &[func.into()]).err().unwrap(); + let err = Instance::new(&store, &module, &[func.into()]) + .err() + .unwrap(); assert_eq!(err.downcast_ref::().unwrap().message(), "user trap"); Ok(()) } @@ -253,10 +255,11 @@ fn rust_panic_import() -> Result<()> { "#, )?; - let module = Module::new(&store, &binary)?; + let module = Module::new(store.engine(), &binary)?; let sig = FuncType::new(Box::new([]), Box::new([])); let func = Func::new(&store, sig, |_, _, _| panic!("this is a panic")); let instance = Instance::new( + &store, &module, &[ func.into(), @@ -295,18 +298,18 @@ fn rust_panic_start_function() -> Result<()> { "#, )?; - let module = Module::new(&store, &binary)?; + let module = Module::new(store.engine(), &binary)?; let sig = FuncType::new(Box::new([]), Box::new([])); let func = Func::new(&store, sig, |_, _, _| panic!("this is a panic")); let err = panic::catch_unwind(AssertUnwindSafe(|| { - drop(Instance::new(&module, &[func.into()])); + drop(Instance::new(&store, &module, &[func.into()])); })) .unwrap_err(); assert_eq!(err.downcast_ref::<&'static str>(), Some(&"this is a panic")); let func = Func::wrap(&store, || panic!("this is another panic")); let err = panic::catch_unwind(AssertUnwindSafe(|| { - drop(Instance::new(&module, &[func.into()])); + drop(Instance::new(&store, &module, &[func.into()])); })) .unwrap_err(); assert_eq!( @@ -328,8 +331,8 @@ fn mismatched_arguments() -> Result<()> { "#, )?; - let module = Module::new(&store, &binary)?; - let instance = Instance::new(&module, &[])?; + let module = Module::new(store.engine(), &binary)?; + let instance = Instance::new(&store, &module, &[])?; let func = instance.get_func("foo").unwrap(); assert_eq!( func.call(&[]).unwrap_err().to_string(), @@ -367,8 +370,8 @@ fn call_signature_mismatch() -> Result<()> { "#, )?; - let module = Module::new(&store, &binary)?; - let err = Instance::new(&module, &[]) + let module = Module::new(store.engine(), &binary)?; + let err = Instance::new(&store, &module, &[]) .err() .unwrap() .downcast::() @@ -391,8 +394,8 @@ fn start_trap_pretty() -> Result<()> { ) "#; - let module = Module::new(&store, wat)?; - let e = match Instance::new(&module, &[]) { + let module = Module::new(store.engine(), wat)?; + let e = match Instance::new(&store, &module, &[]) { Ok(_) => panic!("expected failure"), Err(e) => e.downcast::()?, }; @@ -414,8 +417,8 @@ wasm backtrace: #[test] fn present_after_module_drop() -> Result<()> { let store = Store::default(); - let module = Module::new(&store, r#"(func (export "foo") unreachable)"#)?; - let instance = Instance::new(&module, &[])?; + let module = Module::new(store.engine(), r#"(func (export "foo") unreachable)"#)?; + let instance = Instance::new(&store, &module, &[])?; let func = instance.get_func("foo").unwrap(); println!("asserting before we drop modules"); diff --git a/tests/host_segfault.rs b/tests/host_segfault.rs index 18849672873a..30f3a4f9ecea 100644 --- a/tests/host_segfault.rs +++ b/tests/host_segfault.rs @@ -48,22 +48,25 @@ fn main() { let tests: &[(&str, fn())] = &[ ("normal segfault", || segfault()), ("make instance then segfault", || { - let store = Store::default(); - let module = Module::new(&store, "(module)").unwrap(); - let _instance = Instance::new(&module, &[]).unwrap(); + let engine = Engine::default(); + let store = Store::new(&engine); + let module = Module::new(&engine, "(module)").unwrap(); + let _instance = Instance::new(&store, &module, &[]).unwrap(); segfault(); }), ("make instance then overrun the stack", || { - let store = Store::default(); - let module = Module::new(&store, "(module)").unwrap(); - let _instance = Instance::new(&module, &[]).unwrap(); + let engine = Engine::default(); + let store = Store::new(&engine); + let module = Module::new(&engine, "(module)").unwrap(); + let _instance = Instance::new(&store, &module, &[]).unwrap(); println!("stack overrun: {}", overrun_the_stack()); }), ("segfault in a host function", || { - let store = Store::default(); - let module = Module::new(&store, r#"(import "" "" (func)) (start 0)"#).unwrap(); + let engine = Engine::default(); + let store = Store::new(&engine); + let module = Module::new(&engine, r#"(import "" "" (func)) (start 0)"#).unwrap(); let segfault = Func::wrap(&store, || segfault()); - Instance::new(&module, &[segfault.into()]).unwrap(); + Instance::new(&store, &module, &[segfault.into()]).unwrap(); }), ]; match env::var(VAR_NAME) { From 51b901b32b7a1b9ca5fa12a931bca45db1fa8dbf Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 27 May 2020 14:55:36 -0500 Subject: [PATCH 17/35] fix docs --- crates/c-api/src/module.rs | 38 ++++++++++++++++++-------------------- docs/lang-rust.md | 2 +- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/crates/c-api/src/module.rs b/crates/c-api/src/module.rs index e7e6a1331a64..11e51b4261e5 100644 --- a/crates/c-api/src/module.rs +++ b/crates/c-api/src/module.rs @@ -51,26 +51,24 @@ pub extern "C" fn wasmtime_module_new( ret: &mut *mut wasm_module_t, ) -> Option> { let binary = binary.as_slice(); - handle_result( - Module::from_binary(store.store.borrow().engine(), binary), - |module| { - let imports = module - .imports() - .map(|i| wasm_importtype_t::new(i.module().to_owned(), i.name().to_owned(), i.ty())) - .collect::>(); - let exports = module - .exports() - .map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty())) - .collect::>(); - let module = Box::new(wasm_module_t { - store: store.store.clone(), - module: HostRef::new(module), - imports, - exports, - }); - *ret = Box::into_raw(module); - }, - ) + let store_ref = store.store.borrow(); + handle_result(Module::from_binary(store_ref.engine(), binary), |module| { + let imports = module + .imports() + .map(|i| wasm_importtype_t::new(i.module().to_owned(), i.name().to_owned(), i.ty())) + .collect::>(); + let exports = module + .exports() + .map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty())) + .collect::>(); + let module = Box::new(wasm_module_t { + store: store.store.clone(), + module: HostRef::new(module), + imports, + exports, + }); + *ret = Box::into_raw(module); + }) } #[no_mangle] diff --git a/docs/lang-rust.md b/docs/lang-rust.md index e19b644fe7bd..aeca23ae45c9 100644 --- a/docs/lang-rust.md +++ b/docs/lang-rust.md @@ -55,7 +55,7 @@ use std::error::Error; use wasmtime::*; fn main() -> Result<(), Box> { - let engine = Engine::default() + let engine = Engine::default(); // A `Store` is a sort of "global object" in a sense, but for now it suffices // to say that it's generally passed to most constructors. let store = Store::new(&engine); From 02f79f85fced92a56cbc133000a14adf0686aafb Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 27 May 2020 16:12:00 -0500 Subject: [PATCH 18/35] fix fuzz --- crates/fuzzing/src/oracles.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fuzzing/src/oracles.rs b/crates/fuzzing/src/oracles.rs index ecd6453ffb1b..7242da627d8f 100644 --- a/crates/fuzzing/src/oracles.rs +++ b/crates/fuzzing/src/oracles.rs @@ -303,7 +303,7 @@ pub fn make_api_calls(api: crate::generators::api::ApiCalls) { ApiCall::ModuleNew { id, wasm } => { log::debug!("creating module: {}", id); log_wasm(&wasm.wasm); - let module = match Module::new(store.as_ref().unwrap(), &wasm.wasm) { + let module = match Module::new(engine.as_ref().unwrap(), &wasm.wasm) { Ok(m) => m, Err(_) => continue, }; From 2009eb7f175ed033a4148140d4303da29d07b3fe Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 1 Jun 2020 10:24:23 -0500 Subject: [PATCH 19/35] jit_int comments; fix 'let _ =' lifetime --- crates/runtime/src/jit_int.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/crates/runtime/src/jit_int.rs b/crates/runtime/src/jit_int.rs index 9a7ce68d8c47..bc7d510e1a8a 100644 --- a/crates/runtime/src/jit_int.rs +++ b/crates/runtime/src/jit_int.rs @@ -47,7 +47,14 @@ extern "C" fn __jit_debug_register_code() { } lazy_static! { - pub static ref GDB_REGISTRATION: Mutex = Mutex::new(Default::default()); + // The process controls access to the __jit_debug_descriptor by itself -- + // the GDB/LLDB accesses this structure and its data at the process startup + // and when paused in __jit_debug_register_code. + // + // The GDB_REGISTRATION lock is needed for GdbJitImageRegistration to protect + // access to the __jit_debug_descriptor within this process, and `u32` is + // just a "phantom" data. + pub static ref GDB_REGISTRATION: Mutex<()> = Mutex::new(Default::default()); } /// Registeration for JIT image @@ -62,7 +69,7 @@ impl GdbJitImageRegistration { let file = Pin::new(file.into_boxed_slice()); Self { entry: unsafe { - let _ = GDB_REGISTRATION.lock().unwrap(); + let _lock = GDB_REGISTRATION.lock().unwrap(); register_gdb_jit_image(&file) }, file, @@ -78,7 +85,7 @@ impl GdbJitImageRegistration { impl Drop for GdbJitImageRegistration { fn drop(&mut self) { unsafe { - let _ = GDB_REGISTRATION.lock().unwrap(); + let _lock = GDB_REGISTRATION.lock().unwrap(); unregister_gdb_jit_image(self.entry); } } From 2f23c7f29b8fe8a8d732501c4b7b847a20212bd1 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 1 Jun 2020 11:19:30 -0500 Subject: [PATCH 20/35] Fix linker tests --- tests/all/linker.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/all/linker.rs b/tests/all/linker.rs index 10ad68dcb243..98d5541bbeef 100644 --- a/tests/all/linker.rs +++ b/tests/all/linker.rs @@ -74,7 +74,7 @@ fn function_interposition() -> Result<()> { let mut linker = Linker::new(&store); linker.allow_shadowing(true); let mut module = Module::new( - &store, + store.engine(), r#"(module (func (export "green") (result i32) (i32.const 7)))"#, )?; for _ in 0..4 { @@ -85,7 +85,7 @@ fn function_interposition() -> Result<()> { instance.get_export("green").unwrap().clone(), )?; module = Module::new( - &store, + store.engine(), r#"(module (import "red" "green" (func (result i32))) (func (export "green") (result i32) (i32.mul (call 0) (i32.const 2))) @@ -140,14 +140,14 @@ fn module_interposition() -> Result<()> { let mut linker = Linker::new(&store); linker.allow_shadowing(true); let mut module = Module::new( - &store, + store.engine(), r#"(module (func (export "export") (result i32) (i32.const 7)))"#, )?; for _ in 0..4 { let instance = linker.instantiate(&module)?; linker.instance("instance", &instance)?; module = Module::new( - &store, + store.engine(), r#"(module (import "instance" "export" (func (result i32))) (func (export "export") (result i32) (i32.mul (call 0) (i32.const 2))) From bde14b9a70e902812657a01e3252820b8b2c7555 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 1 Jun 2020 11:19:55 -0500 Subject: [PATCH 21/35] Assert Module and Compiler's Sync+Send --- crates/jit/src/compiler.rs | 5 +++++ crates/wasmtime/src/module.rs | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/crates/jit/src/compiler.rs b/crates/jit/src/compiler.rs index c88161cc5db6..e2e9f0244209 100644 --- a/crates/jit/src/compiler.rs +++ b/crates/jit/src/compiler.rs @@ -66,6 +66,11 @@ impl Compiler { } } +fn _assert_compiler_send_sync() { + fn _assert() {} + _assert::(); +} + #[allow(missing_docs)] pub struct Compilation { pub code_memory: CodeMemory, diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs index 7c1ed068c348..9133fb1afbeb 100644 --- a/crates/wasmtime/src/module.rs +++ b/crates/wasmtime/src/module.rs @@ -533,3 +533,8 @@ impl Module { return ret; } } + +fn _assert_send_sync() { + fn _assert() {} + _assert::(); +} From 3f04e736a193976a66d3e545a2f1119ea0295f91 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 1 Jun 2020 11:30:19 -0500 Subject: [PATCH 22/35] One Compiler instance per Engine --- crates/wasmtime/src/module.rs | 3 +-- crates/wasmtime/src/runtime.rs | 24 ++++++++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs index 9133fb1afbeb..0df14056ab3f 100644 --- a/crates/wasmtime/src/module.rs +++ b/crates/wasmtime/src/module.rs @@ -298,8 +298,7 @@ impl Module { } unsafe fn compile(engine: &Engine, binary: &[u8]) -> Result { - let compiled = - CompiledModule::new(&engine.get_compiler(), binary, &*engine.config().profiler)?; + let compiled = CompiledModule::new(engine.compiler(), binary, &*engine.config().profiler)?; Ok(Module { engine: engine.clone(), diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs index 3b1e96d29896..75fcdb4771c0 100644 --- a/crates/wasmtime/src/runtime.rs +++ b/crates/wasmtime/src/runtime.rs @@ -683,9 +683,10 @@ pub enum ProfilingStrategy { /// You can create an engine with default configuration settings using /// `Engine::default()`. Be sure to consult the documentation of [`Config`] for /// default settings. -#[derive(Default, Clone)] +#[derive(Clone)] pub struct Engine { config: Arc, + compiler: Arc, } impl Engine { @@ -695,6 +696,7 @@ impl Engine { debug_builtins::ensure_exported(); Engine { config: Arc::new(config.clone()), + compiler: Arc::new(Engine::build_compiler(config)), } } @@ -703,17 +705,27 @@ impl Engine { &self.config } - pub(crate) fn get_compiler(&self) -> Compiler { - let isa = native::builder().finish(settings::Flags::new(self.config.flags.clone())); + pub(crate) fn compiler(&self) -> &Compiler { + &self.compiler + } + + fn build_compiler(config: &Config) -> Compiler { + let isa = native::builder().finish(settings::Flags::new(config.flags.clone())); Compiler::new( isa, - self.config.strategy, - self.config.cache_config.clone(), - self.config.tunables.clone(), + config.strategy, + config.cache_config.clone(), + config.tunables.clone(), ) } } +impl Default for Engine { + fn default() -> Engine { + Engine::new(&Config::default()) + } +} + // Store /// A `Store` is a shared cache of information between WebAssembly modules. From 6fd50dbb290a0b4730034e0b565c4e28112b68f0 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 1 Jun 2020 11:51:53 -0500 Subject: [PATCH 23/35] Add thread safety doc --- crates/wasmtime/src/module.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs index 0df14056ab3f..1120ed6f590f 100644 --- a/crates/wasmtime/src/module.rs +++ b/crates/wasmtime/src/module.rs @@ -23,6 +23,8 @@ use wasmtime_jit::CompiledModule; /// compiling the original wasm module only once with a single [`Module`] /// instance. /// +/// The `Module` is threadsafe and safe to share accross threads. +/// /// ## Modules and `Clone` /// /// Using `clone` on a `Module` is a cheap operation. It will not create an From acc6603f5f1d89c6103cadec99ba0087f6a3ce7d Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 1 Jun 2020 13:03:56 -0500 Subject: [PATCH 24/35] check same engine constraint --- crates/c-api/src/module.rs | 11 +++++++---- crates/wasmtime/src/instance.rs | 6 +++++- crates/wasmtime/src/runtime.rs | 5 +++++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/crates/c-api/src/module.rs b/crates/c-api/src/module.rs index 11e51b4261e5..75e07a61b26a 100644 --- a/crates/c-api/src/module.rs +++ b/crates/c-api/src/module.rs @@ -2,7 +2,7 @@ use crate::{handle_result, wasmtime_error_t}; use crate::{wasm_byte_vec_t, wasm_exporttype_vec_t, wasm_importtype_vec_t}; use crate::{wasm_exporttype_t, wasm_importtype_t, wasm_store_t}; use std::ptr; -use wasmtime::{HostRef, Module, Store}; +use wasmtime::{Engine, HostRef, Module, Store}; #[repr(C)] #[derive(Clone)] @@ -119,8 +119,11 @@ pub extern "C" fn wasm_module_share(module: &wasm_module_t) -> Box Box { +) -> Option> { let module = shared_module.module.clone(); + if !Engine::same(store.store.borrow().engine(), module.engine()) { + return None; + } let imports = module .imports() .map(|i| wasm_importtype_t::new(i.module().to_owned(), i.name().to_owned(), i.ty())) @@ -129,10 +132,10 @@ pub extern "C" fn wasm_module_obtain( .exports() .map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty())) .collect::>(); - Box::new(wasm_module_t { + Some(Box::new(wasm_module_t { store: store.store.clone(), module: HostRef::new(module), imports, exports, - }) + })) } diff --git a/crates/wasmtime/src/instance.rs b/crates/wasmtime/src/instance.rs index 3458ad2bffae..559afa6a3237 100644 --- a/crates/wasmtime/src/instance.rs +++ b/crates/wasmtime/src/instance.rs @@ -1,5 +1,5 @@ use crate::trampoline::StoreInstanceHandle; -use crate::{Export, Extern, Func, Global, Memory, Module, Store, Table, Trap}; +use crate::{Engine, Export, Extern, Func, Global, Memory, Module, Store, Table, Trap}; use anyhow::{bail, Error, Result}; use std::any::Any; use std::mem; @@ -181,6 +181,10 @@ impl Instance { /// [issue]: https://github.com/bytecodealliance/wasmtime/issues/727 /// [`ExternType`]: crate::ExternType pub fn new(store: &Store, module: &Module, imports: &[Extern]) -> Result { + if !Engine::same(store.engine(), module.engine()) { + bail!("cross-`Engine` instantiation is not currently supported"); + } + let info = module.register_frame_info(); store.register_jit_code(module.compiled_module().jit_code_ranges()); diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs index 75fcdb4771c0..ae8c1f6de82d 100644 --- a/crates/wasmtime/src/runtime.rs +++ b/crates/wasmtime/src/runtime.rs @@ -718,6 +718,11 @@ impl Engine { config.tunables.clone(), ) } + + /// Returns whether the engine `a` and `b` refer to the same configuration. + pub fn same(a: &Engine, b: &Engine) -> bool { + Arc::ptr_eq(&a.config, &b.config) + } } impl Default for Engine { From b3d3eda00b9cf4c2dd52dcf5df4476d589886505 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 1 Jun 2020 15:28:29 -0500 Subject: [PATCH 25/35] Reduces amount of held Module data --- crates/jit/src/instantiate.rs | 45 +++++++++++-------- crates/runtime/src/instance.rs | 22 +++++---- crates/runtime/src/lib.rs | 2 +- crates/wasmtime/src/frame_info.rs | 15 ++++--- crates/wasmtime/src/module.rs | 2 +- .../wasmtime/src/trampoline/create_handle.rs | 13 ++---- 6 files changed, 50 insertions(+), 49 deletions(-) diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs index f6ce9c85003f..c2670ffb1f31 100644 --- a/crates/jit/src/instantiate.rs +++ b/crates/jit/src/instantiate.rs @@ -23,8 +23,8 @@ use wasmtime_environ::{ use wasmtime_profiling::ProfilingAgent; use wasmtime_runtime::VMInterrupts; use wasmtime_runtime::{ - GdbJitImageRegistration, InstanceContext, InstanceHandle, InstantiationError, - RuntimeMemoryCreator, SignatureRegistry, VMFunctionBody, VMTrampoline, + GdbJitImageRegistration, InstanceHandle, InstantiationError, RuntimeMemoryCreator, + SignatureRegistry, VMFunctionBody, VMTrampoline, }; /// An error condition while setting up a wasm instance, be it validation, @@ -54,25 +54,24 @@ struct FinishedFunctions(BoxedSlice); unsafe impl Send for FinishedFunctions {} unsafe impl Sync for FinishedFunctions {} +/// Container for data needed for an Instance function to exist. +pub struct ModuleCode { + code_memory: CodeMemory, + #[allow(dead_code)] + dbg_jit_registration: Option, +} + /// A compiled wasm module, ready to be instantiated. pub struct CompiledModule { - code_memory: CodeMemory, - module: Module, + module: Arc, + code: Arc, finished_functions: FinishedFunctions, trampolines: PrimaryMap, data_initializers: Box<[OwnedDataInitializer]>, - #[allow(dead_code)] - dbg_jit_registration: Option, traps: Traps, address_transform: ModuleAddressMap, } -impl InstanceContext for CompiledModule { - fn module(&self) -> &Module { - &self.module - } -} - impl CompiledModule { /// Compile a data buffer into a `CompiledModule`, which may then be instantiated. pub fn new<'data>( @@ -129,12 +128,14 @@ impl CompiledModule { FinishedFunctions(compilation.finished_functions.into_boxed_slice()); Ok(Self { - code_memory, - module, + module: Arc::new(module), + code: Arc::new(ModuleCode { + code_memory, + dbg_jit_registration, + }), finished_functions, trampolines: compilation.trampolines, data_initializers, - dbg_jit_registration, traps: compilation.traps, address_transform: compilation.address_transform, }) @@ -177,7 +178,8 @@ impl CompiledModule { let imports = resolve_imports(module.module(), signature_registry, resolver)?; InstanceHandle::new( - module, + module.module.clone(), + module.code.clone(), finished_functions, trampolines, imports, @@ -200,13 +202,13 @@ impl CompiledModule { } /// Return a reference to a module. - pub fn module(&self) -> &Module { + pub fn module(&self) -> &Arc { &self.module } /// Return a reference to a module. pub fn module_mut(&mut self) -> &mut Module { - &mut self.module + Arc::get_mut(&mut self.module).unwrap() } /// Returns the map of all finished JIT functions compiled for this module @@ -226,7 +228,12 @@ impl CompiledModule { /// Returns all ranges convered by JIT code. pub fn jit_code_ranges<'a>(&'a self) -> impl Iterator + 'a { - self.code_memory.published_ranges() + self.code.code_memory.published_ranges() + } + + /// Returns module's JIT code. + pub fn code(&self) -> &Arc { + &self.code } } diff --git a/crates/runtime/src/instance.rs b/crates/runtime/src/instance.rs index 4b42f6f31f63..9dc343850254 100644 --- a/crates/runtime/src/instance.rs +++ b/crates/runtime/src/instance.rs @@ -30,19 +30,16 @@ use wasmtime_environ::wasm::{ }; use wasmtime_environ::{ir, DataInitializer, EntityIndex, Module, TableElements, VMOffsets}; -/// Trait that exposes required instance resources. -pub trait InstanceContext { - /// Returns Module module. - fn module(&self) -> &Module; -} - /// A WebAssembly instance. /// /// This is repr(C) to ensure that the vmctx field is last. #[repr(C)] pub(crate) struct Instance { - /// The `ModuleGrip` this `Instance` was instantiated from. - context: Arc, + /// The `Module` this `Instance` was instantiated from. + module: Arc, + + /// The module's JIT code (if exists). + code: Arc, /// Offsets in the `vmctx` region. offsets: VMOffsets, @@ -98,7 +95,7 @@ impl Instance { } pub(crate) fn module(&self) -> &Module { - self.context.module() + &self.module } /// Return a pointer to the `VMSharedSignatureIndex`s. @@ -779,7 +776,8 @@ impl InstanceHandle { /// the `wasmtime` crate API rather than this type since that is vetted for /// safety. pub unsafe fn new( - context: Arc, + module: Arc, + code: Arc, finished_functions: BoxedSlice, trampolines: HashMap, imports: Imports, @@ -788,7 +786,6 @@ impl InstanceHandle { host_state: Box, interrupts: Arc, ) -> Result { - let module = context.module(); let tables = create_tables(&module); let memories = create_memories(&module, mem_creator.unwrap_or(&DefaultMemoryCreator {}))?; @@ -812,7 +809,8 @@ impl InstanceHandle { let handle = { let instance = Instance { - context, + module, + code, offsets, memories, tables, diff --git a/crates/runtime/src/lib.rs b/crates/runtime/src/lib.rs index 3f371ca3440c..97983cde2d4f 100644 --- a/crates/runtime/src/lib.rs +++ b/crates/runtime/src/lib.rs @@ -37,7 +37,7 @@ pub mod libcalls; pub use crate::export::*; pub use crate::imports::Imports; -pub use crate::instance::{InstanceContext, InstanceHandle, InstantiationError, LinkError}; +pub use crate::instance::{InstanceHandle, InstantiationError, LinkError}; pub use crate::jit_int::GdbJitImageRegistration; pub use crate::memory::{RuntimeLinearMemory, RuntimeMemoryCreator}; pub use crate::mmap::Mmap; diff --git a/crates/wasmtime/src/frame_info.rs b/crates/wasmtime/src/frame_info.rs index c2cf0e86f372..faf6e00c1c5d 100644 --- a/crates/wasmtime/src/frame_info.rs +++ b/crates/wasmtime/src/frame_info.rs @@ -4,7 +4,7 @@ use std::sync::{Arc, RwLock}; use wasmtime_environ::entity::EntityRef; use wasmtime_environ::ir; use wasmtime_environ::wasm::FuncIndex; -use wasmtime_environ::{FunctionAddressMap, TrapInformation}; +use wasmtime_environ::{FunctionAddressMap, Module, TrapInformation}; use wasmtime_jit::CompiledModule; lazy_static::lazy_static! { @@ -41,7 +41,9 @@ pub struct GlobalFrameInfoRegistration { struct ModuleFrameInfo { start: usize, functions: BTreeMap, - module: Arc, + module: Arc, + #[allow(dead_code)] + module_code: Arc, } struct FunctionInfo { @@ -101,9 +103,9 @@ impl GlobalFrameInfo { None => func.instr_map.start_srcloc, }; Some(FrameInfo { - module_name: module.module.module().name.clone(), + module_name: module.module.name.clone(), func_index: func.index.index() as u32, - func_name: module.module.module().func_names.get(&func.index).cloned(), + func_name: module.module.func_names.get(&func.index).cloned(), instr, func_start: func.instr_map.start_srcloc, }) @@ -146,7 +148,7 @@ impl Drop for GlobalFrameInfoRegistration { /// 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(module: Arc) -> Option { +pub fn register(module: &CompiledModule) -> Option { let mut min = usize::max_value(); let mut max = 0; let mut functions = BTreeMap::new(); @@ -191,7 +193,8 @@ pub fn register(module: Arc) -> Option &Module { - &self.0 - } -} - pub(crate) fn create_handle( module: Module, store: &Store, @@ -45,7 +37,8 @@ pub(crate) fn create_handle( unsafe { let handle = InstanceHandle::new( - Arc::new(ModuleWrapper(module)), + Arc::new(module), + Arc::new(()), finished_functions.into_boxed_slice(), trampolines, imports, From 6e1a5908e55680453af8557b04426f61edf117cc Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 1 Jun 2020 15:57:40 -0500 Subject: [PATCH 26/35] Change signatures of wasmtime_module_new/wasmtime_instance_new --- crates/c-api/include/wasmtime.h | 3 +- crates/c-api/src/instance.rs | 18 ++++------- crates/c-api/src/module.rs | 55 +++++++++++++++++---------------- examples/fib-debug/main.c | 4 +-- examples/gcd.c | 4 +-- examples/hello.c | 4 +-- examples/interrupt.c | 4 +-- examples/linking.c | 4 +-- examples/memory.c | 4 +-- examples/multi.c | 4 +-- examples/wasi/main.c | 2 +- 11 files changed, 52 insertions(+), 54 deletions(-) diff --git a/crates/c-api/include/wasmtime.h b/crates/c-api/include/wasmtime.h index 1b43f97422fd..b0c73386d905 100644 --- a/crates/c-api/include/wasmtime.h +++ b/crates/c-api/include/wasmtime.h @@ -244,6 +244,7 @@ WASM_API_EXTERN own wasmtime_error_t *wasmtime_global_set( // instance is returned), or an instance can be returned (meaning no error or // trap is returned). WASM_API_EXTERN own wasmtime_error_t *wasmtime_instance_new( + wasm_store_t *store, const wasm_module_t *module, const wasm_extern_t* const imports[], size_t num_imports, @@ -254,7 +255,7 @@ WASM_API_EXTERN own wasmtime_error_t *wasmtime_instance_new( // Similar to `wasm_module_new`, but an error is returned to return a // descriptive error message in case compilation fails. WASM_API_EXTERN own wasmtime_error_t *wasmtime_module_new( - wasm_store_t *store, + wasm_engine_t *engine, const wasm_byte_vec_t *binary, own wasm_module_t **ret ); diff --git a/crates/c-api/src/instance.rs b/crates/c-api/src/instance.rs index fce0b8d36cbd..80473731befe 100644 --- a/crates/c-api/src/instance.rs +++ b/crates/c-api/src/instance.rs @@ -3,7 +3,7 @@ use crate::{wasm_store_t, wasmtime_error_t, ExternHost}; use anyhow::Result; use std::cell::RefCell; use std::ptr; -use wasmtime::{Extern, HostRef, Instance, Store, Trap}; +use wasmtime::{Extern, HostRef, Instance, Trap}; #[repr(C)] #[derive(Clone)] @@ -34,19 +34,10 @@ pub unsafe extern "C" fn wasm_instance_new( imports: *const Box, result: Option<&mut *mut wasm_trap_t>, ) -> Option> { - let store = &store.store.borrow(); - let module_store = &wasm_module.store.borrow(); - if !Store::same(&store, module_store) { - if let Some(result) = result { - let trap = Trap::new("wasm_store_t must match store in wasm_module_t"); - let trap = Box::new(wasm_trap_t::new(trap)); - *result = Box::into_raw(trap); - } - return None; - } let mut instance = ptr::null_mut(); let mut trap = ptr::null_mut(); let err = wasmtime_instance_new( + store, wasm_module, imports, wasm_module.imports.len(), @@ -81,6 +72,7 @@ pub unsafe extern "C" fn wasm_instance_new( #[no_mangle] pub unsafe extern "C" fn wasmtime_instance_new( + store: &wasm_store_t, module: &wasm_module_t, imports: *const Box, num_imports: usize, @@ -88,6 +80,7 @@ pub unsafe extern "C" fn wasmtime_instance_new( trap_ptr: &mut *mut wasm_trap_t, ) -> Option> { _wasmtime_instance_new( + store, module, std::slice::from_raw_parts(imports, num_imports), instance_ptr, @@ -96,11 +89,13 @@ pub unsafe extern "C" fn wasmtime_instance_new( } fn _wasmtime_instance_new( + store: &wasm_store_t, module: &wasm_module_t, imports: &[Box], instance_ptr: &mut *mut wasm_instance_t, trap_ptr: &mut *mut wasm_trap_t, ) -> Option> { + let store = &store.store.borrow(); let imports = imports .iter() .map(|import| match &import.which { @@ -110,7 +105,6 @@ fn _wasmtime_instance_new( ExternHost::Memory(e) => Extern::Memory(e.borrow().clone()), }) .collect::>(); - let store = &module.store.borrow(); let module = &module.module.borrow(); handle_instantiate( Instance::new(store, module, &imports), diff --git a/crates/c-api/src/module.rs b/crates/c-api/src/module.rs index 75e07a61b26a..dcdf8bf6e9ea 100644 --- a/crates/c-api/src/module.rs +++ b/crates/c-api/src/module.rs @@ -1,13 +1,13 @@ -use crate::{handle_result, wasmtime_error_t}; -use crate::{wasm_byte_vec_t, wasm_exporttype_vec_t, wasm_importtype_vec_t}; -use crate::{wasm_exporttype_t, wasm_importtype_t, wasm_store_t}; +use crate::{ + handle_result, wasm_byte_vec_t, wasm_engine_t, wasm_exporttype_t, wasm_exporttype_vec_t, + wasm_importtype_t, wasm_importtype_vec_t, wasm_store_t, wasmtime_error_t, +}; use std::ptr; -use wasmtime::{Engine, HostRef, Module, Store}; +use wasmtime::{Engine, HostRef, Module}; #[repr(C)] #[derive(Clone)] pub struct wasm_module_t { - pub(crate) store: HostRef, pub(crate) module: HostRef, pub(crate) imports: Vec, pub(crate) exports: Vec, @@ -35,7 +35,10 @@ pub extern "C" fn wasm_module_new( binary: &wasm_byte_vec_t, ) -> Option> { let mut ret = ptr::null_mut(); - match wasmtime_module_new(store, binary, &mut ret) { + let engine = wasm_engine_t { + engine: HostRef::new(store.store.borrow().engine().clone()), + }; + match wasmtime_module_new(&engine, binary, &mut ret) { Some(_err) => None, None => { assert!(!ret.is_null()); @@ -46,29 +49,30 @@ pub extern "C" fn wasm_module_new( #[no_mangle] pub extern "C" fn wasmtime_module_new( - store: &wasm_store_t, + engine: &wasm_engine_t, binary: &wasm_byte_vec_t, ret: &mut *mut wasm_module_t, ) -> Option> { let binary = binary.as_slice(); - let store_ref = store.store.borrow(); - handle_result(Module::from_binary(store_ref.engine(), binary), |module| { - let imports = module - .imports() - .map(|i| wasm_importtype_t::new(i.module().to_owned(), i.name().to_owned(), i.ty())) - .collect::>(); - let exports = module - .exports() - .map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty())) - .collect::>(); - let module = Box::new(wasm_module_t { - store: store.store.clone(), - module: HostRef::new(module), - imports, - exports, - }); - *ret = Box::into_raw(module); - }) + handle_result( + Module::from_binary(&engine.engine.borrow(), binary), + |module| { + let imports = module + .imports() + .map(|i| wasm_importtype_t::new(i.module().to_owned(), i.name().to_owned(), i.ty())) + .collect::>(); + let exports = module + .exports() + .map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty())) + .collect::>(); + let module = Box::new(wasm_module_t { + module: HostRef::new(module), + imports, + exports, + }); + *ret = Box::into_raw(module); + }, + ) } #[no_mangle] @@ -133,7 +137,6 @@ pub extern "C" fn wasm_module_obtain( .map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty())) .collect::>(); Some(Box::new(wasm_module_t { - store: store.store.clone(), module: HostRef::new(module), imports, exports, diff --git a/examples/fib-debug/main.c b/examples/fib-debug/main.c index dfebf8993e4c..a4e22dee3c95 100644 --- a/examples/fib-debug/main.c +++ b/examples/fib-debug/main.c @@ -43,7 +43,7 @@ int main(int argc, const char* argv[]) { // Compile. printf("Compiling module...\n"); wasm_module_t *module = NULL; - wasmtime_error_t* error = wasmtime_module_new(store, &binary, &module); + wasmtime_error_t* error = wasmtime_module_new(engine, &binary, &module); if (!module) exit_with_error("failed to compile module", error, NULL); wasm_byte_vec_delete(&binary); @@ -71,7 +71,7 @@ int main(int argc, const char* argv[]) { printf("Instantiating module...\n"); wasm_instance_t* instance = NULL; wasm_trap_t *trap = NULL; - error = wasmtime_instance_new(module, NULL, 0, &instance, &trap); + error = wasmtime_instance_new(store, module, NULL, 0, &instance, &trap); if (error != NULL || trap != NULL) exit_with_error("failed to instantiate", error, trap); wasm_module_delete(module); diff --git a/examples/gcd.c b/examples/gcd.c index c4b6beb69c74..285bc1593f2d 100644 --- a/examples/gcd.c +++ b/examples/gcd.c @@ -59,13 +59,13 @@ int main() { // Compile and instantiate our module wasm_module_t *module = NULL; - error = wasmtime_module_new(store, &wasm, &module); + error = wasmtime_module_new(engine, &wasm, &module); if (module == NULL) exit_with_error("failed to compile module", error, NULL); wasm_byte_vec_delete(&wasm); wasm_trap_t *trap = NULL; wasm_instance_t *instance = NULL; - error = wasmtime_instance_new(module, NULL, 0, &instance, &trap); + error = wasmtime_instance_new(store, module, NULL, 0, &instance, &trap); if (instance == NULL) exit_with_error("failed to instantiate", error, trap); diff --git a/examples/hello.c b/examples/hello.c index 2082247203f8..fd268a84de25 100644 --- a/examples/hello.c +++ b/examples/hello.c @@ -67,7 +67,7 @@ int main() { // Now that we've got our binary webassembly we can compile our module. printf("Compiling module...\n"); wasm_module_t *module = NULL; - error = wasmtime_module_new(store, &wasm, &module); + error = wasmtime_module_new(engine, &wasm, &module); wasm_byte_vec_delete(&wasm); if (error != NULL) exit_with_error("failed to compile module", error, NULL); @@ -87,7 +87,7 @@ int main() { wasm_trap_t *trap = NULL; wasm_instance_t *instance = NULL; const wasm_extern_t *imports[] = { wasm_func_as_extern(hello) }; - error = wasmtime_instance_new(module, imports, 1, &instance, &trap); + error = wasmtime_instance_new(store, module, imports, 1, &instance, &trap); if (instance == NULL) exit_with_error("failed to instantiate", error, trap); diff --git a/examples/interrupt.c b/examples/interrupt.c index 2a4f5cfbd289..d2b5a3ac751e 100644 --- a/examples/interrupt.c +++ b/examples/interrupt.c @@ -89,11 +89,11 @@ int main() { wasm_module_t *module = NULL; wasm_trap_t *trap = NULL; wasm_instance_t *instance = NULL; - error = wasmtime_module_new(store, &wasm, &module); + error = wasmtime_module_new(engine, &wasm, &module); wasm_byte_vec_delete(&wasm); if (error != NULL) exit_with_error("failed to compile module", error, NULL); - error = wasmtime_instance_new(module, NULL, 0, &instance, &trap); + error = wasmtime_instance_new(store, module, NULL, 0, &instance, &trap); if (instance == NULL) exit_with_error("failed to instantiate", error, trap); diff --git a/examples/linking.c b/examples/linking.c index 7e6a29aed055..bc13f3cb97ad 100644 --- a/examples/linking.c +++ b/examples/linking.c @@ -45,10 +45,10 @@ int main() { wasmtime_error_t *error; wasm_module_t *linking1_module = NULL; wasm_module_t *linking2_module = NULL; - error = wasmtime_module_new(store, &linking1_wasm, &linking1_module); + error = wasmtime_module_new(engine, &linking1_wasm, &linking1_module); if (error != NULL) exit_with_error("failed to compile linking1", error, NULL); - error = wasmtime_module_new(store, &linking2_wasm, &linking2_module); + error = wasmtime_module_new(engine, &linking2_wasm, &linking2_module); if (error != NULL) exit_with_error("failed to compile linking2", error, NULL); wasm_byte_vec_delete(&linking1_wasm); diff --git a/examples/memory.c b/examples/memory.c index 1687048f9254..7d1674df1b80 100644 --- a/examples/memory.c +++ b/examples/memory.c @@ -158,7 +158,7 @@ int main(int argc, const char* argv[]) { // Compile. printf("Compiling module...\n"); wasm_module_t* module = NULL; - error = wasmtime_module_new(store, &binary, &module); + error = wasmtime_module_new(engine, &binary, &module); if (error) exit_with_error("failed to compile module", error, NULL); wasm_byte_vec_delete(&binary); @@ -167,7 +167,7 @@ int main(int argc, const char* argv[]) { printf("Instantiating module...\n"); wasm_instance_t* instance = NULL; wasm_trap_t *trap = NULL; - error = wasmtime_instance_new(module, NULL, 0, &instance, &trap); + error = wasmtime_instance_new(store, module, NULL, 0, &instance, &trap); if (!instance) exit_with_error("failed to instantiate", error, trap); diff --git a/examples/multi.c b/examples/multi.c index 0006dd0e5dcd..a56883884fed 100644 --- a/examples/multi.c +++ b/examples/multi.c @@ -91,7 +91,7 @@ int main(int argc, const char* argv[]) { // Compile. printf("Compiling module...\n"); wasm_module_t* module = NULL; - error = wasmtime_module_new(store, &binary, &module); + error = wasmtime_module_new(engine, &binary, &module); if (error) exit_with_error("failed to compile module", error, NULL); @@ -115,7 +115,7 @@ int main(int argc, const char* argv[]) { const wasm_extern_t* imports[] = {wasm_func_as_extern(callback_func)}; wasm_instance_t* instance = NULL; wasm_trap_t* trap = NULL; - error = wasmtime_instance_new(module, imports, 1, &instance, &trap); + error = wasmtime_instance_new(store, module, imports, 1, &instance, &trap); if (!instance) exit_with_error("failed to instantiate", error, trap); diff --git a/examples/wasi/main.c b/examples/wasi/main.c index 68a978ccd28a..2ad9592f4e85 100644 --- a/examples/wasi/main.c +++ b/examples/wasi/main.c @@ -54,7 +54,7 @@ int main() { // Compile our modules wasm_module_t *module = NULL; - wasmtime_error_t *error = wasmtime_module_new(store, &wasm, &module); + wasmtime_error_t *error = wasmtime_module_new(engine, &wasm, &module); if (!module) exit_with_error("failed to compile module", error, NULL); wasm_byte_vec_delete(&wasm); From 449cc5228b403bb233fb5984dc61394ae3e3f382 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 1 Jun 2020 16:52:52 -0500 Subject: [PATCH 27/35] mv alloc/drop outside of lock --- crates/runtime/src/jit_int.rs | 44 ++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/crates/runtime/src/jit_int.rs b/crates/runtime/src/jit_int.rs index bc7d510e1a8a..4fd1e7f88e41 100644 --- a/crates/runtime/src/jit_int.rs +++ b/crates/runtime/src/jit_int.rs @@ -52,14 +52,13 @@ lazy_static! { // and when paused in __jit_debug_register_code. // // The GDB_REGISTRATION lock is needed for GdbJitImageRegistration to protect - // access to the __jit_debug_descriptor within this process, and `u32` is - // just a "phantom" data. + // access to the __jit_debug_descriptor within this process. pub static ref GDB_REGISTRATION: Mutex<()> = Mutex::new(Default::default()); } /// Registeration for JIT image pub struct GdbJitImageRegistration { - entry: *mut JITCodeEntry, + entry: Pin>, file: Pin>, } @@ -67,13 +66,21 @@ impl GdbJitImageRegistration { /// Registers JIT image using __jit_debug_register_code pub fn register(file: Vec) -> Self { let file = Pin::new(file.into_boxed_slice()); - Self { - entry: unsafe { - let _lock = GDB_REGISTRATION.lock().unwrap(); - register_gdb_jit_image(&file) - }, - file, + + // Create a code entry for the file, which gives the start and size + // of the symbol file. + let mut entry = Pin::new(Box::new(JITCodeEntry { + next_entry: ptr::null_mut(), + prev_entry: ptr::null_mut(), + symfile_addr: file.as_ptr(), + symfile_size: file.len() as u64, + })); + + unsafe { + register_gdb_jit_image(&mut *entry); } + + Self { entry, file } } /// JIT image used in registration @@ -85,8 +92,7 @@ impl GdbJitImageRegistration { impl Drop for GdbJitImageRegistration { fn drop(&mut self) { unsafe { - let _lock = GDB_REGISTRATION.lock().unwrap(); - unregister_gdb_jit_image(self.entry); + unregister_gdb_jit_image(&mut *self.entry); } } } @@ -94,15 +100,11 @@ impl Drop for GdbJitImageRegistration { unsafe impl Send for GdbJitImageRegistration {} unsafe impl Sync for GdbJitImageRegistration {} -unsafe fn register_gdb_jit_image(file: &[u8]) -> *mut JITCodeEntry { - // Create a code entry for the file, which gives the start and size of the symbol file. - let entry = Box::into_raw(Box::new(JITCodeEntry { - next_entry: __jit_debug_descriptor.first_entry, - prev_entry: ptr::null_mut(), - symfile_addr: file.as_ptr(), - symfile_size: file.len() as u64, - })); +unsafe fn register_gdb_jit_image(entry: *mut JITCodeEntry) { + let _lock = GDB_REGISTRATION.lock().unwrap(); + // Add it to the linked list in the JIT descriptor. + (*entry).next_entry = __jit_debug_descriptor.first_entry; if !__jit_debug_descriptor.first_entry.is_null() { (*__jit_debug_descriptor.first_entry).prev_entry = entry; } @@ -115,10 +117,11 @@ unsafe fn register_gdb_jit_image(file: &[u8]) -> *mut JITCodeEntry { __jit_debug_descriptor.action_flag = JIT_NOACTION; __jit_debug_descriptor.relevant_entry = ptr::null_mut(); - entry } unsafe fn unregister_gdb_jit_image(entry: *mut JITCodeEntry) { + let _lock = GDB_REGISTRATION.lock().unwrap(); + // Remove the code entry corresponding to the code from the linked list. if !(*entry).prev_entry.is_null() { (*(*entry).prev_entry).next_entry = (*entry).next_entry; @@ -136,5 +139,4 @@ unsafe fn unregister_gdb_jit_image(entry: *mut JITCodeEntry) { __jit_debug_descriptor.action_flag = JIT_NOACTION; __jit_debug_descriptor.relevant_entry = ptr::null_mut(); - let _box = Box::from_raw(entry); } From 4048b5a6efcd227e4b353d713fe8fc8e12d8d448 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 1 Jun 2020 17:06:22 -0500 Subject: [PATCH 28/35] mv build_compiler() --- crates/wasmtime/src/runtime.rs | 48 ++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs index ae8c1f6de82d..7f04c57b9cd1 100644 --- a/crates/wasmtime/src/runtime.rs +++ b/crates/wasmtime/src/runtime.rs @@ -567,6 +567,16 @@ impl Config { cmp::max(guard_size, self.tunables.static_memory_offset_guard_size); self } + + fn build_compiler(&self) -> Compiler { + let isa = native::builder().finish(settings::Flags::new(self.flags.clone())); + Compiler::new( + isa, + self.strategy, + self.cache_config.clone(), + self.tunables.clone(), + ) + } } fn round_up_to_pages(val: u64) -> u64 { @@ -685,8 +695,12 @@ pub enum ProfilingStrategy { /// default settings. #[derive(Clone)] pub struct Engine { - config: Arc, - compiler: Arc, + inner: Arc, +} + +struct EngineInner { + config: Config, + compiler: Compiler, } impl Engine { @@ -695,33 +709,25 @@ impl Engine { pub fn new(config: &Config) -> Engine { debug_builtins::ensure_exported(); Engine { - config: Arc::new(config.clone()), - compiler: Arc::new(Engine::build_compiler(config)), + inner: Arc::new(EngineInner { + config: config.clone(), + compiler: config.build_compiler(), + }), } } /// Returns the configuration settings that this engine is using. pub fn config(&self) -> &Config { - &self.config + &self.inner.config } pub(crate) fn compiler(&self) -> &Compiler { - &self.compiler - } - - fn build_compiler(config: &Config) -> Compiler { - let isa = native::builder().finish(settings::Flags::new(config.flags.clone())); - Compiler::new( - isa, - config.strategy, - config.cache_config.clone(), - config.tunables.clone(), - ) + &self.inner.compiler } /// Returns whether the engine `a` and `b` refer to the same configuration. pub fn same(a: &Engine, b: &Engine) -> bool { - Arc::ptr_eq(&a.config, &b.config) + Arc::ptr_eq(&a.inner, &b.inner) } } @@ -797,7 +803,11 @@ impl Store { /// Returns an optional reference to a ['RuntimeMemoryCreator'] pub(crate) fn memory_creator(&self) -> Option<&dyn RuntimeMemoryCreator> { - self.engine().config.memory_creator.as_ref().map(|x| x as _) + self.engine() + .config() + .memory_creator + .as_ref() + .map(|x| x as _) } pub(crate) fn signatures(&self) -> std::cell::Ref<'_, SignatureRegistry> { @@ -962,7 +972,7 @@ impl Store { /// # } /// ``` pub fn interrupt_handle(&self) -> Result { - if self.engine().config.tunables.interruptable { + if self.engine().config().tunables.interruptable { Ok(InterruptHandle { interrupts: self.interrupts().clone(), }) From ce9bedfc97619cc0af8208a7c408cb0605281501 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 1 Jun 2020 17:13:19 -0500 Subject: [PATCH 29/35] register_jit_code comment --- crates/wasmtime/src/runtime.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs index 7f04c57b9cd1..fb20e7b06131 100644 --- a/crates/wasmtime/src/runtime.rs +++ b/crates/wasmtime/src/runtime.rs @@ -829,10 +829,14 @@ impl Store { } pub(crate) fn register_jit_code(&self, mut ranges: impl Iterator) { + // Checking of we already registered JIT code ranges by searching + // first range start. match ranges.next() { None => (), Some(first) => { if !self.is_in_jit_code(first.0) { + // The range is not registered -- add all ranges (including + // first one) to the jit_code_ranges. let mut jit_code_ranges = self.inner.jit_code_ranges.borrow_mut(); jit_code_ranges.push(first); jit_code_ranges.extend(ranges); From 9cf7a6174e7de5b6488fc581fc28b725ce2c97e0 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 1 Jun 2020 17:32:16 -0500 Subject: [PATCH 30/35] Remove signatures() accessors where possible --- crates/wasmtime/src/func.rs | 21 +++---------------- crates/wasmtime/src/runtime.rs | 16 ++++++++++---- .../wasmtime/src/trampoline/create_handle.rs | 2 +- crates/wasmtime/src/trampoline/func.rs | 4 ++-- 4 files changed, 18 insertions(+), 25 deletions(-) diff --git a/crates/wasmtime/src/func.rs b/crates/wasmtime/src/func.rs index 86daeae100cb..221875e1523a 100644 --- a/crates/wasmtime/src/func.rs +++ b/crates/wasmtime/src/func.rs @@ -479,12 +479,7 @@ impl Func { pub fn ty(&self) -> FuncType { // Signatures should always be registered in the store's registry of // shared signatures, so we should be able to unwrap safely here. - let sig = self - .instance - .store - .signatures() - .lookup(self.export.signature) - .expect("failed to lookup signature"); + let sig = self.instance.store.lookup_signature(self.export.signature); // This is only called with `Export::Function`, and since it's coming // from wasmtime_runtime itself we should support all the types coming @@ -494,23 +489,13 @@ impl Func { /// Returns the number of parameters that this function takes. pub fn param_arity(&self) -> usize { - let sig = self - .instance - .store - .signatures() - .lookup(self.export.signature) - .expect("failed to lookup signature"); + let sig = self.instance.store.lookup_signature(self.export.signature); sig.params.len() - 2 // skip the two vmctx leading parameters } /// Returns the number of results this function produces. pub fn result_arity(&self) -> usize { - let sig = self - .instance - .store - .signatures() - .lookup(self.export.signature) - .expect("failed to lookup signature"); + let sig = self.instance.store.lookup_signature(self.export.signature); sig.returns.len() } diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs index fb20e7b06131..79eac7548cf7 100644 --- a/crates/wasmtime/src/runtime.rs +++ b/crates/wasmtime/src/runtime.rs @@ -10,12 +10,12 @@ use std::rc::{Rc, Weak}; use std::sync::Arc; use wasmparser::{OperatorValidatorConfig, ValidatingParserConfig}; use wasmtime_environ::settings::{self, Configurable}; -use wasmtime_environ::{CacheConfig, Tunables}; +use wasmtime_environ::{ir, CacheConfig, Tunables}; use wasmtime_jit::{native, CompilationStrategy, Compiler}; use wasmtime_profiling::{JitDumpAgent, NullProfilerAgent, ProfilingAgent, VTuneAgent}; use wasmtime_runtime::{ debug_builtins, InstanceHandle, RuntimeMemoryCreator, SignalHandler, SignatureRegistry, - VMInterrupts, + VMInterrupts, VMSharedSignatureIndex, }; // Runtime Environment @@ -810,8 +810,16 @@ impl Store { .map(|x| x as _) } - pub(crate) fn signatures(&self) -> std::cell::Ref<'_, SignatureRegistry> { - self.inner.signatures.borrow() + pub(crate) fn lookup_signature(&self, sig_index: VMSharedSignatureIndex) -> ir::Signature { + self.inner + .signatures + .borrow() + .lookup(sig_index) + .expect("failed to lookup signature") + } + + pub(crate) fn register_signature(&self, sig: &ir::Signature) -> VMSharedSignatureIndex { + self.inner.signatures.borrow_mut().register(sig) } pub(crate) fn signatures_mut(&self) -> std::cell::RefMut<'_, SignatureRegistry> { diff --git a/crates/wasmtime/src/trampoline/create_handle.rs b/crates/wasmtime/src/trampoline/create_handle.rs index dc8f5b67c2b0..57bedf19d132 100644 --- a/crates/wasmtime/src/trampoline/create_handle.rs +++ b/crates/wasmtime/src/trampoline/create_handle.rs @@ -32,7 +32,7 @@ pub(crate) fn create_handle( .local .signatures .values() - .map(|sig| store.signatures_mut().register(sig)) + .map(|sig| store.register_signature(sig)) .collect::>(); unsafe { diff --git a/crates/wasmtime/src/trampoline/func.rs b/crates/wasmtime/src/trampoline/func.rs index ea826d163b9a..edff97a3dae7 100644 --- a/crates/wasmtime/src/trampoline/func.rs +++ b/crates/wasmtime/src/trampoline/func.rs @@ -244,7 +244,7 @@ pub fn create_handle_with_function( mem::size_of::(), )?; assert!(relocations.is_empty()); - let sig_id = store.signatures_mut().register(&sig); + let sig_id = store.register_signature(&sig); trampolines.insert(sig_id, trampoline); // Next up we wrap everything up into an `InstanceHandle` by publishing our @@ -291,7 +291,7 @@ pub unsafe fn create_handle_with_raw_function( .exports .insert("trampoline".to_string(), EntityIndex::Function(func_id)); finished_functions.push(func); - let sig_id = store.signatures_mut().register(&sig); + let sig_id = store.register_signature(&sig); trampolines.insert(sig_id, trampoline); create_handle(module, store, finished_functions, trampolines, state) From 88093a640dc6a2105a9efe2c81333cf91671a4d8 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 1 Jun 2020 17:38:06 -0500 Subject: [PATCH 31/35] fix tests --- crates/wasmtime/src/runtime.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs index 79eac7548cf7..bf7dc9033241 100644 --- a/crates/wasmtime/src/runtime.rs +++ b/crates/wasmtime/src/runtime.rs @@ -1064,33 +1064,33 @@ mod tests { .cache_config_load(&config_path)?; let engine = Engine::new(&cfg); Module::new(&engine, "(module (func))")?; - assert_eq!(engine.config.cache_config.cache_hits(), 0); - assert_eq!(engine.config.cache_config.cache_misses(), 1); + assert_eq!(engine.config().cache_config.cache_hits(), 0); + assert_eq!(engine.config().cache_config.cache_misses(), 1); Module::new(&engine, "(module (func))")?; - assert_eq!(engine.config.cache_config.cache_hits(), 1); - assert_eq!(engine.config.cache_config.cache_misses(), 1); + assert_eq!(engine.config().cache_config.cache_hits(), 1); + assert_eq!(engine.config().cache_config.cache_misses(), 1); let mut cfg = Config::new(); cfg.cranelift_opt_level(OptLevel::Speed) .cache_config_load(&config_path)?; let engine = Engine::new(&cfg); Module::new(&engine, "(module (func))")?; - assert_eq!(engine.config.cache_config.cache_hits(), 0); - assert_eq!(engine.config.cache_config.cache_misses(), 1); + assert_eq!(engine.config().cache_config.cache_hits(), 0); + assert_eq!(engine.config().cache_config.cache_misses(), 1); Module::new(&engine, "(module (func))")?; - assert_eq!(engine.config.cache_config.cache_hits(), 1); - assert_eq!(engine.config.cache_config.cache_misses(), 1); + assert_eq!(engine.config().cache_config.cache_hits(), 1); + assert_eq!(engine.config().cache_config.cache_misses(), 1); let mut cfg = Config::new(); cfg.cranelift_opt_level(OptLevel::SpeedAndSize) .cache_config_load(&config_path)?; let engine = Engine::new(&cfg); Module::new(&engine, "(module (func))")?; - assert_eq!(engine.config.cache_config.cache_hits(), 0); - assert_eq!(engine.config.cache_config.cache_misses(), 1); + assert_eq!(engine.config().cache_config.cache_hits(), 0); + assert_eq!(engine.config().cache_config.cache_misses(), 1); Module::new(&engine, "(module (func))")?; - assert_eq!(engine.config.cache_config.cache_hits(), 1); - assert_eq!(engine.config.cache_config.cache_misses(), 1); + assert_eq!(engine.config().cache_config.cache_hits(), 1); + assert_eq!(engine.config().cache_config.cache_misses(), 1); // FIXME(#1523) need debuginfo on aarch64 before we run this test there if !cfg!(target_arch = "aarch64") { @@ -1098,11 +1098,11 @@ mod tests { cfg.debug_info(true).cache_config_load(&config_path)?; let engine = Engine::new(&cfg); Module::new(&engine, "(module (func))")?; - assert_eq!(engine.config.cache_config.cache_hits(), 0); - assert_eq!(engine.config.cache_config.cache_misses(), 1); + assert_eq!(engine.config().cache_config.cache_hits(), 0); + assert_eq!(engine.config().cache_config.cache_misses(), 1); Module::new(&engine, "(module (func))")?; - assert_eq!(engine.config.cache_config.cache_hits(), 1); - assert_eq!(engine.config.cache_config.cache_misses(), 1); + assert_eq!(engine.config().cache_config.cache_hits(), 1); + assert_eq!(engine.config().cache_config.cache_misses(), 1); } Ok(()) From fc9d28920c90618561cfaf0750d6f99f49b8b667 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 1 Jun 2020 18:01:15 -0500 Subject: [PATCH 32/35] revert some changes --- crates/jit/src/instantiate.rs | 15 +++++----- crates/runtime/src/instance.rs | 51 ++++++++++++++++----------------- crates/wasmtime/src/instance.rs | 6 ++-- crates/wasmtime/src/module.rs | 2 +- 4 files changed, 35 insertions(+), 39 deletions(-) diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs index c2670ffb1f31..d77b41644d3e 100644 --- a/crates/jit/src/instantiate.rs +++ b/crates/jit/src/instantiate.rs @@ -151,7 +151,7 @@ impl CompiledModule { /// /// See `InstanceHandle::new` pub unsafe fn instantiate( - module: Arc, + &self, resolver: &mut dyn Resolver, signature_registry: &mut SignatureRegistry, mem_creator: Option<&dyn RuntimeMemoryCreator>, @@ -160,8 +160,7 @@ impl CompiledModule { ) -> Result { // Compute indices into the shared signature table. let signatures = { - module - .module() + self.module .local .signatures .values() @@ -170,16 +169,16 @@ impl CompiledModule { }; let mut trampolines = HashMap::new(); - for (i, trampoline) in module.trampolines.iter() { + for (i, trampoline) in self.trampolines.iter() { trampolines.insert(signatures[i], trampoline.clone()); } - let finished_functions = module.finished_functions.0.clone(); + let finished_functions = self.finished_functions.0.clone(); - let imports = resolve_imports(module.module(), signature_registry, resolver)?; + let imports = resolve_imports(&self.module, signature_registry, resolver)?; InstanceHandle::new( - module.module.clone(), - module.code.clone(), + self.module.clone(), + self.code.clone(), finished_functions, trampolines, imports, diff --git a/crates/runtime/src/instance.rs b/crates/runtime/src/instance.rs index 9dc343850254..db21b0a03c4d 100644 --- a/crates/runtime/src/instance.rs +++ b/crates/runtime/src/instance.rs @@ -173,7 +173,7 @@ impl Instance { /// Get a locally defined or imported memory. pub(crate) fn get_memory(&self, index: MemoryIndex) -> VMMemoryDefinition { - if let Some(defined_index) = self.module().local.defined_memory_index(index) { + if let Some(defined_index) = self.module.local.defined_memory_index(index) { self.memory(defined_index) } else { let import = self.imported_memory(index); @@ -250,7 +250,7 @@ impl Instance { /// Lookup an export with the given name. pub fn lookup(&self, field: &str) -> Option { - let export = if let Some(export) = self.module().exports.get(field) { + let export = if let Some(export) = self.module.exports.get(field) { export.clone() } else { return None; @@ -262,9 +262,9 @@ impl Instance { pub fn lookup_by_declaration(&self, export: &EntityIndex) -> Export { match export { EntityIndex::Function(index) => { - let signature = self.signature_id(self.module().local.functions[*index]); + let signature = self.signature_id(self.module.local.functions[*index]); let (address, vmctx) = - if let Some(def_index) = self.module().local.defined_func_index(*index) { + if let Some(def_index) = self.module.local.defined_func_index(*index) { ( self.finished_functions[def_index] as *const _, self.vmctx_ptr(), @@ -282,7 +282,7 @@ impl Instance { } EntityIndex::Table(index) => { let (definition, vmctx) = - if let Some(def_index) = self.module().local.defined_table_index(*index) { + if let Some(def_index) = self.module.local.defined_table_index(*index) { (self.table_ptr(def_index), self.vmctx_ptr()) } else { let import = self.imported_table(*index); @@ -291,13 +291,13 @@ impl Instance { ExportTable { definition, vmctx, - table: self.module().local.table_plans[*index].clone(), + table: self.module.local.table_plans[*index].clone(), } .into() } EntityIndex::Memory(index) => { let (definition, vmctx) = - if let Some(def_index) = self.module().local.defined_memory_index(*index) { + if let Some(def_index) = self.module.local.defined_memory_index(*index) { (self.memory_ptr(def_index), self.vmctx_ptr()) } else { let import = self.imported_memory(*index); @@ -306,20 +306,19 @@ impl Instance { ExportMemory { definition, vmctx, - memory: self.module().local.memory_plans[*index].clone(), + memory: self.module.local.memory_plans[*index].clone(), } .into() } EntityIndex::Global(index) => ExportGlobal { - definition: if let Some(def_index) = - self.module().local.defined_global_index(*index) + definition: if let Some(def_index) = self.module.local.defined_global_index(*index) { self.global_ptr(def_index) } else { self.imported_global(*index).from }, vmctx: self.vmctx_ptr(), - global: self.module().local.globals[*index], + global: self.module.local.globals[*index], } .into(), } @@ -331,7 +330,7 @@ impl Instance { /// are export names, and the values are export declarations which can be /// resolved `lookup_by_declaration`. pub fn exports(&self) -> indexmap::map::Iter { - self.module().exports.iter() + self.module.exports.iter() } /// Return a reference to the custom state attached to this instance. @@ -493,19 +492,19 @@ impl Instance { return VMCallerCheckedAnyfunc::default(); } - let sig = self.module().local.functions[index]; + let sig = self.module.local.functions[index]; let type_index = self.signature_id(sig); - let (func_ptr, vmctx) = - if let Some(def_index) = self.module().local.defined_func_index(index) { - ( - self.finished_functions[def_index] as *const _, - self.vmctx_ptr(), - ) - } else { - let import = self.imported_function(index); - (import.body, import.vmctx) - }; + let (func_ptr, vmctx) = if let Some(def_index) = self.module.local.defined_func_index(index) + { + ( + self.finished_functions[def_index] as *const _, + self.vmctx_ptr(), + ) + } else { + let import = self.imported_function(index); + (import.body, import.vmctx) + }; VMCallerCheckedAnyfunc { func_ptr, type_index, @@ -731,7 +730,7 @@ impl Instance { /// Get a table by index regardless of whether it is locally-defined or an /// imported, foreign table. pub(crate) fn get_table(&self, table_index: TableIndex) -> &Table { - if let Some(defined_table_index) = self.module().local.defined_table_index(table_index) { + if let Some(defined_table_index) = self.module.local.defined_table_index(table_index) { self.get_defined_table(defined_table_index) } else { self.get_foreign_table(table_index) @@ -1076,7 +1075,7 @@ fn get_memory_init_start(init: &DataInitializer<'_>, instance: &Instance) -> usi if let Some(base) = init.location.base { let val = unsafe { - if let Some(def_index) = instance.module().local.defined_global_index(base) { + if let Some(def_index) = instance.module.local.defined_global_index(base) { *instance.global(def_index).as_u32() } else { *(*instance.imported_global(base).from).as_u32() @@ -1145,7 +1144,7 @@ fn get_table_init_start(init: &TableElements, instance: &Instance) -> usize { if let Some(base) = init.base { let val = unsafe { - if let Some(def_index) = instance.module().local.defined_global_index(base) { + if let Some(def_index) = instance.module.local.defined_global_index(base) { *instance.global(def_index).as_u32() } else { *(*instance.imported_global(base).from).as_u32() diff --git a/crates/wasmtime/src/instance.rs b/crates/wasmtime/src/instance.rs index 559afa6a3237..ed39a70d4d72 100644 --- a/crates/wasmtime/src/instance.rs +++ b/crates/wasmtime/src/instance.rs @@ -3,7 +3,6 @@ use crate::{Engine, Export, Extern, Func, Global, Memory, Module, Store, Table, use anyhow::{bail, Error, Result}; use std::any::Any; use std::mem; -use std::sync::Arc; use wasmtime_environ::EntityIndex; use wasmtime_jit::{CompiledModule, Resolver}; use wasmtime_runtime::{InstantiationError, VMContext, VMFunctionBody}; @@ -22,7 +21,7 @@ impl Resolver for SimpleResolver<'_> { fn instantiate( store: &Store, - compiled_module: &Arc, + compiled_module: &CompiledModule, imports: &[Extern], host: Box, ) -> Result { @@ -45,8 +44,7 @@ fn instantiate( let mut resolver = SimpleResolver { imports }; let config = store.engine().config(); let instance = unsafe { - let instance = CompiledModule::instantiate( - compiled_module.clone(), + let instance = compiled_module.instantiate( &mut resolver, &mut store.signatures_mut(), config.memory_creator.as_ref().map(|a| a as _), diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs index 38894dfa0968..2896de0302be 100644 --- a/crates/wasmtime/src/module.rs +++ b/crates/wasmtime/src/module.rs @@ -309,7 +309,7 @@ impl Module { }) } - pub(crate) fn compiled_module(&self) -> &Arc { + pub(crate) fn compiled_module(&self) -> &CompiledModule { &self.compiled } From 4cefa4a17a032256c3a7d4f9937378129a31d97b Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 1 Jun 2020 18:25:56 -0500 Subject: [PATCH 33/35] Fix intermitent failures in threads tests e.g. https://github.com/bytecodealliance/wasmtime/runs/728875254 --- crates/c-api/src/engine.rs | 9 +++++---- crates/c-api/src/module.rs | 39 +++++++++++++++++++------------------- crates/c-api/src/store.rs | 3 +-- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/crates/c-api/src/engine.rs b/crates/c-api/src/engine.rs index 843c261ea631..6088c4e05aae 100644 --- a/crates/c-api/src/engine.rs +++ b/crates/c-api/src/engine.rs @@ -1,10 +1,11 @@ use crate::wasm_config_t; -use wasmtime::{Engine, HostRef}; +use std::sync::Arc; +use wasmtime::Engine; #[repr(C)] #[derive(Clone)] pub struct wasm_engine_t { - pub(crate) engine: HostRef, + pub(crate) engine: Arc, } wasmtime_c_api_macros::declare_own!(wasm_engine_t); @@ -22,7 +23,7 @@ pub extern "C" fn wasm_engine_new() -> Box { drop(env_logger::try_init()); Box::new(wasm_engine_t { - engine: HostRef::new(Engine::default()), + engine: Arc::new(Engine::default()), }) } @@ -30,6 +31,6 @@ pub extern "C" fn wasm_engine_new() -> Box { pub extern "C" fn wasm_engine_new_with_config(c: Box) -> Box { let config = c.config; Box::new(wasm_engine_t { - engine: HostRef::new(Engine::new(&config)), + engine: Arc::new(Engine::new(&config)), }) } diff --git a/crates/c-api/src/module.rs b/crates/c-api/src/module.rs index dcdf8bf6e9ea..360e8e2b88f9 100644 --- a/crates/c-api/src/module.rs +++ b/crates/c-api/src/module.rs @@ -3,6 +3,7 @@ use crate::{ wasm_importtype_t, wasm_importtype_vec_t, wasm_store_t, wasmtime_error_t, }; use std::ptr; +use std::sync::Arc; use wasmtime::{Engine, HostRef, Module}; #[repr(C)] @@ -35,8 +36,9 @@ pub extern "C" fn wasm_module_new( binary: &wasm_byte_vec_t, ) -> Option> { let mut ret = ptr::null_mut(); + let store = store.store.clone(); let engine = wasm_engine_t { - engine: HostRef::new(store.store.borrow().engine().clone()), + engine: Arc::new(store.borrow().engine().clone()), }; match wasmtime_module_new(&engine, binary, &mut ret) { Some(_err) => None, @@ -54,25 +56,22 @@ pub extern "C" fn wasmtime_module_new( ret: &mut *mut wasm_module_t, ) -> Option> { let binary = binary.as_slice(); - handle_result( - Module::from_binary(&engine.engine.borrow(), binary), - |module| { - let imports = module - .imports() - .map(|i| wasm_importtype_t::new(i.module().to_owned(), i.name().to_owned(), i.ty())) - .collect::>(); - let exports = module - .exports() - .map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty())) - .collect::>(); - let module = Box::new(wasm_module_t { - module: HostRef::new(module), - imports, - exports, - }); - *ret = Box::into_raw(module); - }, - ) + handle_result(Module::from_binary(&engine.engine, binary), |module| { + let imports = module + .imports() + .map(|i| wasm_importtype_t::new(i.module().to_owned(), i.name().to_owned(), i.ty())) + .collect::>(); + let exports = module + .exports() + .map(|e| wasm_exporttype_t::new(e.name().to_owned(), e.ty())) + .collect::>(); + let module = Box::new(wasm_module_t { + module: HostRef::new(module), + imports, + exports, + }); + *ret = Box::into_raw(module); + }) } #[no_mangle] diff --git a/crates/c-api/src/store.rs b/crates/c-api/src/store.rs index a2a5b1c25b60..9c076e09ea03 100644 --- a/crates/c-api/src/store.rs +++ b/crates/c-api/src/store.rs @@ -11,9 +11,8 @@ wasmtime_c_api_macros::declare_own!(wasm_store_t); #[no_mangle] pub extern "C" fn wasm_store_new(engine: &wasm_engine_t) -> Box { - let engine = &engine.engine; Box::new(wasm_store_t { - store: HostRef::new(Store::new(&engine.borrow())), + store: HostRef::new(Store::new(&engine.engine)), }) } From 65f2c0064560db7a86d94f87127289ba07e01444 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 2 Jun 2020 13:03:45 -0500 Subject: [PATCH 34/35] mv unwrap(); reduce code churn --- crates/c-api/src/store.rs | 3 ++- crates/jit/src/instantiate.rs | 8 ++++---- crates/runtime/src/instance.rs | 4 ++-- crates/wasmtime/src/module.rs | 1 + 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/crates/c-api/src/store.rs b/crates/c-api/src/store.rs index 735b53bbf751..625b3831ea43 100644 --- a/crates/c-api/src/store.rs +++ b/crates/c-api/src/store.rs @@ -11,8 +11,9 @@ wasmtime_c_api_macros::declare_own!(wasm_store_t); #[no_mangle] pub extern "C" fn wasm_store_new(engine: &wasm_engine_t) -> Box { + let engine = &engine.engine; Box::new(wasm_store_t { - store: Store::new(&engine.engine), + store: Store::new(&engine), }) } diff --git a/crates/jit/src/instantiate.rs b/crates/jit/src/instantiate.rs index 41c86d3d1258..c8cdc937a9f1 100644 --- a/crates/jit/src/instantiate.rs +++ b/crates/jit/src/instantiate.rs @@ -202,14 +202,14 @@ impl CompiledModule { .collect() } - /// Return a reference to a module. + /// Return a reference-counting pointer to a module. pub fn module(&self) -> &Arc { &self.module } - /// Return a reference to a module. - pub fn module_mut(&mut self) -> &mut Module { - Arc::get_mut(&mut self.module).unwrap() + /// Return a reference to a mutable module (if possible). + pub fn module_mut(&mut self) -> Option<&mut Module> { + Arc::get_mut(&mut self.module) } /// Returns the map of all finished JIT functions compiled for this module diff --git a/crates/runtime/src/instance.rs b/crates/runtime/src/instance.rs index db21b0a03c4d..8642da2aef45 100644 --- a/crates/runtime/src/instance.rs +++ b/crates/runtime/src/instance.rs @@ -1093,7 +1093,7 @@ unsafe fn get_memory_slice<'instance>( instance: &'instance Instance, ) -> &'instance mut [u8] { let memory = if let Some(defined_memory_index) = instance - .module() + .module .local .defined_memory_index(init.location.memory_index) { @@ -1194,7 +1194,7 @@ fn initialize_passive_elements(instance: &Instance) { passive_elements.extend( instance - .module() + .module .passive_elements .iter() .filter(|(_, segments)| !segments.is_empty()) diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs index 2896de0302be..391c3b63de10 100644 --- a/crates/wasmtime/src/module.rs +++ b/crates/wasmtime/src/module.rs @@ -164,6 +164,7 @@ impl Module { Arc::get_mut(&mut module.compiled) .unwrap() .module_mut() + .expect("mutable module") .name = Some(name.to_string()); Ok(module) } From 430a41745f57ea9f0558b11bc676be7d2b7b585b Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 2 Jun 2020 13:12:05 -0500 Subject: [PATCH 35/35] RELEASES.md --- RELEASES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 8146b5d867bb..8a812b99132d 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -43,6 +43,10 @@ is now enabled by default. [#1667](https://github.com/bytecodealliance/wasmtime/pull/1667) +The Rust API does not require a store provided during `Module::new` operation. The `Module` can be send accross threads and instantiate for a specific store. The `Instance::new` now requires the store. + + [#1761](https://github.com/bytecodealliance/wasmtime/pull/1761) + -------------------------------------------------------------------------------- ## 0.16.0