Fix bad merge.

Fix a bad merge with the `async` feature that accidentally removed the
allocation of fiber stacks via the instance allocator.
This commit is contained in:
Peter Huene
2021-03-01 10:39:59 -08:00
parent 505437e353
commit 4e83392070

View File

@@ -754,12 +754,14 @@ impl Store {
/// that the various comments are illuminating as to what's going on here. /// that the various comments are illuminating as to what's going on here.
#[cfg(feature = "async")] #[cfg(feature = "async")]
pub(crate) async fn on_fiber<R>(&self, func: impl FnOnce() -> R) -> Result<R, Trap> { pub(crate) async fn on_fiber<R>(&self, func: impl FnOnce() -> R) -> Result<R, Trap> {
debug_assert!(self.is_async()); let config = self.inner.engine.config();
// TODO: allocation of a fiber should be much more abstract where we debug_assert!(self.is_async());
// shouldn't be allocating huge stacks on every async wasm function call. debug_assert!(config.async_stack_size > 0);
type SuspendType = wasmtime_fiber::Suspend<Result<(), Trap>, (), Result<(), Trap>>;
let mut slot = None; let mut slot = None;
let fiber = wasmtime_fiber::Fiber::new(10 * 1024 * 1024, |keep_going, suspend| { let func = |keep_going, suspend: &SuspendType| {
// First check and see if we were interrupted/dropped, and only // First check and see if we were interrupted/dropped, and only
// continue if we haven't been. // continue if we haven't been.
keep_going?; keep_going?;
@@ -777,18 +779,46 @@ impl Store {
slot = Some(func()); slot = Some(func());
Ok(()) Ok(())
}) };
.map_err(|e| Trap::from(anyhow::Error::from(e)))?;
let (fiber, stack) = match config.instance_allocator().allocate_fiber_stack() {
Ok(stack) => {
// Use the returned stack and deallocate it when finished
(
unsafe {
wasmtime_fiber::Fiber::new_with_stack(stack, func)
.map_err(|e| Trap::from(anyhow::Error::from(e)))?
},
stack,
)
}
Err(wasmtime_runtime::FiberStackError::NotSupported) => {
// The allocator doesn't support custom fiber stacks for the current platform
// Request that the fiber itself allocate the stack
(
wasmtime_fiber::Fiber::new(config.async_stack_size, func)
.map_err(|e| Trap::from(anyhow::Error::from(e)))?,
std::ptr::null_mut(),
)
}
Err(e) => return Err(Trap::from(anyhow::Error::from(e))),
};
// Once we have the fiber representing our synchronous computation, we // Once we have the fiber representing our synchronous computation, we
// wrap that in a custom future implementation which does the // wrap that in a custom future implementation which does the
// translation from the future protocol to our fiber API. // translation from the future protocol to our fiber API.
FiberFuture { fiber, store: self }.await?; FiberFuture {
fiber,
store: self,
stack,
}
.await?;
return Ok(slot.unwrap()); return Ok(slot.unwrap());
struct FiberFuture<'a> { struct FiberFuture<'a> {
fiber: wasmtime_fiber::Fiber<'a, Result<(), Trap>, (), Result<(), Trap>>, fiber: wasmtime_fiber::Fiber<'a, Result<(), Trap>, (), Result<(), Trap>>,
store: &'a Store, store: &'a Store,
stack: *mut u8,
} }
impl Future for FiberFuture<'_> { impl Future for FiberFuture<'_> {
@@ -845,15 +875,23 @@ impl Store {
// completion. // completion.
impl Drop for FiberFuture<'_> { impl Drop for FiberFuture<'_> {
fn drop(&mut self) { fn drop(&mut self) {
if self.fiber.done() { if !self.fiber.done() {
return; let result = self.fiber.resume(Err(Trap::new("future dropped")));
// This resumption with an error should always complete the
// fiber. While it's technically possible for host code to catch
// the trap and re-resume, we'd ideally like to signal that to
// callers that they shouldn't be doing that.
debug_assert!(result.is_ok());
}
if !self.stack.is_null() {
unsafe {
self.store
.engine()
.config()
.instance_allocator()
.deallocate_fiber_stack(self.stack)
};
} }
let result = self.fiber.resume(Err(Trap::new("future dropped")));
// This resumption with an error should always complete the
// fiber. While it's technically possible for host code to catch
// the trap and re-resume, we'd ideally like to signal that to
// callers that they shouldn't be doing that.
debug_assert!(result.is_ok());
} }
} }
} }