diff --git a/crates/wasmtime/src/instance.rs b/crates/wasmtime/src/instance.rs index e11971739a..b2cf6affa5 100644 --- a/crates/wasmtime/src/instance.rs +++ b/crates/wasmtime/src/instance.rs @@ -503,19 +503,19 @@ impl<'a> Instantiator<'a> { // NB: this is the same code as `run`. It's intentionally // small but should be kept in sync (modulo the async bits). - loop { - let step = self.step(store.0)?; - if let Some((instance, start, toplevel)) = step { - if let Some(start) = start { - store - .on_fiber(|store| Instantiator::start_raw(store, instance, start)) - .await??; - } - if toplevel { - break Ok(instance); + store + .on_fiber(|store| loop { + let step = self.step(store.0)?; + if let Some((instance, start, toplevel)) = step { + if let Some(start) = start { + Instantiator::start_raw(store, instance, start)? + } + if toplevel { + break Ok(instance); + } } - } - } + }) + .await? } /// Processes the next initializer for the next instance being created diff --git a/crates/wasmtime/src/memory.rs b/crates/wasmtime/src/memory.rs index 1d04a6edad..de15665afd 100644 --- a/crates/wasmtime/src/memory.rs +++ b/crates/wasmtime/src/memory.rs @@ -223,6 +223,24 @@ impl Memory { Memory::_new(store.as_context_mut().0, ty) } + /// Async variant of [`Memory::new`]. You must use this variant with Stores which have a + /// [`ResourceLimiterAsync`]. + #[cfg(feature = "async")] + pub async fn new_async( + mut store: impl AsContextMut, + ty: MemoryType, + ) -> Result + where + T: Send, + { + let mut store = store.as_context_mut(); + assert!( + store.0.async_support(), + "cannot use `new_async` without enabling async support on the config" + ); + store.on_fiber(|store| Memory::_new(store.0, ty)).await? + } + fn _new(store: &mut StoreOpaque, ty: MemoryType) -> Result { unsafe { let export = generate_memory_export(store, &ty)?; @@ -472,6 +490,23 @@ impl Memory { } } + /// Async variant of [`Memory::grow`]. Required when using a [`ResourceLimiterAsync`]. + #[cfg(feature = "async")] + pub async fn grow_async( + &self, + mut store: impl AsContextMut, + delta: u64, + ) -> Result + where + T: Send, + { + let mut store = store.as_context_mut(); + assert!( + store.0.async_support(), + "cannot use `grow_async` without enabling async support on the config" + ); + store.on_fiber(|store| self.grow(store, delta)).await? + } fn wasmtime_memory(&self, store: &mut StoreOpaque) -> *mut wasmtime_runtime::Memory { unsafe { let export = &store[self.0]; diff --git a/tests/all/limits.rs b/tests/all/limits.rs index dab1542794..3a5388cf20 100644 --- a/tests/all/limits.rs +++ b/tests/all/limits.rs @@ -115,15 +115,16 @@ async fn test_limits_async() -> Result<()> { // Test instance exports and host objects hitting the limit for memory in std::array::IntoIter::new([ instance.get_memory(&mut store, "m").unwrap(), - Memory::new(&mut store, MemoryType::new(0, None))?, + Memory::new_async(&mut store, MemoryType::new(0, None)).await?, ]) { - memory.grow(&mut store, 3)?; - memory.grow(&mut store, 5)?; - memory.grow(&mut store, 2)?; + memory.grow_async(&mut store, 3).await?; + memory.grow_async(&mut store, 5).await?; + memory.grow_async(&mut store, 2).await?; assert_eq!( memory - .grow(&mut store, 1) + .grow_async(&mut store, 1) + .await .map_err(|e| e.to_string()) .unwrap_err(), "failed to grow memory by `1`"