diff --git a/Cargo.lock b/Cargo.lock index d95912d784..1b2ce6bd77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1890,9 +1890,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" [[package]] name = "oorandom" @@ -3377,6 +3377,7 @@ dependencies = [ "libc", "log", "object", + "once_cell", "paste", "psm", "rayon", diff --git a/crates/wasmtime/Cargo.toml b/crates/wasmtime/Cargo.toml index 77402eb21c..2fc4440c71 100644 --- a/crates/wasmtime/Cargo.toml +++ b/crates/wasmtime/Cargo.toml @@ -37,6 +37,7 @@ lazy_static = "1.4" rayon = { version = "1.0", optional = true } object = { version = "0.27", default-features = false, features = ['read_core', 'elf'] } async-trait = { version = "0.1.51", optional = true } +once_cell = "1.9" [target.'cfg(target_os = "windows")'.dependencies] winapi = "0.3.7" diff --git a/crates/wasmtime/src/instance.rs b/crates/wasmtime/src/instance.rs index 4161a10a54..1ec0ac8ab0 100644 --- a/crates/wasmtime/src/instance.rs +++ b/crates/wasmtime/src/instance.rs @@ -690,6 +690,9 @@ impl<'a> Instantiator<'a> { // properly referenced while in use by the store. store.modules_mut().register(&self.cur.module); + // Initialize any memfd images now. + let memfds = self.cur.module.memfds()?; + unsafe { // The first thing we do is issue an instance allocation request // to the instance allocator. This, on success, will give us an @@ -708,7 +711,7 @@ impl<'a> Instantiator<'a> { .allocate(InstanceAllocationRequest { module: compiled_module.module(), unique_id: Some(compiled_module.unique_id()), - memfds: self.cur.module.memfds(), + memfds, image_base: compiled_module.code().as_ptr() as usize, functions: compiled_module.functions(), imports: self.cur.build(), diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs index 1662388e03..2feb19ed01 100644 --- a/crates/wasmtime/src/module.rs +++ b/crates/wasmtime/src/module.rs @@ -4,6 +4,7 @@ use crate::{ }; use crate::{Engine, ModuleType}; use anyhow::{bail, Context, Result}; +use once_cell::sync::OnceCell; use std::fs; use std::mem; use std::path::Path; @@ -108,8 +109,11 @@ struct ModuleInner { types: Arc, /// Registered shared signature for the module. signatures: Arc, - /// a set of memfd images for memories, if any. - memfds: Option>, + /// A set of memfd images for memories, if any. Note that module + /// instantiation (hence the need for lazy init) may happen for the + /// same module concurrently in multiple Stores, so we use a + /// OnceCell. + memfds: OnceCell>>, } impl Module { @@ -531,8 +535,6 @@ impl Module { }) .collect::>>()?; - let memfds = ModuleMemFds::new(module.module(), module.wasm_data())?; - return Ok(Self { inner: Arc::new(ModuleInner { engine: engine.clone(), @@ -541,7 +543,7 @@ impl Module { artifact_upvars: modules, module_upvars, signatures, - memfds, + memfds: OnceCell::new(), }), }); @@ -555,13 +557,12 @@ impl Module { signatures: &Arc, ) -> Result { let module = artifacts[module_index].clone(); - let memfds = ModuleMemFds::new(module.module(), module.wasm_data())?; Ok(Module { inner: Arc::new(ModuleInner { engine: engine.clone(), types: types.clone(), module, - memfds, + memfds: OnceCell::new(), artifact_upvars: artifact_upvars .iter() .map(|i| artifacts[*i].clone()) @@ -682,13 +683,12 @@ impl Module { modules: &PrimaryMap, ) -> Result { let module = self.inner.artifact_upvars[artifact_index].clone(); - let memfds = ModuleMemFds::new(module.module(), module.wasm_data())?; Ok(Module { inner: Arc::new(ModuleInner { types: self.inner.types.clone(), engine: self.inner.engine.clone(), module, - memfds, + memfds: OnceCell::new(), artifact_upvars: artifact_upvars .iter() .map(|i| self.inner.artifact_upvars[*i].clone()) @@ -723,8 +723,14 @@ impl Module { &self.inner.signatures } - pub(crate) fn memfds(&self) -> Option<&Arc> { - self.inner.memfds.as_ref() + pub(crate) fn memfds(&self) -> Result>> { + Ok(self + .inner + .memfds + .get_or_try_init(|| { + ModuleMemFds::new(self.inner.module.module(), self.inner.module.wasm_data()) + })? + .as_ref()) } /// Looks up the module upvar value at the `index` specified.