1 //! Runtime support for the Component Model Async ABI.
2 //!
3 //! This module and its submodules provide host runtime support for Component
4 //! Model Async features such as async-lifted exports, async-lowered imports,
5 //! streams, futures, and related intrinsics.  See [the Async
6 //! Explainer](https://github.com/WebAssembly/component-model/blob/main/design/mvp/Async.md)
7 //! for a high-level overview.
8 //!
9 //! At the core of this support is an event loop which schedules and switches
10 //! between guest tasks and any host tasks they create.  Each
11 //! `ComponentInstance` will have at most one event loop running at any given
12 //! time, and that loop may be suspended and resumed by the host embedder using
13 //! e.g. `Instance::run_concurrent`.  The `ComponentInstance::poll_until`
14 //! function contains the loop itself, while the
15 //! `ComponentInstance::concurrent_state` field holds its state.
16 //!
17 //! # Public API Overview
18 //!
19 //! ## Top-level API (e.g. kicking off host->guest calls and driving the event loop)
20 //!
21 //! - `[Typed]Func::call_concurrent`: Start a host->guest call to an
22 //! async-lifted or sync-lifted import, creating a guest task.
23 //!
24 //! - `Instance::run_concurrent`: Run the event loop for the specified instance,
25 //! allowing any and all tasks belonging to that instance to make progress.
26 //!
27 //! - `Instance::spawn`: Run a background task as part of the event loop for the
28 //! specified instance.
29 //!
30 //! - `Instance::{future,stream}`: Create a new Component Model `future` or
31 //! `stream`; the read end may be passed to the guest.
32 //!
33 //! - `{Future,Stream}Reader::read` and `{Future,Stream}Writer::write`: read
34 //! from or write to a future or stream, respectively.
35 //!
36 //! ## Host Task API (e.g. implementing concurrent host functions and background tasks)
37 //!
38 //! - `LinkerInstance::func_wrap_concurrent`: Register a concurrent host
39 //! function with the linker.  That function will take an `Accessor` as its
40 //! first parameter, which provides access to the store and instance between
41 //! (but not across) await points.
42 //!
43 //! - `Accessor::with`: Access the store, its associated data, and the current
44 //! instance.
45 //!
46 //! - `Accessor::spawn`: Run a background task as part of the event loop for the
47 //! specified instance.  This is equivalent to `Instance::spawn` but more
48 //! convenient to use in host functions.
49 
50 use crate::component::func::{self, Func, Options};
51 use crate::component::{
52     Component, ComponentInstanceId, HasData, HasSelf, Instance, Resource, ResourceTable,
53     ResourceTableError,
54 };
55 use crate::fiber::{self, StoreFiber, StoreFiberYield};
56 use crate::store::{StoreInner, StoreOpaque, StoreToken};
57 use crate::vm::component::{
58     CallContext, ComponentInstance, InstanceFlags, ResourceTables, TransmitLocalState,
59 };
60 use crate::vm::{AlwaysMut, SendSyncPtr, VMFuncRef, VMMemoryDefinition, VMStore};
61 use crate::{AsContext, AsContextMut, StoreContext, StoreContextMut, ValRaw};
62 use anyhow::{Context as _, Result, anyhow, bail};
63 use error_contexts::GlobalErrorContextRefCount;
64 use futures::channel::oneshot;
65 use futures::future::{self, Either, FutureExt};
66 use futures::stream::{FuturesUnordered, StreamExt};
67 use futures_and_streams::{FlatAbi, ReturnCode, TransmitHandle, TransmitIndex};
68 use std::any::Any;
69 use std::borrow::ToOwned;
70 use std::boxed::Box;
71 use std::cell::UnsafeCell;
72 use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
73 use std::fmt;
74 use std::future::Future;
75 use std::marker::PhantomData;
76 use std::mem::{self, ManuallyDrop, MaybeUninit};
77 use std::ops::DerefMut;
78 use std::pin::{Pin, pin};
79 use std::ptr::{self, NonNull};
80 use std::slice;
81 use std::sync::Arc;
82 use std::task::{Context, Poll, Waker};
83 use std::vec::Vec;
84 use table::{TableDebug, TableId};
85 use wasmtime_environ::component::{
86     CanonicalOptions, CanonicalOptionsDataModel, ExportIndex, MAX_FLAT_PARAMS, MAX_FLAT_RESULTS,
87     OptionsIndex, PREPARE_ASYNC_NO_RESULT, PREPARE_ASYNC_WITH_RESULT,
88     RuntimeComponentInstanceIndex, StringEncoding, TypeComponentGlobalErrorContextTableIndex,
89     TypeComponentLocalErrorContextTableIndex, TypeFutureTableIndex, TypeStreamTableIndex,
90     TypeTupleIndex,
91 };
92 
93 pub use abort::JoinHandle;
94 pub use futures_and_streams::{
95     Destination, DirectDestination, DirectSource, ErrorContext, FutureConsumer, FutureProducer,
96     FutureReader, GuardedFutureReader, GuardedStreamReader, ReadBuffer, Source, StreamConsumer,
97     StreamProducer, StreamReader, StreamResult, VecBuffer, WriteBuffer,
98 };
99 pub(crate) use futures_and_streams::{
100     ResourcePair, lower_error_context_to_index, lower_future_to_index, lower_stream_to_index,
101 };
102 
103 mod abort;
104 mod error_contexts;
105 mod futures_and_streams;
106 mod table;
107 pub(crate) mod tls;
108 
109 /// Constant defined in the Component Model spec to indicate that the async
110 /// intrinsic (e.g. `future.write`) has not yet completed.
111 const BLOCKED: u32 = 0xffff_ffff;
112 
113 /// Corresponds to `CallState` in the upstream spec.
114 #[derive(Clone, Copy, Eq, PartialEq, Debug)]
115 pub enum Status {
116     Starting = 0,
117     Started = 1,
118     Returned = 2,
119     StartCancelled = 3,
120     ReturnCancelled = 4,
121 }
122 
123 impl Status {
124     /// Packs this status and the optional `waitable` provided into a 32-bit
125     /// result that the canonical ABI requires.
126     ///
127     /// The low 4 bits are reserved for the status while the upper 28 bits are
128     /// the waitable, if present.
129     pub fn pack(self, waitable: Option<u32>) -> u32 {
130         assert!(matches!(self, Status::Returned) == waitable.is_none());
131         let waitable = waitable.unwrap_or(0);
132         assert!(waitable < (1 << 28));
133         (waitable << 4) | (self as u32)
134     }
135 }
136 
137 /// Corresponds to `EventCode` in the Component Model spec, plus related payload
138 /// data.
139 #[derive(Clone, Copy, Debug)]
140 enum Event {
141     None,
142     Cancelled,
143     Subtask {
144         status: Status,
145     },
146     StreamRead {
147         code: ReturnCode,
148         pending: Option<(TypeStreamTableIndex, u32)>,
149     },
150     StreamWrite {
151         code: ReturnCode,
152         pending: Option<(TypeStreamTableIndex, u32)>,
153     },
154     FutureRead {
155         code: ReturnCode,
156         pending: Option<(TypeFutureTableIndex, u32)>,
157     },
158     FutureWrite {
159         code: ReturnCode,
160         pending: Option<(TypeFutureTableIndex, u32)>,
161     },
162 }
163 
164 impl Event {
165     /// Lower this event to core Wasm integers for delivery to the guest.
166     ///
167     /// Note that the waitable handle, if any, is assumed to be lowered
168     /// separately.
169     fn parts(self) -> (u32, u32) {
170         const EVENT_NONE: u32 = 0;
171         const EVENT_SUBTASK: u32 = 1;
172         const EVENT_STREAM_READ: u32 = 2;
173         const EVENT_STREAM_WRITE: u32 = 3;
174         const EVENT_FUTURE_READ: u32 = 4;
175         const EVENT_FUTURE_WRITE: u32 = 5;
176         const EVENT_CANCELLED: u32 = 6;
177         match self {
178             Event::None => (EVENT_NONE, 0),
179             Event::Cancelled => (EVENT_CANCELLED, 0),
180             Event::Subtask { status } => (EVENT_SUBTASK, status as u32),
181             Event::StreamRead { code, .. } => (EVENT_STREAM_READ, code.encode()),
182             Event::StreamWrite { code, .. } => (EVENT_STREAM_WRITE, code.encode()),
183             Event::FutureRead { code, .. } => (EVENT_FUTURE_READ, code.encode()),
184             Event::FutureWrite { code, .. } => (EVENT_FUTURE_WRITE, code.encode()),
185         }
186     }
187 }
188 
189 /// Corresponds to `CallbackCode` in the spec.
190 mod callback_code {
191     pub const EXIT: u32 = 0;
192     pub const YIELD: u32 = 1;
193     pub const WAIT: u32 = 2;
194     pub const POLL: u32 = 3;
195 }
196 
197 /// A flag indicating that the callee is an async-lowered export.
198 ///
199 /// This may be passed to the `async-start` intrinsic from a fused adapter.
200 const START_FLAG_ASYNC_CALLEE: u32 = wasmtime_environ::component::START_FLAG_ASYNC_CALLEE as u32;
201 
202 /// Provides access to either store data (via the `get` method) or the store
203 /// itself (via [`AsContext`]/[`AsContextMut`]), as well as the component
204 /// instance to which the current host task belongs.
205 ///
206 /// See [`Accessor::with`] for details.
207 pub struct Access<'a, T: 'static, D: HasData + ?Sized = HasSelf<T>> {
208     store: StoreContextMut<'a, T>,
209     get_data: fn(&mut T) -> D::Data<'_>,
210     instance: Option<Instance>,
211 }
212 
213 impl<'a, T, D> Access<'a, T, D>
214 where
215     D: HasData + ?Sized,
216     T: 'static,
217 {
218     /// Creates a new [`Access`] from its component parts.
219     pub fn new(store: StoreContextMut<'a, T>, get_data: fn(&mut T) -> D::Data<'_>) -> Self {
220         Self {
221             store,
222             get_data,
223             instance: None,
224         }
225     }
226 
227     /// Get mutable access to the store data.
228     pub fn data_mut(&mut self) -> &mut T {
229         self.store.data_mut()
230     }
231 
232     /// Get mutable access to the store data.
233     pub fn get(&mut self) -> D::Data<'_> {
234         (self.get_data)(self.data_mut())
235     }
236 
237     /// Spawn a background task.
238     ///
239     /// See [`Accessor::spawn`] for details.
240     pub fn spawn(&mut self, task: impl AccessorTask<T, D, Result<()>>) -> JoinHandle
241     where
242         T: 'static,
243     {
244         let accessor = Accessor {
245             get_data: self.get_data,
246             instance: self.instance,
247             token: StoreToken::new(self.store.as_context_mut()),
248         };
249         self.instance
250             .unwrap()
251             .spawn_with_accessor(self.store.as_context_mut(), accessor, task)
252     }
253 
254     /// Retrieve the component instance of the caller.
255     pub fn instance(&self) -> Instance {
256         self.instance.unwrap()
257     }
258 }
259 
260 impl<'a, T, D> AsContext for Access<'a, T, D>
261 where
262     D: HasData + ?Sized,
263     T: 'static,
264 {
265     type Data = T;
266 
267     fn as_context(&self) -> StoreContext<'_, T> {
268         self.store.as_context()
269     }
270 }
271 
272 impl<'a, T, D> AsContextMut for Access<'a, T, D>
273 where
274     D: HasData + ?Sized,
275     T: 'static,
276 {
277     fn as_context_mut(&mut self) -> StoreContextMut<'_, T> {
278         self.store.as_context_mut()
279     }
280 }
281 
282 /// Provides scoped mutable access to store data in the context of a concurrent
283 /// host task future.
284 ///
285 /// This allows multiple host task futures to execute concurrently and access
286 /// the store between (but not across) `await` points.
287 ///
288 /// # Rationale
289 ///
290 /// This structure is sort of like `&mut T` plus a projection from `&mut T` to
291 /// `D::Data<'_>`. The problem this is solving, however, is that it does not
292 /// literally store these values. The basic problem is that when a concurrent
293 /// host future is being polled it has access to `&mut T` (and the whole
294 /// `Store`) but when it's not being polled it does not have access to these
295 /// values. This reflects how the store is only ever polling one future at a
296 /// time so the store is effectively being passed between futures.
297 ///
298 /// Rust's `Future` trait, however, has no means of passing a `Store`
299 /// temporarily between futures. The [`Context`](std::task::Context) type does
300 /// not have the ability to attach arbitrary information to it at this time.
301 /// This type, [`Accessor`], is used to bridge this expressivity gap.
302 ///
303 /// The [`Accessor`] type here represents the ability to acquire, temporarily in
304 /// a synchronous manner, the current store. The [`Accessor::with`] function
305 /// yields an [`Access`] which can be used to access [`StoreContextMut`], `&mut
306 /// T`, or `D::Data<'_>`. Note though that [`Accessor::with`] intentionally does
307 /// not take an `async` closure as its argument, instead it's a synchronous
308 /// closure which must complete during on run of `Future::poll`. This reflects
309 /// how the store is temporarily made available while a host future is being
310 /// polled.
311 ///
312 /// # Implementation
313 ///
314 /// This type does not actually store `&mut T` nor `StoreContextMut<T>`, and
315 /// this type additionally doesn't even have a lifetime parameter. This is
316 /// instead a representation of proof of the ability to acquire these while a
317 /// future is being polled. Wasmtime will, when it polls a host future,
318 /// configure ambient state such that the `Accessor` that a future closes over
319 /// will work and be able to access the store.
320 ///
321 /// This has a number of implications for users such as:
322 ///
323 /// * It's intentional that `Accessor` cannot be cloned, it needs to stay within
324 ///   the lifetime of a single future.
325 /// * A future is expected to, however, close over an `Accessor` and keep it
326 ///   alive probably for the duration of the entire future.
327 /// * Different host futures will be given different `Accessor`s, and that's
328 ///   intentional.
329 /// * The `Accessor` type is `Send` and `Sync` irrespective of `T` which
330 ///   alleviates some otherwise required bounds to be written down.
331 ///
332 /// # Using `Accessor` in `Drop`
333 ///
334 /// The methods on `Accessor` are only expected to work in the context of
335 /// `Future::poll` and are not guaranteed to work in `Drop`. This is because a
336 /// host future can be dropped at any time throughout the system and Wasmtime
337 /// store context is not necessarily available at that time. It's recommended to
338 /// not use `Accessor` methods in anything connected to a `Drop` implementation
339 /// as they will panic and have unintended results. If you run into this though
340 /// feel free to file an issue on the Wasmtime repository.
341 pub struct Accessor<T: 'static, D = HasSelf<T>>
342 where
343     D: HasData + ?Sized,
344 {
345     token: StoreToken<T>,
346     get_data: fn(&mut T) -> D::Data<'_>,
347     instance: Option<Instance>,
348 }
349 
350 /// A helper trait to take any type of accessor-with-data in functions.
351 ///
352 /// This trait is similar to [`AsContextMut`] except that it's used when
353 /// working with an [`Accessor`] instead of a [`StoreContextMut`]. The
354 /// [`Accessor`] is the main type used in concurrent settings and is passed to
355 /// functions such as [`Func::call_concurrent`] or [`FutureWriter::write`].
356 ///
357 /// This trait is implemented for [`Accessor`] and `&T` where `T` implements
358 /// this trait. This effectively means that regardless of the `D` in
359 /// `Accessor<T, D>` it can still be passed to a function which just needs a
360 /// store accessor.
361 ///
362 /// Acquiring an [`Accessor`] can be done through [`Instance::run_concurrent`]
363 /// for example or in a host function through
364 /// [`Linker::func_wrap_concurrent`](crate::component::Linker::func_wrap_concurrent).
365 pub trait AsAccessor {
366     /// The `T` in `Store<T>` that this accessor refers to.
367     type Data: 'static;
368 
369     /// The `D` in `Accessor<T, D>`, or the projection out of
370     /// `Self::Data`.
371     type AccessorData: HasData + ?Sized;
372 
373     /// Returns the accessor that this is referring to.
374     fn as_accessor(&self) -> &Accessor<Self::Data, Self::AccessorData>;
375 }
376 
377 impl<T: AsAccessor + ?Sized> AsAccessor for &T {
378     type Data = T::Data;
379     type AccessorData = T::AccessorData;
380 
381     fn as_accessor(&self) -> &Accessor<Self::Data, Self::AccessorData> {
382         T::as_accessor(self)
383     }
384 }
385 
386 impl<T, D: HasData + ?Sized> AsAccessor for Accessor<T, D> {
387     type Data = T;
388     type AccessorData = D;
389 
390     fn as_accessor(&self) -> &Accessor<T, D> {
391         self
392     }
393 }
394 
395 // Note that it is intentional at this time that `Accessor` does not actually
396 // store `&mut T` or anything similar. This distinctly enables the `Accessor`
397 // structure to be both `Send` and `Sync` regardless of what `T` is (or `D` for
398 // that matter). This is used to ergonomically simplify bindings where the
399 // majority of the time `Accessor` is closed over in a future which then needs
400 // to be `Send` and `Sync`. To avoid needing to write `T: Send` everywhere (as
401 // you already have to write `T: 'static`...) it helps to avoid this.
402 //
403 // Note as well that `Accessor` doesn't actually store its data at all. Instead
404 // it's more of a "proof" of what can be accessed from TLS. API design around
405 // `Accessor` and functions like `Linker::func_wrap_concurrent` are
406 // intentionally made to ensure that `Accessor` is ideally only used in the
407 // context that TLS variables are actually set. For example host functions are
408 // given `&Accessor`, not `Accessor`, and this prevents them from persisting
409 // the value outside of a future. Within the future the TLS variables are all
410 // guaranteed to be set while the future is being polled.
411 //
412 // Finally though this is not an ironclad guarantee, but nor does it need to be.
413 // The TLS APIs are designed to panic or otherwise model usage where they're
414 // called recursively or similar. It's hoped that code cannot be constructed to
415 // actually hit this at runtime but this is not a safety requirement at this
416 // time.
417 const _: () = {
418     const fn assert<T: Send + Sync>() {}
419     assert::<Accessor<UnsafeCell<u32>>>();
420 };
421 
422 impl<T> Accessor<T> {
423     /// Creates a new `Accessor` backed by the specified functions.
424     ///
425     /// - `get`: used to retrieve the store
426     ///
427     /// - `get_data`: used to "project" from the store's associated data to
428     /// another type (e.g. a field of that data or a wrapper around it).
429     ///
430     /// - `spawn`: used to queue spawned background tasks to be run later
431     ///
432     /// - `instance`: used to access the `Instance` to which this `Accessor`
433     /// (and the future which closes over it) belongs
434     pub(crate) fn new(token: StoreToken<T>, instance: Option<Instance>) -> Self {
435         Self {
436             token,
437             get_data: |x| x,
438             instance,
439         }
440     }
441 }
442 
443 impl<T, D> Accessor<T, D>
444 where
445     D: HasData + ?Sized,
446 {
447     /// Run the specified closure, passing it mutable access to the store.
448     ///
449     /// This function is one of the main building blocks of the [`Accessor`]
450     /// type. This yields synchronous, blocking, access to store via an
451     /// [`Access`]. The [`Access`] implements [`AsContextMut`] in addition to
452     /// providing the ability to access `D` via [`Access::get`]. Note that the
453     /// `fun` here is given only temporary access to the store and `T`/`D`
454     /// meaning that the return value `R` here is not allowed to capture borrows
455     /// into the two. If access is needed to data within `T` or `D` outside of
456     /// this closure then it must be `clone`d out, for example.
457     ///
458     /// # Panics
459     ///
460     /// This function will panic if it is call recursively with any other
461     /// accessor already in scope. For example if `with` is called within `fun`,
462     /// then this function will panic. It is up to the embedder to ensure that
463     /// this does not happen.
464     pub fn with<R>(&self, fun: impl FnOnce(Access<'_, T, D>) -> R) -> R {
465         tls::get(|vmstore| {
466             fun(Access {
467                 store: self.token.as_context_mut(vmstore),
468                 get_data: self.get_data,
469                 instance: self.instance,
470             })
471         })
472     }
473 
474     /// Returns the getter this accessor is using to project from `T` into
475     /// `D::Data`.
476     pub fn getter(&self) -> fn(&mut T) -> D::Data<'_> {
477         self.get_data
478     }
479 
480     /// Changes this accessor to access `D2` instead of the current type
481     /// parameter `D`.
482     ///
483     /// This changes the underlying data access from `T` to `D2::Data<'_>`.
484     ///
485     /// # Panics
486     ///
487     /// When using this API the returned value is disconnected from `&self` and
488     /// the lifetime binding the `self` argument. An `Accessor` only works
489     /// within the context of the closure or async closure that it was
490     /// originally given to, however. This means that due to the fact that the
491     /// returned value has no lifetime connection it's possible to use the
492     /// accessor outside of `&self`, the original accessor, and panic.
493     ///
494     /// The returned value should only be used within the scope of the original
495     /// `Accessor` that `self` refers to.
496     pub fn with_getter<D2: HasData>(
497         &self,
498         get_data: fn(&mut T) -> D2::Data<'_>,
499     ) -> Accessor<T, D2> {
500         Accessor {
501             token: self.token,
502             get_data,
503             instance: self.instance,
504         }
505     }
506 
507     /// Spawn a background task which will receive an `&Accessor<T, D>` and
508     /// run concurrently with any other tasks in progress for the current
509     /// instance.
510     ///
511     /// This is particularly useful for host functions which return a `stream`
512     /// or `future` such that the code to write to the write end of that
513     /// `stream` or `future` must run after the function returns.
514     ///
515     /// The returned [`JoinHandle`] may be used to cancel the task.
516     ///
517     /// # Panics
518     ///
519     /// Panics if called within a closure provided to the [`Accessor::with`]
520     /// function. This can only be called outside an active invocation of
521     /// [`Accessor::with`].
522     pub fn spawn(&self, task: impl AccessorTask<T, D, Result<()>>) -> JoinHandle
523     where
524         T: 'static,
525     {
526         let instance = self.instance.unwrap();
527         let accessor = self.clone_for_spawn();
528         self.with(|mut access| {
529             instance.spawn_with_accessor(access.as_context_mut(), accessor, task)
530         })
531     }
532 
533     /// Retrieve the component instance of the caller.
534     pub fn instance(&self) -> Instance {
535         self.instance.unwrap()
536     }
537 
538     fn clone_for_spawn(&self) -> Self {
539         Self {
540             token: self.token,
541             get_data: self.get_data,
542             instance: self.instance,
543         }
544     }
545 }
546 
547 /// Represents a task which may be provided to `Accessor::spawn`,
548 /// `Accessor::forward`, or `Instance::spawn`.
549 // TODO: Replace this with `std::ops::AsyncFnOnce` when that becomes a viable
550 // option.
551 //
552 // `AsyncFnOnce` is still nightly-only in latest stable Rust version as of this
553 // writing (1.84.1), and even with 1.85.0-beta it's not possible to specify
554 // e.g. `Send` and `Sync` bounds on the `Future` type returned by an
555 // `AsyncFnOnce`.  Also, using `F: Future<Output = Result<()>> + Send + Sync,
556 // FN: FnOnce(&Accessor<T>) -> F + Send + Sync + 'static` fails with a type
557 // mismatch error when we try to pass it an async closure (e.g. `async move |_|
558 // { ... }`).  So this seems to be the best we can do for the time being.
559 pub trait AccessorTask<T, D, R>: Send + 'static
560 where
561     D: HasData + ?Sized,
562 {
563     /// Run the task.
564     fn run(self, accessor: &Accessor<T, D>) -> impl Future<Output = R> + Send;
565 }
566 
567 /// Represents parameter and result metadata for the caller side of a
568 /// guest->guest call orchestrated by a fused adapter.
569 enum CallerInfo {
570     /// Metadata for a call to an async-lowered import
571     Async {
572         params: Vec<ValRaw>,
573         has_result: bool,
574     },
575     /// Metadata for a call to an sync-lowered import
576     Sync {
577         params: Vec<ValRaw>,
578         result_count: u32,
579     },
580 }
581 
582 /// Indicates how a guest task is waiting on a waitable set.
583 enum WaitMode {
584     /// The guest task is waiting using `task.wait`
585     Fiber(StoreFiber<'static>),
586     /// The guest task is waiting via a callback declared as part of an
587     /// async-lifted export.
588     Callback,
589 }
590 
591 /// Represents the reason a fiber is suspending itself.
592 #[derive(Debug)]
593 enum SuspendReason {
594     /// The fiber is waiting for an event to be delivered to the specified
595     /// waitable set or task.
596     Waiting {
597         set: TableId<WaitableSet>,
598         task: TableId<GuestTask>,
599     },
600     /// The fiber has finished handling its most recent work item and is waiting
601     /// for another (or to be dropped if it is no longer needed).
602     NeedWork,
603     /// The fiber is yielding and should be resumed once other tasks have had a
604     /// chance to run.
605     Yielding { task: TableId<GuestTask> },
606 }
607 
608 /// Represents a pending call into guest code for a given guest task.
609 enum GuestCallKind {
610     /// Indicates there's an event to deliver to the task, possibly related to a
611     /// waitable set the task has been waiting on or polling.
612     DeliverEvent {
613         /// The waitable set the event belongs to, if any.
614         ///
615         /// If this is `None` the event will be waiting in the
616         /// `GuestTask::event` field for the task.
617         set: Option<TableId<WaitableSet>>,
618     },
619     /// Indicates that a new guest task call is pending and may be executed
620     /// using the specified closure.
621     Start(Box<dyn FnOnce(&mut dyn VMStore, Instance) -> Result<()> + Send + Sync>),
622 }
623 
624 impl fmt::Debug for GuestCallKind {
625     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
626         match self {
627             Self::DeliverEvent { set } => f.debug_struct("DeliverEvent").field("set", set).finish(),
628             Self::Start(_) => f.debug_tuple("Start").finish(),
629         }
630     }
631 }
632 
633 /// Represents a pending call into guest code for a given guest task.
634 #[derive(Debug)]
635 struct GuestCall {
636     task: TableId<GuestTask>,
637     kind: GuestCallKind,
638 }
639 
640 impl GuestCall {
641     /// Returns whether or not the call is ready to run.
642     ///
643     /// A call will not be ready to run if either:
644     ///
645     /// - the (sub-)component instance to be called has already been entered and
646     /// cannot be reentered until an in-progress call completes
647     ///
648     /// - the call is for a not-yet started task and the (sub-)component
649     /// instance to be called has backpressure enabled
650     fn is_ready(&self, state: &mut ConcurrentState) -> Result<bool> {
651         let task_instance = state.get_mut(self.task)?.instance;
652         let state = state.instance_state(task_instance);
653         let ready = match &self.kind {
654             GuestCallKind::DeliverEvent { .. } => !state.do_not_enter,
655             GuestCallKind::Start(_) => !(state.do_not_enter || state.backpressure > 0),
656         };
657         log::trace!(
658             "call {self:?} ready? {ready} (do_not_enter: {}; backpressure: {})",
659             state.do_not_enter,
660             state.backpressure
661         );
662         Ok(ready)
663     }
664 }
665 
666 /// Job to be run on a worker fiber.
667 enum WorkerItem {
668     GuestCall(GuestCall),
669     Function(AlwaysMut<Box<dyn FnOnce(&mut dyn VMStore, Instance) -> Result<()> + Send>>),
670 }
671 
672 /// Represents state related to an in-progress poll operation (e.g. `task.poll`
673 /// or `CallbackCode.POLL`).
674 #[derive(Debug)]
675 struct PollParams {
676     /// Identifies the polling task.
677     task: TableId<GuestTask>,
678     /// The waitable set being polled.
679     set: TableId<WaitableSet>,
680 }
681 
682 /// Represents a pending work item to be handled by the event loop for a given
683 /// component instance.
684 enum WorkItem {
685     /// A host task to be pushed to `ConcurrentState::futures`.
686     PushFuture(AlwaysMut<HostTaskFuture>),
687     /// A fiber to resume.
688     ResumeFiber(StoreFiber<'static>),
689     /// A pending call into guest code for a given guest task.
690     GuestCall(GuestCall),
691     /// A pending `task.poll` or `CallbackCode.POLL` operation.
692     Poll(PollParams),
693     /// A job to run on a worker fiber.
694     WorkerFunction(AlwaysMut<Box<dyn FnOnce(&mut dyn VMStore, Instance) -> Result<()> + Send>>),
695 }
696 
697 impl fmt::Debug for WorkItem {
698     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
699         match self {
700             Self::PushFuture(_) => f.debug_tuple("PushFuture").finish(),
701             Self::ResumeFiber(_) => f.debug_tuple("ResumeFiber").finish(),
702             Self::GuestCall(call) => f.debug_tuple("GuestCall").field(call).finish(),
703             Self::Poll(params) => f.debug_tuple("Poll").field(params).finish(),
704             Self::WorkerFunction(_) => f.debug_tuple("WorkerFunction").finish(),
705         }
706     }
707 }
708 
709 impl ComponentInstance {
710     /// Handle the `CallbackCode` returned from an async-lifted export or its
711     /// callback.
712     ///
713     /// If `initial_call` is `true`, then the code was received from the
714     /// async-lifted export; otherwise, it was received from its callback.
715     fn handle_callback_code(
716         mut self: Pin<&mut Self>,
717         guest_task: TableId<GuestTask>,
718         runtime_instance: RuntimeComponentInstanceIndex,
719         code: u32,
720         initial_call: bool,
721     ) -> Result<()> {
722         let (code, set) = unpack_callback_code(code);
723 
724         log::trace!("received callback code from {guest_task:?}: {code} (set: {set})");
725 
726         let state = self.as_mut().concurrent_state_mut();
727         let task = state.get_mut(guest_task)?;
728 
729         if task.lift_result.is_some() {
730             if code == callback_code::EXIT {
731                 return Err(anyhow!(crate::Trap::NoAsyncResult));
732             }
733             if initial_call {
734                 // Notify any current or future waiters that this subtask has
735                 // started.
736                 Waitable::Guest(guest_task).set_event(
737                     state,
738                     Some(Event::Subtask {
739                         status: Status::Started,
740                     }),
741                 )?;
742             }
743         }
744 
745         let get_set = |instance: Pin<&mut Self>, handle| {
746             if handle == 0 {
747                 bail!("invalid waitable-set handle");
748             }
749 
750             let set = instance.guest_tables().0[runtime_instance].waitable_set_rep(handle)?;
751 
752             Ok(TableId::<WaitableSet>::new(set))
753         };
754 
755         match code {
756             callback_code::EXIT => {
757                 let task = state.get_mut(guest_task)?;
758                 match &task.caller {
759                     Caller::Host {
760                         remove_task_automatically,
761                         ..
762                     } => {
763                         if *remove_task_automatically {
764                             log::trace!("handle_callback_code will delete task {guest_task:?}");
765                             Waitable::Guest(guest_task).delete_from(state)?;
766                         }
767                     }
768                     Caller::Guest { .. } => {
769                         task.exited = true;
770                         task.callback = None;
771                     }
772                 }
773             }
774             callback_code::YIELD => {
775                 // Push this task onto the "low priority" queue so it runs after
776                 // any other tasks have had a chance to run.
777                 let task = state.get_mut(guest_task)?;
778                 assert!(task.event.is_none());
779                 task.event = Some(Event::None);
780                 state.push_low_priority(WorkItem::GuestCall(GuestCall {
781                     task: guest_task,
782                     kind: GuestCallKind::DeliverEvent { set: None },
783                 }));
784             }
785             callback_code::WAIT | callback_code::POLL => {
786                 let set = get_set(self.as_mut(), set)?;
787                 let state = self.concurrent_state_mut();
788 
789                 if state.get_mut(guest_task)?.event.is_some()
790                     || !state.get_mut(set)?.ready.is_empty()
791                 {
792                     // An event is immediately available; deliver it ASAP.
793                     state.push_high_priority(WorkItem::GuestCall(GuestCall {
794                         task: guest_task,
795                         kind: GuestCallKind::DeliverEvent { set: Some(set) },
796                     }));
797                 } else {
798                     // No event is immediately available.
799                     match code {
800                         callback_code::POLL => {
801                             // We're polling, so just yield and check whether an
802                             // event has arrived after that.
803                             state.push_low_priority(WorkItem::Poll(PollParams {
804                                 task: guest_task,
805                                 set,
806                             }));
807                         }
808                         callback_code::WAIT => {
809                             // We're waiting, so register to be woken up when an
810                             // event is published for this waitable set.
811                             //
812                             // Here we also set `GuestTask::wake_on_cancel`
813                             // which allows `subtask.cancel` to interrupt the
814                             // wait.
815                             let old = state.get_mut(guest_task)?.wake_on_cancel.replace(set);
816                             assert!(old.is_none());
817                             let old = state
818                                 .get_mut(set)?
819                                 .waiting
820                                 .insert(guest_task, WaitMode::Callback);
821                             assert!(old.is_none());
822                         }
823                         _ => unreachable!(),
824                     }
825                 }
826             }
827             _ => bail!("unsupported callback code: {code}"),
828         }
829 
830         Ok(())
831     }
832 
833     /// Get the next pending event for the specified task and (optional)
834     /// waitable set, along with the waitable handle if applicable.
835     fn get_event(
836         mut self: Pin<&mut Self>,
837         guest_task: TableId<GuestTask>,
838         set: Option<TableId<WaitableSet>>,
839         cancellable: bool,
840     ) -> Result<Option<(Event, Option<(Waitable, u32)>)>> {
841         let state = self.as_mut().concurrent_state_mut();
842 
843         if let Some(event) = state.get_mut(guest_task)?.event.take() {
844             log::trace!("deliver event {event:?} to {guest_task:?}");
845 
846             if cancellable || !matches!(event, Event::Cancelled) {
847                 return Ok(Some((event, None)));
848             } else {
849                 state.get_mut(guest_task)?.event = Some(event);
850             }
851         }
852 
853         Ok(
854             if let Some((set, waitable)) = set
855                 .and_then(|set| {
856                     state
857                         .get_mut(set)
858                         .map(|v| v.ready.pop_first().map(|v| (set, v)))
859                         .transpose()
860                 })
861                 .transpose()?
862             {
863                 let common = waitable.common(state)?;
864                 let handle = common.handle.unwrap();
865                 let event = common.event.take().unwrap();
866 
867                 log::trace!(
868                     "deliver event {event:?} to {guest_task:?} for {waitable:?} (handle {handle}); set {set:?}"
869                 );
870 
871                 waitable.on_delivery(self, event);
872 
873                 Some((event, Some((waitable, handle))))
874             } else {
875                 None
876             },
877         )
878     }
879 
880     /// Implements the `waitable-set.new` intrinsic.
881     pub(crate) fn waitable_set_new(
882         mut self: Pin<&mut Self>,
883         caller_instance: RuntimeComponentInstanceIndex,
884     ) -> Result<u32> {
885         self.check_may_leave(caller_instance)?;
886         let set = self
887             .as_mut()
888             .concurrent_state_mut()
889             .push(WaitableSet::default())?;
890         let handle = self.guest_tables().0[caller_instance].waitable_set_insert(set.rep())?;
891         log::trace!("new waitable set {set:?} (handle {handle})");
892         Ok(handle)
893     }
894 
895     /// Implements the `waitable-set.drop` intrinsic.
896     pub(crate) fn waitable_set_drop(
897         mut self: Pin<&mut Self>,
898         caller_instance: RuntimeComponentInstanceIndex,
899         set: u32,
900     ) -> Result<()> {
901         self.check_may_leave(caller_instance)?;
902         let rep = self.as_mut().guest_tables().0[caller_instance].waitable_set_remove(set)?;
903 
904         log::trace!("drop waitable set {rep} (handle {set})");
905 
906         let set = self
907             .concurrent_state_mut()
908             .delete(TableId::<WaitableSet>::new(rep))?;
909 
910         if !set.waiting.is_empty() {
911             bail!("cannot drop waitable set with waiters");
912         }
913 
914         Ok(())
915     }
916 
917     /// Implements the `waitable.join` intrinsic.
918     pub(crate) fn waitable_join(
919         mut self: Pin<&mut Self>,
920         caller_instance: RuntimeComponentInstanceIndex,
921         waitable_handle: u32,
922         set_handle: u32,
923     ) -> Result<()> {
924         self.check_may_leave(caller_instance)?;
925         let waitable = Waitable::from_instance(self.as_mut(), caller_instance, waitable_handle)?;
926 
927         let set = if set_handle == 0 {
928             None
929         } else {
930             let set =
931                 self.as_mut().guest_tables().0[caller_instance].waitable_set_rep(set_handle)?;
932 
933             Some(TableId::<WaitableSet>::new(set))
934         };
935 
936         log::trace!(
937             "waitable {waitable:?} (handle {waitable_handle}) join set {set:?} (handle {set_handle})",
938         );
939 
940         waitable.join(self.concurrent_state_mut(), set)
941     }
942 
943     /// Implements the `subtask.drop` intrinsic.
944     pub(crate) fn subtask_drop(
945         mut self: Pin<&mut Self>,
946         caller_instance: RuntimeComponentInstanceIndex,
947         task_id: u32,
948     ) -> Result<()> {
949         self.check_may_leave(caller_instance)?;
950         self.as_mut().waitable_join(caller_instance, task_id, 0)?;
951 
952         let (rep, is_host) =
953             self.as_mut().guest_tables().0[caller_instance].subtask_remove(task_id)?;
954 
955         let concurrent_state = self.concurrent_state_mut();
956         let (waitable, expected_caller_instance, delete) = if is_host {
957             let id = TableId::<HostTask>::new(rep);
958             let task = concurrent_state.get_mut(id)?;
959             if task.join_handle.is_some() {
960                 bail!("cannot drop a subtask which has not yet resolved");
961             }
962             (Waitable::Host(id), task.caller_instance, true)
963         } else {
964             let id = TableId::<GuestTask>::new(rep);
965             let task = concurrent_state.get_mut(id)?;
966             if task.lift_result.is_some() {
967                 bail!("cannot drop a subtask which has not yet resolved");
968             }
969             if let Caller::Guest { instance, .. } = &task.caller {
970                 (Waitable::Guest(id), *instance, task.exited)
971             } else {
972                 unreachable!()
973             }
974         };
975 
976         waitable.common(concurrent_state)?.handle = None;
977 
978         if waitable.take_event(concurrent_state)?.is_some() {
979             bail!("cannot drop a subtask with an undelivered event");
980         }
981 
982         if delete {
983             waitable.delete_from(concurrent_state)?;
984         }
985 
986         // Since waitables can neither be passed between instances nor forged,
987         // this should never fail unless there's a bug in Wasmtime, but we check
988         // here to be sure:
989         assert_eq!(expected_caller_instance, caller_instance);
990         log::trace!("subtask_drop {waitable:?} (handle {task_id})");
991         Ok(())
992     }
993 }
994 
995 impl Instance {
996     /// Assert that all the relevant tables and queues in the concurrent state
997     /// for this instance are empty.
998     ///
999     /// This is for sanity checking in integration tests
1000     /// (e.g. `component-async-tests`) that the relevant state has been cleared
1001     /// after each test concludes.  This should help us catch leaks, e.g. guest
1002     /// tasks which haven't been deleted despite having completed and having
1003     /// been dropped by their supertasks.
1004     #[doc(hidden)]
1005     pub fn assert_concurrent_state_empty(&self, mut store: impl AsContextMut) {
1006         let mut instance = self.id().get_mut(store.as_context_mut().0);
1007         assert!(
1008             instance
1009                 .as_mut()
1010                 .guest_tables()
1011                 .0
1012                 .iter()
1013                 .all(|(_, table)| table.is_empty())
1014         );
1015         let state = instance.concurrent_state_mut();
1016         assert!(
1017             state.table.get_mut().is_empty(),
1018             "non-empty table: {:?}",
1019             state.table.get_mut()
1020         );
1021         assert!(state.high_priority.is_empty());
1022         assert!(state.low_priority.is_empty());
1023         assert!(state.guest_task.is_none());
1024         assert!(state.futures.get_mut().as_ref().unwrap().is_empty());
1025         assert!(
1026             state
1027                 .instance_states
1028                 .iter()
1029                 .all(|(_, state)| state.pending.is_empty())
1030         );
1031         assert!(state.global_error_context_ref_counts.is_empty());
1032     }
1033 
1034     /// Run the specified closure `fun` to completion as part of this instance's
1035     /// event loop.
1036     ///
1037     /// Like [`Self::run`], this will run `fun` as part of this instance's event
1038     /// loop until it yields a result _or_ there are no more tasks to run.
1039     /// Unlike [`Self::run`], `fun` is provided an [`Accessor`], which provides
1040     /// controlled access to the `Store` and its data.
1041     ///
1042     /// This function can be used to invoke [`Func::call_concurrent`] for
1043     /// example within the async closure provided here.
1044     ///
1045     /// # Example
1046     ///
1047     /// ```
1048     /// # use {
1049     /// #   anyhow::{Result},
1050     /// #   wasmtime::{
1051     /// #     component::{ Component, Linker, Resource, ResourceTable},
1052     /// #     Config, Engine, Store
1053     /// #   },
1054     /// # };
1055     /// #
1056     /// # struct MyResource(u32);
1057     /// # struct Ctx { table: ResourceTable }
1058     /// #
1059     /// # async fn foo() -> Result<()> {
1060     /// # let mut config = Config::new();
1061     /// # let engine = Engine::new(&config)?;
1062     /// # let mut store = Store::new(&engine, Ctx { table: ResourceTable::new() });
1063     /// # let mut linker = Linker::new(&engine);
1064     /// # let component = Component::new(&engine, "")?;
1065     /// # let instance = linker.instantiate_async(&mut store, &component).await?;
1066     /// # let foo = instance.get_typed_func::<(Resource<MyResource>,), (Resource<MyResource>,)>(&mut store, "foo")?;
1067     /// # let bar = instance.get_typed_func::<(u32,), ()>(&mut store, "bar")?;
1068     /// instance.run_concurrent(&mut store, async |accessor| -> wasmtime::Result<_> {
1069     ///    let resource = accessor.with(|mut access| access.get().table.push(MyResource(42)))?;
1070     ///    let (another_resource,) = foo.call_concurrent(accessor, (resource,)).await?.0;
1071     ///    let value = accessor.with(|mut access| access.get().table.delete(another_resource))?;
1072     ///    bar.call_concurrent(accessor, (value.0,)).await?;
1073     ///    Ok(())
1074     /// }).await??;
1075     /// # Ok(())
1076     /// # }
1077     /// ```
1078     pub async fn run_concurrent<T, R>(
1079         self,
1080         mut store: impl AsContextMut<Data = T>,
1081         fun: impl AsyncFnOnce(&Accessor<T>) -> R,
1082     ) -> Result<R>
1083     where
1084         T: Send + 'static,
1085     {
1086         check_recursive_run();
1087         let mut store = store.as_context_mut();
1088         let token = StoreToken::new(store.as_context_mut());
1089 
1090         struct Dropper<'a, T: 'static, V> {
1091             store: StoreContextMut<'a, T>,
1092             value: ManuallyDrop<V>,
1093         }
1094 
1095         impl<'a, T, V> Drop for Dropper<'a, T, V> {
1096             fn drop(&mut self) {
1097                 tls::set(self.store.0, || {
1098                     // SAFETY: Here we drop the value without moving it for the
1099                     // first and only time -- per the contract for `Drop::drop`,
1100                     // this code won't run again, and the `value` field will no
1101                     // longer be accessible.
1102                     unsafe { ManuallyDrop::drop(&mut self.value) }
1103                 });
1104             }
1105         }
1106 
1107         let accessor = &Accessor::new(token, Some(self));
1108         let dropper = &mut Dropper {
1109             store,
1110             value: ManuallyDrop::new(fun(accessor)),
1111         };
1112         // SAFETY: We never move `dropper` nor its `value` field.
1113         let future = unsafe { Pin::new_unchecked(dropper.value.deref_mut()) };
1114 
1115         self.poll_until(dropper.store.as_context_mut(), future)
1116             .await
1117     }
1118 
1119     /// Spawn a background task to run as part of this instance's event loop.
1120     ///
1121     /// The task will receive an `&Accessor<U>` and run concurrently with
1122     /// any other tasks in progress for the instance.
1123     ///
1124     /// Note that the task will only make progress if and when the event loop
1125     /// for this instance is run.
1126     ///
1127     /// The returned [`SpawnHandle`] may be used to cancel the task.
1128     pub fn spawn<U: 'static>(
1129         self,
1130         mut store: impl AsContextMut<Data = U>,
1131         task: impl AccessorTask<U, HasSelf<U>, Result<()>>,
1132     ) -> JoinHandle {
1133         let mut store = store.as_context_mut();
1134         let accessor = Accessor::new(StoreToken::new(store.as_context_mut()), Some(self));
1135         self.spawn_with_accessor(store, accessor, task)
1136     }
1137 
1138     /// Internal implementation of `spawn` functions where a `store` is
1139     /// available along with an `Accessor`.
1140     fn spawn_with_accessor<T, D>(
1141         self,
1142         mut store: StoreContextMut<T>,
1143         accessor: Accessor<T, D>,
1144         task: impl AccessorTask<T, D, Result<()>>,
1145     ) -> JoinHandle
1146     where
1147         T: 'static,
1148         D: HasData + ?Sized,
1149     {
1150         let store = store.as_context_mut();
1151 
1152         // Create an "abortable future" here where internally the future will
1153         // hook calls to poll and possibly spawn more background tasks on each
1154         // iteration.
1155         let (handle, future) = JoinHandle::run(async move { task.run(&accessor).await });
1156         self.concurrent_state_mut(store.0)
1157             .push_future(Box::pin(async move { future.await.unwrap_or(Ok(())) }));
1158 
1159         handle
1160     }
1161 
1162     /// Run this instance's event loop.
1163     ///
1164     /// The returned future will resolve when either the specified future
1165     /// completes (in which case we return its result) or no further progress
1166     /// can be made (in which case we trap with `Trap::AsyncDeadlock`).
1167     async fn poll_until<T, R>(
1168         self,
1169         mut store: StoreContextMut<'_, T>,
1170         mut future: Pin<&mut impl Future<Output = R>>,
1171     ) -> Result<R>
1172     where
1173         T: Send + 'static,
1174     {
1175         struct Reset<'a, T: 'static> {
1176             store: StoreContextMut<'a, T>,
1177             instance: Instance,
1178             futures: Option<FuturesUnordered<HostTaskFuture>>,
1179         }
1180 
1181         impl<'a, T> Drop for Reset<'a, T> {
1182             fn drop(&mut self) {
1183                 if let Some(futures) = self.futures.take() {
1184                     *self
1185                         .instance
1186                         .concurrent_state_mut(self.store.0)
1187                         .futures
1188                         .get_mut() = Some(futures);
1189                 }
1190             }
1191         }
1192 
1193         loop {
1194             // Take `ConcurrentState::futures` out of the instance so we can
1195             // poll it while also safely giving any of the futures inside access
1196             // to `self`.
1197             let futures = self.concurrent_state_mut(store.0).futures.get_mut().take();
1198             let mut reset = Reset {
1199                 store: store.as_context_mut(),
1200                 instance: self,
1201                 futures,
1202             };
1203             let mut next = pin!(reset.futures.as_mut().unwrap().next());
1204 
1205             let result = future::poll_fn(|cx| {
1206                 // First, poll the future we were passed as an argument and
1207                 // return immediately if it's ready.
1208                 if let Poll::Ready(value) = self.set_tls(reset.store.0, || future.as_mut().poll(cx))
1209                 {
1210                     return Poll::Ready(Ok(Either::Left(value)));
1211                 }
1212 
1213                 // Next, poll `ConcurrentState::futures` (which includes any
1214                 // pending host tasks and/or background tasks), returning
1215                 // immediately if one of them fails.
1216                 let next = match self.set_tls(reset.store.0, || next.as_mut().poll(cx)) {
1217                     Poll::Ready(Some(output)) => {
1218                         match output {
1219                             Err(e) => return Poll::Ready(Err(e)),
1220                             Ok(()) => {}
1221                         }
1222                         Poll::Ready(true)
1223                     }
1224                     Poll::Ready(None) => Poll::Ready(false),
1225                     Poll::Pending => Poll::Pending,
1226                 };
1227 
1228                 let mut instance = self.id().get_mut(reset.store.0);
1229 
1230                 // Next, check the "high priority" work queue and return
1231                 // immediately if it has at least one item.
1232                 let state = instance.as_mut().concurrent_state_mut();
1233                 let ready = mem::take(&mut state.high_priority);
1234                 let ready = if ready.is_empty() {
1235                     // Next, check the "low priority" work queue and return
1236                     // immediately if it has at least one item.
1237                     let ready = mem::take(&mut state.low_priority);
1238                     if ready.is_empty() {
1239                         return match next {
1240                             Poll::Ready(true) => {
1241                                 // In this case, one of the futures in
1242                                 // `ConcurrentState::futures` completed
1243                                 // successfully, so we return now and continue
1244                                 // the outer loop in case there is another one
1245                                 // ready to complete.
1246                                 Poll::Ready(Ok(Either::Right(Vec::new())))
1247                             }
1248                             Poll::Ready(false) => {
1249                                 // Poll the future we were passed one last time
1250                                 // in case one of `ConcurrentState::futures` had
1251                                 // the side effect of unblocking it.
1252                                 if let Poll::Ready(value) =
1253                                     self.set_tls(reset.store.0, || future.as_mut().poll(cx))
1254                                 {
1255                                     Poll::Ready(Ok(Either::Left(value)))
1256                                 } else {
1257                                     // In this case, there are no more pending
1258                                     // futures in `ConcurrentState::futures`,
1259                                     // there are no remaining work items, _and_
1260                                     // the future we were passed as an argument
1261                                     // still hasn't completed, meaning we're
1262                                     // stuck, so we return an error.  The
1263                                     // underlying assumption is that `future`
1264                                     // depends on this component instance making
1265                                     // such progress, and thus there's no point
1266                                     // in continuing to poll it given we've run
1267                                     // out of work to do.
1268                                     //
1269                                     // Note that we'd also reach this point if
1270                                     // the host embedder passed e.g. a
1271                                     // `std::future::Pending` to
1272                                     // `Instance::run_concurrent`, in which case
1273                                     // we'd return a "deadlock" error even when
1274                                     // any and all tasks have completed
1275                                     // normally.  However, that's not how
1276                                     // `Instance::run_concurrent` is intended
1277                                     // (and documented) to be used, so it seems
1278                                     // reasonable to lump that case in with
1279                                     // "real" deadlocks.
1280                                     //
1281                                     // TODO: Once we've added host APIs for
1282                                     // cancelling in-progress tasks, we can
1283                                     // return some other, non-error value here,
1284                                     // treating it as "normal" and giving the
1285                                     // host embedder a chance to intervene by
1286                                     // cancelling one or more tasks and/or
1287                                     // starting new tasks capable of waking the
1288                                     // existing ones.
1289                                     Poll::Ready(Err(anyhow!(crate::Trap::AsyncDeadlock)))
1290                                 }
1291                             }
1292                             // There is at least one pending future in
1293                             // `ConcurrentState::futures` and we have nothing
1294                             // else to do but wait for now, so we return
1295                             // `Pending`.
1296                             Poll::Pending => Poll::Pending,
1297                         };
1298                     } else {
1299                         ready
1300                     }
1301                 } else {
1302                     ready
1303                 };
1304 
1305                 Poll::Ready(Ok(Either::Right(ready)))
1306             })
1307             .await;
1308 
1309             // Put the `ConcurrentState::futures` back into the instance before
1310             // we return or handle any work items since one or more of those
1311             // items might append more futures.
1312             drop(reset);
1313 
1314             match result? {
1315                 // The future we were passed as an argument completed, so we
1316                 // return the result.
1317                 Either::Left(value) => break Ok(value),
1318                 // The future we were passed has not yet completed, so handle
1319                 // any work items and then loop again.
1320                 Either::Right(ready) => {
1321                     struct Dispose<'a, T: 'static, I: Iterator<Item = WorkItem>> {
1322                         store: StoreContextMut<'a, T>,
1323                         ready: I,
1324                     }
1325 
1326                     impl<'a, T, I: Iterator<Item = WorkItem>> Drop for Dispose<'a, T, I> {
1327                         fn drop(&mut self) {
1328                             while let Some(item) = self.ready.next() {
1329                                 match item {
1330                                     WorkItem::ResumeFiber(mut fiber) => fiber.dispose(self.store.0),
1331                                     WorkItem::PushFuture(future) => {
1332                                         tls::set(self.store.0, move || drop(future))
1333                                     }
1334                                     _ => {}
1335                                 }
1336                             }
1337                         }
1338                     }
1339 
1340                     let mut dispose = Dispose {
1341                         store: store.as_context_mut(),
1342                         ready: ready.into_iter(),
1343                     };
1344 
1345                     while let Some(item) = dispose.ready.next() {
1346                         self.handle_work_item(dispose.store.as_context_mut(), item)
1347                             .await?;
1348                     }
1349                 }
1350             }
1351         }
1352     }
1353 
1354     /// Handle the specified work item, possibly resuming a fiber if applicable.
1355     async fn handle_work_item<T: Send>(
1356         self,
1357         store: StoreContextMut<'_, T>,
1358         item: WorkItem,
1359     ) -> Result<()> {
1360         log::trace!("handle work item {item:?}");
1361         match item {
1362             WorkItem::PushFuture(future) => {
1363                 self.concurrent_state_mut(store.0)
1364                     .futures
1365                     .get_mut()
1366                     .as_mut()
1367                     .unwrap()
1368                     .push(future.into_inner());
1369             }
1370             WorkItem::ResumeFiber(fiber) => {
1371                 self.resume_fiber(store.0, fiber).await?;
1372             }
1373             WorkItem::GuestCall(call) => {
1374                 let state = self.concurrent_state_mut(store.0);
1375                 if call.is_ready(state)? {
1376                     self.run_on_worker(store, WorkerItem::GuestCall(call))
1377                         .await?;
1378                 } else {
1379                     let task = state.get_mut(call.task)?;
1380                     if !task.starting_sent {
1381                         task.starting_sent = true;
1382                         if let GuestCallKind::Start(_) = &call.kind {
1383                             Waitable::Guest(call.task).set_event(
1384                                 state,
1385                                 Some(Event::Subtask {
1386                                     status: Status::Starting,
1387                                 }),
1388                             )?;
1389                         }
1390                     }
1391 
1392                     let runtime_instance = state.get_mut(call.task)?.instance;
1393                     state
1394                         .instance_state(runtime_instance)
1395                         .pending
1396                         .insert(call.task, call.kind);
1397                 }
1398             }
1399             WorkItem::Poll(params) => {
1400                 let state = self.concurrent_state_mut(store.0);
1401                 if state.get_mut(params.task)?.event.is_some()
1402                     || !state.get_mut(params.set)?.ready.is_empty()
1403                 {
1404                     // There's at least one event immediately available; deliver
1405                     // it to the guest ASAP.
1406                     state.push_high_priority(WorkItem::GuestCall(GuestCall {
1407                         task: params.task,
1408                         kind: GuestCallKind::DeliverEvent {
1409                             set: Some(params.set),
1410                         },
1411                     }));
1412                 } else {
1413                     // There are no events immediately available; deliver
1414                     // `Event::None` to the guest.
1415                     state.get_mut(params.task)?.event = Some(Event::None);
1416                     state.push_high_priority(WorkItem::GuestCall(GuestCall {
1417                         task: params.task,
1418                         kind: GuestCallKind::DeliverEvent {
1419                             set: Some(params.set),
1420                         },
1421                     }));
1422                 }
1423             }
1424             WorkItem::WorkerFunction(fun) => {
1425                 self.run_on_worker(store, WorkerItem::Function(fun)).await?;
1426             }
1427         }
1428 
1429         Ok(())
1430     }
1431 
1432     /// Resume the specified fiber, giving it exclusive access to the specified
1433     /// store.
1434     async fn resume_fiber(self, store: &mut StoreOpaque, fiber: StoreFiber<'static>) -> Result<()> {
1435         let old_task = self.concurrent_state_mut(store).guest_task;
1436         log::trace!("resume_fiber: save current task {old_task:?}");
1437 
1438         let fiber = fiber::resolve_or_release(store, fiber).await?;
1439 
1440         let state = self.concurrent_state_mut(store);
1441 
1442         state.guest_task = old_task;
1443         log::trace!("resume_fiber: restore current task {old_task:?}");
1444 
1445         if let Some(mut fiber) = fiber {
1446             // See the `SuspendReason` documentation for what each case means.
1447             match state.suspend_reason.take().unwrap() {
1448                 SuspendReason::NeedWork => {
1449                     if state.worker.is_none() {
1450                         state.worker = Some(fiber);
1451                     } else {
1452                         fiber.dispose(store);
1453                     }
1454                 }
1455                 SuspendReason::Yielding { .. } => {
1456                     state.push_low_priority(WorkItem::ResumeFiber(fiber));
1457                 }
1458                 SuspendReason::Waiting { set, task } => {
1459                     let old = state
1460                         .get_mut(set)?
1461                         .waiting
1462                         .insert(task, WaitMode::Fiber(fiber));
1463                     assert!(old.is_none());
1464                 }
1465             }
1466         }
1467 
1468         Ok(())
1469     }
1470 
1471     /// Execute the specified guest call on a worker fiber.
1472     async fn run_on_worker<T: Send>(
1473         self,
1474         store: StoreContextMut<'_, T>,
1475         item: WorkerItem,
1476     ) -> Result<()> {
1477         let worker = if let Some(fiber) = self.concurrent_state_mut(store.0).worker.take() {
1478             fiber
1479         } else {
1480             fiber::make_fiber(store.0, move |store| {
1481                 loop {
1482                     match self.concurrent_state_mut(store).worker_item.take().unwrap() {
1483                         WorkerItem::GuestCall(call) => self.handle_guest_call(store, call)?,
1484                         WorkerItem::Function(fun) => fun.into_inner()(store, self)?,
1485                     }
1486 
1487                     self.suspend(store, SuspendReason::NeedWork)?;
1488                 }
1489             })?
1490         };
1491 
1492         let worker_item = &mut self.concurrent_state_mut(store.0).worker_item;
1493         assert!(worker_item.is_none());
1494         *worker_item = Some(item);
1495 
1496         self.resume_fiber(store.0, worker).await
1497     }
1498 
1499     /// Execute the specified guest call.
1500     fn handle_guest_call(self, store: &mut dyn VMStore, call: GuestCall) -> Result<()> {
1501         match call.kind {
1502             GuestCallKind::DeliverEvent { set } => {
1503                 let (event, waitable) = self
1504                     .id()
1505                     .get_mut(store)
1506                     .get_event(call.task, set, true)?
1507                     .unwrap();
1508                 let state = self.concurrent_state_mut(store);
1509                 let task = state.get_mut(call.task)?;
1510                 let runtime_instance = task.instance;
1511                 let handle = waitable.map(|(_, v)| v).unwrap_or(0);
1512 
1513                 log::trace!(
1514                     "use callback to deliver event {event:?} to {:?} for {waitable:?}",
1515                     call.task,
1516                 );
1517 
1518                 let old_task = state.guest_task.replace(call.task);
1519                 log::trace!(
1520                     "GuestCallKind::DeliverEvent: replaced {old_task:?} with {:?} as current task",
1521                     call.task
1522                 );
1523 
1524                 self.maybe_push_call_context(store.store_opaque_mut(), call.task)?;
1525 
1526                 let state = self.concurrent_state_mut(store);
1527                 state.enter_instance(runtime_instance);
1528 
1529                 let callback = state.get_mut(call.task)?.callback.take().unwrap();
1530 
1531                 let code = callback(store, self, runtime_instance, event, handle)?;
1532 
1533                 let state = self.concurrent_state_mut(store);
1534 
1535                 state.get_mut(call.task)?.callback = Some(callback);
1536 
1537                 state.exit_instance(runtime_instance)?;
1538 
1539                 self.maybe_pop_call_context(store.store_opaque_mut(), call.task)?;
1540 
1541                 self.id().get_mut(store).handle_callback_code(
1542                     call.task,
1543                     runtime_instance,
1544                     code,
1545                     false,
1546                 )?;
1547 
1548                 self.concurrent_state_mut(store).guest_task = old_task;
1549                 log::trace!("GuestCallKind::DeliverEvent: restored {old_task:?} as current task");
1550             }
1551             GuestCallKind::Start(fun) => {
1552                 fun(store, self)?;
1553             }
1554         }
1555 
1556         Ok(())
1557     }
1558 
1559     /// Suspend the current fiber, storing the reason in
1560     /// `ConcurrentState::suspend_reason` to indicate the conditions under which
1561     /// it should be resumed.
1562     ///
1563     /// See the `SuspendReason` documentation for details.
1564     fn suspend(self, store: &mut dyn VMStore, reason: SuspendReason) -> Result<()> {
1565         log::trace!("suspend fiber: {reason:?}");
1566 
1567         // If we're yielding or waiting on behalf of a guest task, we'll need to
1568         // pop the call context which manages resource borrows before suspending
1569         // and then push it again once we've resumed.
1570         let task = match &reason {
1571             SuspendReason::Yielding { task } | SuspendReason::Waiting { task, .. } => Some(*task),
1572             SuspendReason::NeedWork => None,
1573         };
1574 
1575         let old_guest_task = if let Some(task) = task {
1576             self.maybe_pop_call_context(store, task)?;
1577             self.concurrent_state_mut(store).guest_task
1578         } else {
1579             None
1580         };
1581 
1582         let suspend_reason = &mut self.concurrent_state_mut(store).suspend_reason;
1583         assert!(suspend_reason.is_none());
1584         *suspend_reason = Some(reason);
1585 
1586         store.with_blocking(|_, cx| cx.suspend(StoreFiberYield::ReleaseStore))?;
1587 
1588         if let Some(task) = task {
1589             self.concurrent_state_mut(store).guest_task = old_guest_task;
1590             self.maybe_push_call_context(store, task)?;
1591         }
1592 
1593         Ok(())
1594     }
1595 
1596     /// Push the call context for managing resource borrows for the specified
1597     /// guest task if it has not yet either returned a result or cancelled
1598     /// itself.
1599     fn maybe_push_call_context(
1600         self,
1601         store: &mut StoreOpaque,
1602         guest_task: TableId<GuestTask>,
1603     ) -> Result<()> {
1604         let task = self.concurrent_state_mut(store).get_mut(guest_task)?;
1605         if task.lift_result.is_some() {
1606             log::trace!("push call context for {guest_task:?}");
1607             let call_context = task.call_context.take().unwrap();
1608             store.component_resource_state().0.push(call_context);
1609         }
1610         Ok(())
1611     }
1612 
1613     /// Pop the call context for managing resource borrows for the specified
1614     /// guest task if it has not yet either returned a result or cancelled
1615     /// itself.
1616     fn maybe_pop_call_context(
1617         self,
1618         store: &mut StoreOpaque,
1619         guest_task: TableId<GuestTask>,
1620     ) -> Result<()> {
1621         if self
1622             .concurrent_state_mut(store)
1623             .get_mut(guest_task)?
1624             .lift_result
1625             .is_some()
1626         {
1627             log::trace!("pop call context for {guest_task:?}");
1628             let call_context = Some(store.component_resource_state().0.pop().unwrap());
1629             self.concurrent_state_mut(store)
1630                 .get_mut(guest_task)?
1631                 .call_context = call_context;
1632         }
1633         Ok(())
1634     }
1635 
1636     /// Add the specified guest call to the "high priority" work item queue, to
1637     /// be started as soon as backpressure and/or reentrance rules allow.
1638     ///
1639     /// SAFETY: The raw pointer arguments must be valid references to guest
1640     /// functions (with the appropriate signatures) when the closures queued by
1641     /// this function are called.
1642     unsafe fn queue_call<T: 'static>(
1643         self,
1644         mut store: StoreContextMut<T>,
1645         guest_task: TableId<GuestTask>,
1646         callee: SendSyncPtr<VMFuncRef>,
1647         param_count: usize,
1648         result_count: usize,
1649         flags: Option<InstanceFlags>,
1650         async_: bool,
1651         callback: Option<SendSyncPtr<VMFuncRef>>,
1652         post_return: Option<SendSyncPtr<VMFuncRef>>,
1653     ) -> Result<()> {
1654         /// Return a closure which will call the specified function in the scope
1655         /// of the specified task.
1656         ///
1657         /// This will use `GuestTask::lower_params` to lower the parameters, but
1658         /// will not lift the result; instead, it returns a
1659         /// `[MaybeUninit<ValRaw>; MAX_FLAT_PARAMS]` from which the result, if
1660         /// any, may be lifted.  Note that an async-lifted export will have
1661         /// returned its result using the `task.return` intrinsic (or not
1662         /// returned a result at all, in the case of `task.cancel`), in which
1663         /// case the "result" of this call will either be a callback code or
1664         /// nothing.
1665         ///
1666         /// SAFETY: `callee` must be a valid `*mut VMFuncRef` at the time when
1667         /// the returned closure is called.
1668         unsafe fn make_call<T: 'static>(
1669             store: StoreContextMut<T>,
1670             guest_task: TableId<GuestTask>,
1671             callee: SendSyncPtr<VMFuncRef>,
1672             param_count: usize,
1673             result_count: usize,
1674             flags: Option<InstanceFlags>,
1675         ) -> impl FnOnce(
1676             &mut dyn VMStore,
1677             Instance,
1678         ) -> Result<[MaybeUninit<ValRaw>; MAX_FLAT_PARAMS]>
1679         + Send
1680         + Sync
1681         + 'static
1682         + use<T> {
1683             let token = StoreToken::new(store);
1684             move |store: &mut dyn VMStore, instance: Instance| {
1685                 let mut storage = [MaybeUninit::uninit(); MAX_FLAT_PARAMS];
1686                 let task = instance.concurrent_state_mut(store).get_mut(guest_task)?;
1687                 let may_enter_after_call = task.call_post_return_automatically();
1688                 let lower = task.lower_params.take().unwrap();
1689 
1690                 lower(store, instance, &mut storage[..param_count])?;
1691 
1692                 let mut store = token.as_context_mut(store);
1693 
1694                 // SAFETY: Per the contract documented in `make_call's`
1695                 // documentation, `callee` must be a valid pointer.
1696                 unsafe {
1697                     if let Some(mut flags) = flags {
1698                         flags.set_may_enter(false);
1699                     }
1700                     crate::Func::call_unchecked_raw(
1701                         &mut store,
1702                         callee.as_non_null(),
1703                         NonNull::new(
1704                             &mut storage[..param_count.max(result_count)]
1705                                 as *mut [MaybeUninit<ValRaw>] as _,
1706                         )
1707                         .unwrap(),
1708                     )?;
1709                     if let Some(mut flags) = flags {
1710                         flags.set_may_enter(may_enter_after_call);
1711                     }
1712                 }
1713 
1714                 Ok(storage)
1715             }
1716         }
1717 
1718         // SAFETY: Per the contract described in this function documentation,
1719         // the `callee` pointer which `call` closes over must be valid when
1720         // called by the closure we queue below.
1721         let call = unsafe {
1722             make_call(
1723                 store.as_context_mut(),
1724                 guest_task,
1725                 callee,
1726                 param_count,
1727                 result_count,
1728                 flags,
1729             )
1730         };
1731 
1732         let callee_instance = self
1733             .concurrent_state_mut(store.0)
1734             .get_mut(guest_task)?
1735             .instance;
1736         let fun = if callback.is_some() {
1737             assert!(async_);
1738 
1739             Box::new(move |store: &mut dyn VMStore, instance: Instance| {
1740                 let old_task = instance
1741                     .concurrent_state_mut(store)
1742                     .guest_task
1743                     .replace(guest_task);
1744                 log::trace!(
1745                     "stackless call: replaced {old_task:?} with {guest_task:?} as current task"
1746                 );
1747 
1748                 instance.maybe_push_call_context(store.store_opaque_mut(), guest_task)?;
1749 
1750                 instance
1751                     .concurrent_state_mut(store)
1752                     .enter_instance(callee_instance);
1753 
1754                 // SAFETY: See the documentation for `make_call` to review the
1755                 // contract we must uphold for `call` here.
1756                 //
1757                 // Per the contract described in the `queue_call`
1758                 // documentation, the `callee` pointer which `call` closes
1759                 // over must be valid.
1760                 let storage = call(store, instance)?;
1761 
1762                 instance
1763                     .concurrent_state_mut(store)
1764                     .exit_instance(callee_instance)?;
1765 
1766                 instance.maybe_pop_call_context(store.store_opaque_mut(), guest_task)?;
1767 
1768                 let state = instance.concurrent_state_mut(store);
1769                 state.guest_task = old_task;
1770                 log::trace!("stackless call: restored {old_task:?} as current task");
1771 
1772                 // SAFETY: `wasmparser` will have validated that the callback
1773                 // function returns a `i32` result.
1774                 let code = unsafe { storage[0].assume_init() }.get_i32() as u32;
1775 
1776                 instance.id().get_mut(store).handle_callback_code(
1777                     guest_task,
1778                     callee_instance,
1779                     code,
1780                     true,
1781                 )?;
1782 
1783                 Ok(())
1784             })
1785                 as Box<dyn FnOnce(&mut dyn VMStore, Instance) -> Result<()> + Send + Sync>
1786         } else {
1787             let token = StoreToken::new(store.as_context_mut());
1788             Box::new(move |store: &mut dyn VMStore, instance: Instance| {
1789                 let old_task = instance
1790                     .concurrent_state_mut(store)
1791                     .guest_task
1792                     .replace(guest_task);
1793                 log::trace!(
1794                     "stackful call: replaced {old_task:?} with {guest_task:?} as current task",
1795                 );
1796 
1797                 let mut flags = instance.id().get(store).instance_flags(callee_instance);
1798 
1799                 instance.maybe_push_call_context(store.store_opaque_mut(), guest_task)?;
1800 
1801                 // Unless this is a callback-less (i.e. stackful)
1802                 // async-lifted export, we need to record that the instance
1803                 // cannot be entered until the call returns.
1804                 if !async_ {
1805                     instance
1806                         .concurrent_state_mut(store)
1807                         .enter_instance(callee_instance);
1808                 }
1809 
1810                 // SAFETY: See the documentation for `make_call` to review the
1811                 // contract we must uphold for `call` here.
1812                 //
1813                 // Per the contract described in the `queue_call`
1814                 // documentation, the `callee` pointer which `call` closes
1815                 // over must be valid.
1816                 let storage = call(store, instance)?;
1817 
1818                 if async_ {
1819                     // This is a callback-less (i.e. stackful) async-lifted
1820                     // export, so there is no post-return function, and
1821                     // either `task.return` or `task.cancel` should have
1822                     // been called.
1823                     if instance
1824                         .concurrent_state_mut(store)
1825                         .get_mut(guest_task)?
1826                         .lift_result
1827                         .is_some()
1828                     {
1829                         return Err(anyhow!(crate::Trap::NoAsyncResult));
1830                     }
1831                 } else {
1832                     // This is a sync-lifted export, so now is when we lift the
1833                     // result, optionally call the post-return function, if any,
1834                     // and finally notify any current or future waiters that the
1835                     // subtask has returned.
1836 
1837                     let lift = {
1838                         let state = instance.concurrent_state_mut(store);
1839                         state.exit_instance(callee_instance)?;
1840 
1841                         assert!(state.get_mut(guest_task)?.result.is_none());
1842 
1843                         state.get_mut(guest_task)?.lift_result.take().unwrap()
1844                     };
1845 
1846                     // SAFETY: `result_count` represents the number of core Wasm
1847                     // results returned, per `wasmparser`.
1848                     let result = (lift.lift)(store, instance, unsafe {
1849                         mem::transmute::<&[MaybeUninit<ValRaw>], &[ValRaw]>(
1850                             &storage[..result_count],
1851                         )
1852                     })?;
1853 
1854                     let post_return_arg = match result_count {
1855                         0 => ValRaw::i32(0),
1856                         // SAFETY: `result_count` represents the number of
1857                         // core Wasm results returned, per `wasmparser`.
1858                         1 => unsafe { storage[0].assume_init() },
1859                         _ => unreachable!(),
1860                     };
1861 
1862                     if instance
1863                         .concurrent_state_mut(store)
1864                         .get_mut(guest_task)?
1865                         .call_post_return_automatically()
1866                     {
1867                         unsafe {
1868                             flags.set_may_leave(false);
1869                             flags.set_needs_post_return(false);
1870                         }
1871 
1872                         if let Some(func) = post_return {
1873                             let mut store = token.as_context_mut(store);
1874 
1875                             // SAFETY: `func` is a valid `*mut VMFuncRef` from
1876                             // either `wasmtime-cranelift`-generated fused adapter
1877                             // code or `component::Options`.  Per `wasmparser`
1878                             // post-return signature validation, we know it takes a
1879                             // single parameter.
1880                             unsafe {
1881                                 crate::Func::call_unchecked_raw(
1882                                     &mut store,
1883                                     func.as_non_null(),
1884                                     slice::from_ref(&post_return_arg).into(),
1885                                 )?;
1886                             }
1887                         }
1888 
1889                         unsafe {
1890                             flags.set_may_leave(true);
1891                             flags.set_may_enter(true);
1892                         }
1893                     }
1894 
1895                     instance.task_complete(
1896                         store,
1897                         guest_task,
1898                         result,
1899                         Status::Returned,
1900                         post_return_arg,
1901                     )?;
1902                 }
1903 
1904                 instance.maybe_pop_call_context(store.store_opaque_mut(), guest_task)?;
1905 
1906                 let task = instance.concurrent_state_mut(store).get_mut(guest_task)?;
1907 
1908                 match &task.caller {
1909                     Caller::Host {
1910                         remove_task_automatically,
1911                         ..
1912                     } => {
1913                         if *remove_task_automatically {
1914                             Waitable::Guest(guest_task)
1915                                 .delete_from(instance.concurrent_state_mut(store))?;
1916                         }
1917                     }
1918                     Caller::Guest { .. } => {
1919                         task.exited = true;
1920                     }
1921                 }
1922 
1923                 Ok(())
1924             })
1925         };
1926 
1927         self.concurrent_state_mut(store.0)
1928             .push_high_priority(WorkItem::GuestCall(GuestCall {
1929                 task: guest_task,
1930                 kind: GuestCallKind::Start(fun),
1931             }));
1932 
1933         Ok(())
1934     }
1935 
1936     /// Prepare (but do not start) a guest->guest call.
1937     ///
1938     /// This is called from fused adapter code generated in
1939     /// `wasmtime_environ::fact::trampoline::Compiler`.  `start` and `return_`
1940     /// are synthesized Wasm functions which move the parameters from the caller
1941     /// to the callee and the result from the callee to the caller,
1942     /// respectively.  The adapter will call `Self::start_call` immediately
1943     /// after calling this function.
1944     ///
1945     /// SAFETY: All the pointer arguments must be valid pointers to guest
1946     /// entities (and with the expected signatures for the function references
1947     /// -- see `wasmtime_environ::fact::trampoline::Compiler` for details).
1948     unsafe fn prepare_call<T: 'static>(
1949         self,
1950         mut store: StoreContextMut<T>,
1951         start: *mut VMFuncRef,
1952         return_: *mut VMFuncRef,
1953         caller_instance: RuntimeComponentInstanceIndex,
1954         callee_instance: RuntimeComponentInstanceIndex,
1955         task_return_type: TypeTupleIndex,
1956         memory: *mut VMMemoryDefinition,
1957         string_encoding: u8,
1958         caller_info: CallerInfo,
1959     ) -> Result<()> {
1960         self.id().get(store.0).check_may_leave(caller_instance)?;
1961 
1962         enum ResultInfo {
1963             Heap { results: u32 },
1964             Stack { result_count: u32 },
1965         }
1966 
1967         let result_info = match &caller_info {
1968             CallerInfo::Async {
1969                 has_result: true,
1970                 params,
1971             } => ResultInfo::Heap {
1972                 results: params.last().unwrap().get_u32(),
1973             },
1974             CallerInfo::Async {
1975                 has_result: false, ..
1976             } => ResultInfo::Stack { result_count: 0 },
1977             CallerInfo::Sync {
1978                 result_count,
1979                 params,
1980             } if *result_count > u32::try_from(MAX_FLAT_RESULTS).unwrap() => ResultInfo::Heap {
1981                 results: params.last().unwrap().get_u32(),
1982             },
1983             CallerInfo::Sync { result_count, .. } => ResultInfo::Stack {
1984                 result_count: *result_count,
1985             },
1986         };
1987 
1988         let sync_caller = matches!(caller_info, CallerInfo::Sync { .. });
1989 
1990         // Create a new guest task for the call, closing over the `start` and
1991         // `return_` functions to lift the parameters and lower the result,
1992         // respectively.
1993         let start = SendSyncPtr::new(NonNull::new(start).unwrap());
1994         let return_ = SendSyncPtr::new(NonNull::new(return_).unwrap());
1995         let token = StoreToken::new(store.as_context_mut());
1996         let state = self.concurrent_state_mut(store.0);
1997         let old_task = state.guest_task.take();
1998         let new_task = GuestTask::new(
1999             state,
2000             Box::new(move |store, instance, dst| {
2001                 let mut store = token.as_context_mut(store);
2002                 assert!(dst.len() <= MAX_FLAT_PARAMS);
2003                 let mut src = [MaybeUninit::uninit(); MAX_FLAT_PARAMS];
2004                 let count = match caller_info {
2005                     // Async callers, if they have a result, use the last
2006                     // parameter as a return pointer so chop that off if
2007                     // relevant here.
2008                     CallerInfo::Async { params, has_result } => {
2009                         let params = &params[..params.len() - usize::from(has_result)];
2010                         for (param, src) in params.iter().zip(&mut src) {
2011                             src.write(*param);
2012                         }
2013                         params.len()
2014                     }
2015 
2016                     // Sync callers forward everything directly.
2017                     CallerInfo::Sync { params, .. } => {
2018                         for (param, src) in params.iter().zip(&mut src) {
2019                             src.write(*param);
2020                         }
2021                         params.len()
2022                     }
2023                 };
2024                 // SAFETY: `start` is a valid `*mut VMFuncRef` from
2025                 // `wasmtime-cranelift`-generated fused adapter code.  Based on
2026                 // how it was constructed (see
2027                 // `wasmtime_environ::fact::trampoline::Compiler::compile_async_start_adapter`
2028                 // for details) we know it takes count parameters and returns
2029                 // `dst.len()` results.
2030                 unsafe {
2031                     crate::Func::call_unchecked_raw(
2032                         &mut store,
2033                         start.as_non_null(),
2034                         NonNull::new(
2035                             &mut src[..count.max(dst.len())] as *mut [MaybeUninit<ValRaw>] as _,
2036                         )
2037                         .unwrap(),
2038                     )?;
2039                 }
2040                 dst.copy_from_slice(&src[..dst.len()]);
2041                 let state = instance.concurrent_state_mut(store.0);
2042                 let task = state.guest_task.unwrap();
2043                 Waitable::Guest(task).set_event(
2044                     state,
2045                     Some(Event::Subtask {
2046                         status: Status::Started,
2047                     }),
2048                 )?;
2049                 Ok(())
2050             }),
2051             LiftResult {
2052                 lift: Box::new(move |store, instance, src| {
2053                     // SAFETY: See comment in closure passed as `lower_params`
2054                     // parameter above.
2055                     let mut store = token.as_context_mut(store);
2056                     let mut my_src = src.to_owned(); // TODO: use stack to avoid allocation?
2057                     if let ResultInfo::Heap { results } = &result_info {
2058                         my_src.push(ValRaw::u32(*results));
2059                     }
2060                     // SAFETY: `return_` is a valid `*mut VMFuncRef` from
2061                     // `wasmtime-cranelift`-generated fused adapter code.  Based
2062                     // on how it was constructed (see
2063                     // `wasmtime_environ::fact::trampoline::Compiler::compile_async_return_adapter`
2064                     // for details) we know it takes `src.len()` parameters and
2065                     // returns up to 1 result.
2066                     unsafe {
2067                         crate::Func::call_unchecked_raw(
2068                             &mut store,
2069                             return_.as_non_null(),
2070                             my_src.as_mut_slice().into(),
2071                         )?;
2072                     }
2073                     let state = instance.concurrent_state_mut(store.0);
2074                     let task = state.guest_task.unwrap();
2075                     if sync_caller {
2076                         state.get_mut(task)?.sync_result =
2077                             Some(if let ResultInfo::Stack { result_count } = &result_info {
2078                                 match result_count {
2079                                     0 => None,
2080                                     1 => Some(my_src[0]),
2081                                     _ => unreachable!(),
2082                                 }
2083                             } else {
2084                                 None
2085                             });
2086                     }
2087                     Ok(Box::new(DummyResult) as Box<dyn Any + Send + Sync>)
2088                 }),
2089                 ty: task_return_type,
2090                 memory: NonNull::new(memory).map(SendSyncPtr::new),
2091                 string_encoding: StringEncoding::from_u8(string_encoding).unwrap(),
2092             },
2093             Caller::Guest {
2094                 task: old_task.unwrap(),
2095                 instance: caller_instance,
2096             },
2097             None,
2098             callee_instance,
2099         )?;
2100 
2101         let guest_task = state.push(new_task)?;
2102 
2103         if let Some(old_task) = old_task {
2104             if !state.may_enter(guest_task) {
2105                 bail!(crate::Trap::CannotEnterComponent);
2106             }
2107 
2108             state.get_mut(old_task)?.subtasks.insert(guest_task);
2109         };
2110 
2111         // Make the new task the current one so that `Self::start_call` knows
2112         // which one to start.
2113         state.guest_task = Some(guest_task);
2114         log::trace!("pushed {guest_task:?} as current task; old task was {old_task:?}");
2115 
2116         Ok(())
2117     }
2118 
2119     /// Call the specified callback function for an async-lifted export.
2120     ///
2121     /// SAFETY: `function` must be a valid reference to a guest function of the
2122     /// correct signature for a callback.
2123     unsafe fn call_callback<T>(
2124         self,
2125         mut store: StoreContextMut<T>,
2126         callee_instance: RuntimeComponentInstanceIndex,
2127         function: SendSyncPtr<VMFuncRef>,
2128         event: Event,
2129         handle: u32,
2130         may_enter_after_call: bool,
2131     ) -> Result<u32> {
2132         let mut flags = self.id().get(store.0).instance_flags(callee_instance);
2133 
2134         let (ordinal, result) = event.parts();
2135         let params = &mut [
2136             ValRaw::u32(ordinal),
2137             ValRaw::u32(handle),
2138             ValRaw::u32(result),
2139         ];
2140         // SAFETY: `func` is a valid `*mut VMFuncRef` from either
2141         // `wasmtime-cranelift`-generated fused adapter code or
2142         // `component::Options`.  Per `wasmparser` callback signature
2143         // validation, we know it takes three parameters and returns one.
2144         unsafe {
2145             flags.set_may_enter(false);
2146             crate::Func::call_unchecked_raw(
2147                 &mut store,
2148                 function.as_non_null(),
2149                 params.as_mut_slice().into(),
2150             )?;
2151             flags.set_may_enter(may_enter_after_call);
2152         }
2153         Ok(params[0].get_u32())
2154     }
2155 
2156     /// Start a guest->guest call previously prepared using
2157     /// `Self::prepare_call`.
2158     ///
2159     /// This is called from fused adapter code generated in
2160     /// `wasmtime_environ::fact::trampoline::Compiler`.  The adapter will call
2161     /// this function immediately after calling `Self::prepare_call`.
2162     ///
2163     /// SAFETY: The `*mut VMFuncRef` arguments must be valid pointers to guest
2164     /// functions with the appropriate signatures for the current guest task.
2165     /// If this is a call to an async-lowered import, the actual call may be
2166     /// deferred and run after this function returns, in which case the pointer
2167     /// arguments must also be valid when the call happens.
2168     unsafe fn start_call<T: 'static>(
2169         self,
2170         mut store: StoreContextMut<T>,
2171         callback: *mut VMFuncRef,
2172         post_return: *mut VMFuncRef,
2173         callee: *mut VMFuncRef,
2174         param_count: u32,
2175         result_count: u32,
2176         flags: u32,
2177         storage: Option<&mut [MaybeUninit<ValRaw>]>,
2178     ) -> Result<u32> {
2179         let token = StoreToken::new(store.as_context_mut());
2180         let async_caller = storage.is_none();
2181         let state = self.concurrent_state_mut(store.0);
2182         let guest_task = state.guest_task.unwrap();
2183         let may_enter_after_call = state.get_mut(guest_task)?.call_post_return_automatically();
2184         let callee = SendSyncPtr::new(NonNull::new(callee).unwrap());
2185         let param_count = usize::try_from(param_count).unwrap();
2186         assert!(param_count <= MAX_FLAT_PARAMS);
2187         let result_count = usize::try_from(result_count).unwrap();
2188         assert!(result_count <= MAX_FLAT_RESULTS);
2189 
2190         let task = state.get_mut(guest_task)?;
2191         if !callback.is_null() {
2192             // We're calling an async-lifted export with a callback, so store
2193             // the callback and related context as part of the task so we can
2194             // call it later when needed.
2195             let callback = SendSyncPtr::new(NonNull::new(callback).unwrap());
2196             task.callback = Some(Box::new(
2197                 move |store, instance, runtime_instance, event, handle| {
2198                     let store = token.as_context_mut(store);
2199                     unsafe {
2200                         instance.call_callback::<T>(
2201                             store,
2202                             runtime_instance,
2203                             callback,
2204                             event,
2205                             handle,
2206                             may_enter_after_call,
2207                         )
2208                     }
2209                 },
2210             ));
2211         }
2212 
2213         let Caller::Guest {
2214             task: caller,
2215             instance: runtime_instance,
2216         } = &task.caller
2217         else {
2218             // As of this writing, `start_call` is only used for guest->guest
2219             // calls.
2220             unreachable!()
2221         };
2222         let caller = *caller;
2223         let caller_instance = *runtime_instance;
2224 
2225         let callee_instance = task.instance;
2226 
2227         let instance_flags = if callback.is_null() {
2228             None
2229         } else {
2230             Some(self.id().get(store.0).instance_flags(callee_instance))
2231         };
2232 
2233         // Queue the call as a "high priority" work item.
2234         unsafe {
2235             self.queue_call(
2236                 store.as_context_mut(),
2237                 guest_task,
2238                 callee,
2239                 param_count,
2240                 result_count,
2241                 instance_flags,
2242                 (flags & START_FLAG_ASYNC_CALLEE) != 0,
2243                 NonNull::new(callback).map(SendSyncPtr::new),
2244                 NonNull::new(post_return).map(SendSyncPtr::new),
2245             )?;
2246         }
2247 
2248         let state = self.concurrent_state_mut(store.0);
2249 
2250         // Use the caller's `GuestTask::sync_call_set` to register interest in
2251         // the subtask...
2252         let guest_waitable = Waitable::Guest(guest_task);
2253         let old_set = guest_waitable.common(state)?.set;
2254         let set = state.get_mut(caller)?.sync_call_set;
2255         guest_waitable.join(state, Some(set))?;
2256 
2257         // ... and suspend this fiber temporarily while we wait for it to start.
2258         //
2259         // Note that we _could_ call the callee directly using the current fiber
2260         // rather than suspend this one, but that would make reasoning about the
2261         // event loop more complicated and is probably only worth doing if
2262         // there's a measurable performance benefit.  In addition, it would mean
2263         // blocking the caller if the callee calls a blocking sync-lowered
2264         // import, and as of this writing the spec says we must not do that.
2265         //
2266         // Alternatively, the fused adapter code could be modified to call the
2267         // callee directly without calling a host-provided intrinsic at all (in
2268         // which case it would need to do its own, inline backpressure checks,
2269         // etc.).  Again, we'd want to see a measurable performance benefit
2270         // before committing to such an optimization.  And again, we'd need to
2271         // update the spec to allow that.
2272         let (status, waitable) = loop {
2273             self.suspend(store.0, SuspendReason::Waiting { set, task: caller })?;
2274 
2275             let state = self.concurrent_state_mut(store.0);
2276 
2277             let event = guest_waitable.take_event(state)?;
2278             let Some(Event::Subtask { status }) = event else {
2279                 unreachable!();
2280             };
2281 
2282             log::trace!("status {status:?} for {guest_task:?}");
2283 
2284             if status == Status::Returned {
2285                 // It returned, so we can stop waiting.
2286                 break (status, None);
2287             } else if async_caller {
2288                 // It hasn't returned yet, but the caller is calling via an
2289                 // async-lowered import, so we generate a handle for the task
2290                 // waitable and return the status.
2291                 let handle = self.id().get_mut(store.0).guest_tables().0[caller_instance]
2292                     .subtask_insert_guest(guest_task.rep())?;
2293                 self.concurrent_state_mut(store.0)
2294                     .get_mut(guest_task)?
2295                     .common
2296                     .handle = Some(handle);
2297                 break (status, Some(handle));
2298             } else {
2299                 // The callee hasn't returned yet, and the caller is calling via
2300                 // a sync-lowered import, so we loop and keep waiting until the
2301                 // callee returns.
2302             }
2303         };
2304 
2305         let state = self.concurrent_state_mut(store.0);
2306 
2307         guest_waitable.join(state, old_set)?;
2308 
2309         if let Some(storage) = storage {
2310             // The caller used a sync-lowered import to call an async-lifted
2311             // export, in which case the result, if any, has been stashed in
2312             // `GuestTask::sync_result`.
2313             let task = state.get_mut(guest_task)?;
2314             if let Some(result) = task.sync_result.take() {
2315                 if let Some(result) = result {
2316                     storage[0] = MaybeUninit::new(result);
2317                 }
2318 
2319                 if task.exited {
2320                     Waitable::Guest(guest_task).delete_from(state)?;
2321                 }
2322             } else {
2323                 // This means the callee failed to call either `task.return` or
2324                 // `task.cancel` before exiting.
2325                 return Err(anyhow!(crate::Trap::NoAsyncResult));
2326             }
2327         }
2328 
2329         // Reset the current task to point to the caller as it resumes control.
2330         state.guest_task = Some(caller);
2331         log::trace!("popped current task {guest_task:?}; new task is {caller:?}");
2332 
2333         Ok(status.pack(waitable))
2334     }
2335 
2336     /// Wrap the specified host function in a future which will call it, passing
2337     /// it an `&Accessor<T>`.
2338     ///
2339     /// See the `Accessor` documentation for details.
2340     pub(crate) fn wrap_call<T, F, R>(
2341         self,
2342         store: StoreContextMut<T>,
2343         closure: F,
2344     ) -> impl Future<Output = Result<R>> + 'static
2345     where
2346         T: 'static,
2347         F: FnOnce(&Accessor<T>) -> Pin<Box<dyn Future<Output = Result<R>> + Send + '_>>
2348             + Send
2349             + Sync
2350             + 'static,
2351         R: Send + Sync + 'static,
2352     {
2353         let token = StoreToken::new(store);
2354         async move {
2355             let mut accessor = Accessor::new(token, Some(self));
2356             closure(&mut accessor).await
2357         }
2358     }
2359 
2360     /// Poll the specified future once on behalf of a guest->host call using an
2361     /// async-lowered import.
2362     ///
2363     /// If it returns `Ready`, return `Ok(None)`.  Otherwise, if it returns
2364     /// `Pending`, add it to the set of futures to be polled as part of this
2365     /// instance's event loop until it completes, and then return
2366     /// `Ok(Some(handle))` where `handle` is the waitable handle to return.
2367     ///
2368     /// Whether the future returns `Ready` immediately or later, the `lower`
2369     /// function will be used to lower the result, if any, into the guest caller's
2370     /// stack and linear memory unless the task has been cancelled.
2371     pub(crate) fn first_poll<T: 'static, R: Send + 'static>(
2372         self,
2373         mut store: StoreContextMut<T>,
2374         future: impl Future<Output = Result<R>> + Send + 'static,
2375         caller_instance: RuntimeComponentInstanceIndex,
2376         lower: impl FnOnce(StoreContextMut<T>, Instance, R) -> Result<()> + Send + 'static,
2377     ) -> Result<Option<u32>> {
2378         let token = StoreToken::new(store.as_context_mut());
2379         let state = self.concurrent_state_mut(store.0);
2380         let caller = state.guest_task.unwrap();
2381 
2382         // Create an abortable future which hooks calls to poll and manages call
2383         // context state for the future.
2384         let (join_handle, future) = JoinHandle::run(async move {
2385             let mut future = pin!(future);
2386             let mut call_context = None;
2387             future::poll_fn(move |cx| {
2388                 // Push the call context for managing any resource borrows
2389                 // for the task.
2390                 tls::get(|store| {
2391                     if let Some(call_context) = call_context.take() {
2392                         token
2393                             .as_context_mut(store)
2394                             .0
2395                             .component_resource_state()
2396                             .0
2397                             .push(call_context);
2398                     }
2399                 });
2400 
2401                 let result = future.as_mut().poll(cx);
2402 
2403                 if result.is_pending() {
2404                     // Pop the call context for managing any resource
2405                     // borrows for the task.
2406                     tls::get(|store| {
2407                         call_context = Some(
2408                             token
2409                                 .as_context_mut(store)
2410                                 .0
2411                                 .component_resource_state()
2412                                 .0
2413                                 .pop()
2414                                 .unwrap(),
2415                         );
2416                     });
2417                 }
2418                 result
2419             })
2420             .await
2421         });
2422 
2423         // We create a new host task even though it might complete immediately
2424         // (in which case we won't need to pass a waitable back to the guest).
2425         // If it does complete immediately, we'll remove it before we return.
2426         let task = state.push(HostTask::new(caller_instance, Some(join_handle)))?;
2427 
2428         log::trace!("new host task child of {caller:?}: {task:?}");
2429 
2430         let mut future = Box::pin(future);
2431 
2432         // Finally, poll the future.  We can use a dummy `Waker` here because
2433         // we'll add the future to `ConcurrentState::futures` and poll it
2434         // automatically from the event loop if it doesn't complete immediately
2435         // here.
2436         let poll = self.set_tls(store.0, || {
2437             future
2438                 .as_mut()
2439                 .poll(&mut Context::from_waker(&Waker::noop()))
2440         });
2441 
2442         Ok(match poll {
2443             Poll::Ready(None) => unreachable!(),
2444             Poll::Ready(Some(result)) => {
2445                 // It finished immediately; lower the result and delete the
2446                 // task.
2447                 lower(store.as_context_mut(), self, result?)?;
2448                 log::trace!("delete host task {task:?} (already ready)");
2449                 self.concurrent_state_mut(store.0).delete(task)?;
2450                 None
2451             }
2452             Poll::Pending => {
2453                 // It hasn't finished yet; add the future to
2454                 // `ConcurrentState::futures` so it will be polled by the event
2455                 // loop and allocate a waitable handle to return to the guest.
2456 
2457                 // Wrap the future in a closure responsible for lowering the result into
2458                 // the guest's stack and memory, as well as notifying any waiters that
2459                 // the task returned.
2460                 let future = Box::pin(async move {
2461                     let result = match future.await {
2462                         Some(result) => result?,
2463                         // Task was cancelled; nothing left to do.
2464                         None => return Ok(()),
2465                     };
2466                     tls::get(move |store| {
2467                         // Here we schedule a task to run on a worker fiber to do
2468                         // the lowering since it may involve a call to the guest's
2469                         // realloc function.  This is necessary because calling the
2470                         // guest while there are host embedder frames on the stack
2471                         // is unsound.
2472                         self.concurrent_state_mut(store).push_high_priority(
2473                             WorkItem::WorkerFunction(AlwaysMut::new(Box::new(move |store, _| {
2474                                 lower(token.as_context_mut(store), self, result)?;
2475                                 let state = self.concurrent_state_mut(store);
2476                                 state.get_mut(task)?.join_handle.take();
2477                                 Waitable::Host(task).set_event(
2478                                     state,
2479                                     Some(Event::Subtask {
2480                                         status: Status::Returned,
2481                                     }),
2482                                 )
2483                             }))),
2484                         );
2485                         Ok(())
2486                     })
2487                 });
2488 
2489                 self.concurrent_state_mut(store.0).push_future(future);
2490                 let handle = self.id().get_mut(store.0).guest_tables().0[caller_instance]
2491                     .subtask_insert_host(task.rep())?;
2492                 self.concurrent_state_mut(store.0)
2493                     .get_mut(task)?
2494                     .common
2495                     .handle = Some(handle);
2496                 log::trace!(
2497                     "assign {task:?} handle {handle} for {caller:?} instance {caller_instance:?}"
2498                 );
2499                 Some(handle)
2500             }
2501         })
2502     }
2503 
2504     /// Poll the specified future until it completes on behalf of a guest->host
2505     /// call using a sync-lowered import.
2506     ///
2507     /// This is similar to `Self::first_poll` except it's for sync-lowered
2508     /// imports, meaning we don't need to handle cancellation and we can block
2509     /// the caller until the task completes, at which point the caller can
2510     /// handle lowering the result to the guest's stack and linear memory.
2511     pub(crate) fn poll_and_block<R: Send + Sync + 'static>(
2512         self,
2513         store: &mut dyn VMStore,
2514         future: impl Future<Output = Result<R>> + Send + 'static,
2515         caller_instance: RuntimeComponentInstanceIndex,
2516     ) -> Result<R> {
2517         let state = self.concurrent_state_mut(store);
2518 
2519         // If there is no current guest task set, that means the host function
2520         // was registered using e.g. `LinkerInstance::func_wrap`, in which case
2521         // it should complete immediately.
2522         let Some(caller) = state.guest_task else {
2523             return match pin!(future).poll(&mut Context::from_waker(&Waker::noop())) {
2524                 Poll::Ready(result) => result,
2525                 Poll::Pending => {
2526                     unreachable!()
2527                 }
2528             };
2529         };
2530 
2531         // Save any existing result stashed in `GuestTask::result` so we can
2532         // replace it with the new result.
2533         let old_result = state
2534             .get_mut(caller)
2535             .with_context(|| format!("bad handle: {caller:?}"))?
2536             .result
2537             .take();
2538 
2539         // Add a temporary host task into the table so we can track its
2540         // progress.  Note that we'll never allocate a waitable handle for the
2541         // guest since we're being called synchronously.
2542         let task = state.push(HostTask::new(caller_instance, None))?;
2543 
2544         log::trace!("new host task child of {caller:?}: {task:?}");
2545 
2546         // Wrap the future in a closure which will take care of stashing the
2547         // result in `GuestTask::result` and resuming this fiber when the host
2548         // task completes.
2549         let mut future = Box::pin(async move {
2550             let result = future.await?;
2551             tls::get(move |store| {
2552                 let state = self.concurrent_state_mut(store);
2553                 state.get_mut(caller)?.result = Some(Box::new(result) as _);
2554 
2555                 Waitable::Host(task).set_event(
2556                     state,
2557                     Some(Event::Subtask {
2558                         status: Status::Returned,
2559                     }),
2560                 )?;
2561 
2562                 Ok(())
2563             })
2564         }) as HostTaskFuture;
2565 
2566         // Finally, poll the future.  We can use a dummy `Waker` here because
2567         // we'll add the future to `ConcurrentState::futures` and poll it
2568         // automatically from the event loop if it doesn't complete immediately
2569         // here.
2570         let poll = self.set_tls(store, || {
2571             future
2572                 .as_mut()
2573                 .poll(&mut Context::from_waker(&Waker::noop()))
2574         });
2575 
2576         match poll {
2577             Poll::Ready(result) => {
2578                 // It completed immediately; check the result and delete the task.
2579                 result?;
2580                 log::trace!("delete host task {task:?} (already ready)");
2581                 self.concurrent_state_mut(store).delete(task)?;
2582             }
2583             Poll::Pending => {
2584                 // It did not complete immediately; add it to
2585                 // `ConcurrentState::futures` so it will be polled via the event
2586                 // loop; then use `GuestTask::sync_call_set` to wait for the
2587                 // task to complete, suspending the current fiber until it does
2588                 // so.
2589                 let state = self.concurrent_state_mut(store);
2590                 state.push_future(future);
2591 
2592                 let set = state.get_mut(caller)?.sync_call_set;
2593                 Waitable::Host(task).join(state, Some(set))?;
2594 
2595                 self.suspend(store, SuspendReason::Waiting { set, task: caller })?;
2596             }
2597         }
2598 
2599         // Retrieve and return the result.
2600         Ok(*mem::replace(
2601             &mut self.concurrent_state_mut(store).get_mut(caller)?.result,
2602             old_result,
2603         )
2604         .unwrap()
2605         .downcast()
2606         .unwrap())
2607     }
2608 
2609     /// Implements the `task.return` intrinsic, lifting the result for the
2610     /// current guest task.
2611     pub(crate) fn task_return(
2612         self,
2613         store: &mut dyn VMStore,
2614         caller: RuntimeComponentInstanceIndex,
2615         ty: TypeTupleIndex,
2616         options: OptionsIndex,
2617         storage: &[ValRaw],
2618     ) -> Result<()> {
2619         self.id().get(store).check_may_leave(caller)?;
2620         let state = self.concurrent_state_mut(store);
2621         let CanonicalOptions {
2622             string_encoding,
2623             data_model,
2624             ..
2625         } = *state.options(options);
2626         let guest_task = state.guest_task.unwrap();
2627         let lift = state
2628             .get_mut(guest_task)?
2629             .lift_result
2630             .take()
2631             .ok_or_else(|| {
2632                 anyhow!("`task.return` or `task.cancel` called more than once for current task")
2633             })?;
2634         assert!(state.get_mut(guest_task)?.result.is_none());
2635 
2636         let invalid = ty != lift.ty
2637             || string_encoding != lift.string_encoding
2638             || match data_model {
2639                 CanonicalOptionsDataModel::LinearMemory(opts) => match opts.memory {
2640                     Some(memory) => {
2641                         let expected = lift.memory.map(|v| v.as_ptr()).unwrap_or(ptr::null_mut());
2642                         let actual = self.id().get(store).runtime_memory(memory);
2643                         expected != actual
2644                     }
2645                     // Memory not specified, meaning it didn't need to be
2646                     // specified per validation, so not invalid.
2647                     None => false,
2648                 },
2649                 // Always invalid as this isn't supported.
2650                 CanonicalOptionsDataModel::Gc { .. } => true,
2651             };
2652 
2653         if invalid {
2654             bail!("invalid `task.return` signature and/or options for current task");
2655         }
2656 
2657         log::trace!("task.return for {guest_task:?}");
2658 
2659         let result = (lift.lift)(store, self, storage)?;
2660 
2661         self.task_complete(store, guest_task, result, Status::Returned, ValRaw::i32(0))
2662     }
2663 
2664     /// Implements the `task.cancel` intrinsic.
2665     pub(crate) fn task_cancel(
2666         self,
2667         store: &mut dyn VMStore,
2668         caller: RuntimeComponentInstanceIndex,
2669     ) -> Result<()> {
2670         self.id().get(store).check_may_leave(caller)?;
2671         let state = self.concurrent_state_mut(store);
2672         let guest_task = state.guest_task.unwrap();
2673         let task = state.get_mut(guest_task)?;
2674         if !task.cancel_sent {
2675             bail!("`task.cancel` called by task which has not been cancelled")
2676         }
2677         _ = task.lift_result.take().ok_or_else(|| {
2678             anyhow!("`task.return` or `task.cancel` called more than once for current task")
2679         })?;
2680 
2681         assert!(task.result.is_none());
2682 
2683         log::trace!("task.cancel for {guest_task:?}");
2684 
2685         self.task_complete(
2686             store,
2687             guest_task,
2688             Box::new(DummyResult),
2689             Status::ReturnCancelled,
2690             ValRaw::i32(0),
2691         )
2692     }
2693 
2694     /// Complete the specified guest task (i.e. indicate that it has either
2695     /// returned a (possibly empty) result or cancelled itself).
2696     ///
2697     /// This will return any resource borrows and notify any current or future
2698     /// waiters that the task has completed.
2699     fn task_complete(
2700         self,
2701         store: &mut dyn VMStore,
2702         guest_task: TableId<GuestTask>,
2703         result: Box<dyn Any + Send + Sync>,
2704         status: Status,
2705         post_return_arg: ValRaw,
2706     ) -> Result<()> {
2707         if self
2708             .concurrent_state_mut(store)
2709             .get_mut(guest_task)?
2710             .call_post_return_automatically()
2711         {
2712             let (calls, host_table, _, instance) = store
2713                 .store_opaque_mut()
2714                 .component_resource_state_with_instance(self);
2715             ResourceTables {
2716                 calls,
2717                 host_table: Some(host_table),
2718                 guest: Some(instance.guest_tables()),
2719             }
2720             .exit_call()?;
2721         } else {
2722             // As of this writing, the only scenario where `call_post_return_automatically`
2723             // would be false for a `GuestTask` is for host-to-guest calls using
2724             // `[Typed]Func::call_async`, in which case the `function_index`
2725             // should be a non-`None` value.
2726             let function_index = self
2727                 .concurrent_state_mut(store)
2728                 .get_mut(guest_task)?
2729                 .function_index
2730                 .unwrap();
2731 
2732             self.id()
2733                 .get_mut(store)
2734                 .post_return_arg_set(function_index, post_return_arg);
2735         }
2736 
2737         let state = self.concurrent_state_mut(store);
2738         let task = state.get_mut(guest_task)?;
2739 
2740         if let Caller::Host { tx, .. } = &mut task.caller {
2741             if let Some(tx) = tx.take() {
2742                 _ = tx.send(result);
2743             }
2744         } else {
2745             task.result = Some(result);
2746             Waitable::Guest(guest_task).set_event(state, Some(Event::Subtask { status }))?;
2747         }
2748 
2749         Ok(())
2750     }
2751 
2752     /// Implements the `waitable-set.wait` intrinsic.
2753     pub(crate) fn waitable_set_wait(
2754         self,
2755         store: &mut dyn VMStore,
2756         caller: RuntimeComponentInstanceIndex,
2757         options: OptionsIndex,
2758         set: u32,
2759         payload: u32,
2760     ) -> Result<u32> {
2761         self.id().get(store).check_may_leave(caller)?;
2762         let opts = self.concurrent_state_mut(store).options(options);
2763         let cancellable = opts.cancellable;
2764         let caller_instance = opts.instance;
2765         let rep =
2766             self.id().get_mut(store).guest_tables().0[caller_instance].waitable_set_rep(set)?;
2767 
2768         self.waitable_check(
2769             store,
2770             cancellable,
2771             WaitableCheck::Wait(WaitableCheckParams {
2772                 set: TableId::new(rep),
2773                 options,
2774                 payload,
2775             }),
2776         )
2777     }
2778 
2779     /// Implements the `waitable-set.poll` intrinsic.
2780     pub(crate) fn waitable_set_poll(
2781         self,
2782         store: &mut dyn VMStore,
2783         caller: RuntimeComponentInstanceIndex,
2784         options: OptionsIndex,
2785         set: u32,
2786         payload: u32,
2787     ) -> Result<u32> {
2788         self.id().get(store).check_may_leave(caller)?;
2789         let opts = self.concurrent_state_mut(store).options(options);
2790         let cancellable = opts.cancellable;
2791         let caller_instance = opts.instance;
2792         let rep =
2793             self.id().get_mut(store).guest_tables().0[caller_instance].waitable_set_rep(set)?;
2794 
2795         self.waitable_check(
2796             store,
2797             cancellable,
2798             WaitableCheck::Poll(WaitableCheckParams {
2799                 set: TableId::new(rep),
2800                 options,
2801                 payload,
2802             }),
2803         )
2804     }
2805 
2806     /// Implements the `thread.yield` intrinsic.
2807     pub(crate) fn thread_yield(
2808         self,
2809         store: &mut dyn VMStore,
2810         caller: RuntimeComponentInstanceIndex,
2811         cancellable: bool,
2812     ) -> Result<bool> {
2813         self.id().get(store).check_may_leave(caller)?;
2814         self.waitable_check(store, cancellable, WaitableCheck::Yield)
2815             .map(|_| {
2816                 if cancellable {
2817                     let state = self.concurrent_state_mut(store);
2818                     let task = state.guest_task.unwrap();
2819                     if let Some(event) = state.get_mut(task).unwrap().event.take() {
2820                         assert!(matches!(event, Event::Cancelled));
2821                         true
2822                     } else {
2823                         false
2824                     }
2825                 } else {
2826                     false
2827                 }
2828             })
2829     }
2830 
2831     /// Helper function for the `waitable-set.wait`, `waitable-set.poll`, and
2832     /// `yield` intrinsics.
2833     fn waitable_check(
2834         self,
2835         store: &mut dyn VMStore,
2836         cancellable: bool,
2837         check: WaitableCheck,
2838     ) -> Result<u32> {
2839         let guest_task = self.concurrent_state_mut(store).guest_task.unwrap();
2840 
2841         let (wait, set) = match &check {
2842             WaitableCheck::Wait(params) => (true, Some(params.set)),
2843             WaitableCheck::Poll(params) => (false, Some(params.set)),
2844             WaitableCheck::Yield => (false, None),
2845         };
2846 
2847         // First, suspend this fiber, allowing any other tasks to run.
2848         self.suspend(store, SuspendReason::Yielding { task: guest_task })?;
2849 
2850         log::trace!("waitable check for {guest_task:?}; set {set:?}");
2851 
2852         let state = self.concurrent_state_mut(store);
2853         let task = state.get_mut(guest_task)?;
2854 
2855         if wait && task.callback.is_some() {
2856             bail!("cannot call `task.wait` from async-lifted export with callback");
2857         }
2858 
2859         // If we're waiting, and there are no events immediately available,
2860         // suspend the fiber until that changes.
2861         if wait {
2862             let set = set.unwrap();
2863 
2864             if (task.event.is_none()
2865                 || (matches!(task.event, Some(Event::Cancelled)) && !cancellable))
2866                 && state.get_mut(set)?.ready.is_empty()
2867             {
2868                 if cancellable {
2869                     let old = state.get_mut(guest_task)?.wake_on_cancel.replace(set);
2870                     assert!(old.is_none());
2871                 }
2872 
2873                 self.suspend(
2874                     store,
2875                     SuspendReason::Waiting {
2876                         set,
2877                         task: guest_task,
2878                     },
2879                 )?;
2880             }
2881         }
2882 
2883         log::trace!("waitable check for {guest_task:?}; set {set:?}, part two");
2884 
2885         let result = match check {
2886             // Deliver any pending events to the guest and return.
2887             WaitableCheck::Wait(params) | WaitableCheck::Poll(params) => {
2888                 let event = self.id().get_mut(store).get_event(
2889                     guest_task,
2890                     Some(params.set),
2891                     cancellable,
2892                 )?;
2893 
2894                 let (ordinal, handle, result) = if wait {
2895                     let (event, waitable) = event.unwrap();
2896                     let handle = waitable.map(|(_, v)| v).unwrap_or(0);
2897                     let (ordinal, result) = event.parts();
2898                     (ordinal, handle, result)
2899                 } else {
2900                     if let Some((event, waitable)) = event {
2901                         let handle = waitable.map(|(_, v)| v).unwrap_or(0);
2902                         let (ordinal, result) = event.parts();
2903                         (ordinal, handle, result)
2904                     } else {
2905                         log::trace!(
2906                             "no events ready to deliver via waitable-set.poll to {guest_task:?}; set {:?}",
2907                             params.set
2908                         );
2909                         let (ordinal, result) = Event::None.parts();
2910                         (ordinal, 0, result)
2911                     }
2912                 };
2913                 let store = store.store_opaque_mut();
2914                 let options = Options::new_index(store, self, params.options);
2915                 let ptr = func::validate_inbounds::<(u32, u32)>(
2916                     options.memory_mut(store),
2917                     &ValRaw::u32(params.payload),
2918                 )?;
2919                 options.memory_mut(store)[ptr + 0..][..4].copy_from_slice(&handle.to_le_bytes());
2920                 options.memory_mut(store)[ptr + 4..][..4].copy_from_slice(&result.to_le_bytes());
2921                 Ok(ordinal)
2922             }
2923             WaitableCheck::Yield => Ok(0),
2924         };
2925 
2926         result
2927     }
2928 
2929     /// Implements the `subtask.cancel` intrinsic.
2930     pub(crate) fn subtask_cancel(
2931         self,
2932         store: &mut dyn VMStore,
2933         caller_instance: RuntimeComponentInstanceIndex,
2934         async_: bool,
2935         task_id: u32,
2936     ) -> Result<u32> {
2937         self.id().get(store).check_may_leave(caller_instance)?;
2938         let (rep, is_host) =
2939             self.id().get_mut(store).guest_tables().0[caller_instance].subtask_rep(task_id)?;
2940         let (waitable, expected_caller_instance) = if is_host {
2941             let id = TableId::<HostTask>::new(rep);
2942             (
2943                 Waitable::Host(id),
2944                 self.concurrent_state_mut(store)
2945                     .get_mut(id)?
2946                     .caller_instance,
2947             )
2948         } else {
2949             let id = TableId::<GuestTask>::new(rep);
2950             if let Caller::Guest { instance, .. } =
2951                 &self.concurrent_state_mut(store).get_mut(id)?.caller
2952             {
2953                 (Waitable::Guest(id), *instance)
2954             } else {
2955                 unreachable!()
2956             }
2957         };
2958         // Since waitables can neither be passed between instances nor forged,
2959         // this should never fail unless there's a bug in Wasmtime, but we check
2960         // here to be sure:
2961         assert_eq!(expected_caller_instance, caller_instance);
2962 
2963         log::trace!("subtask_cancel {waitable:?} (handle {task_id})");
2964 
2965         let concurrent_state = self.concurrent_state_mut(store);
2966         if let Waitable::Host(host_task) = waitable {
2967             if let Some(handle) = concurrent_state.get_mut(host_task)?.join_handle.take() {
2968                 handle.abort();
2969                 return Ok(Status::ReturnCancelled as u32);
2970             }
2971         } else {
2972             let caller = concurrent_state.guest_task.unwrap();
2973             let guest_task = TableId::<GuestTask>::new(rep);
2974             let task = concurrent_state.get_mut(guest_task)?;
2975             if task.lower_params.is_some() {
2976                 task.lower_params = None;
2977                 task.lift_result = None;
2978 
2979                 // Not yet started; cancel and remove from pending
2980                 let callee_instance = task.instance;
2981 
2982                 let kind = concurrent_state
2983                     .instance_state(callee_instance)
2984                     .pending
2985                     .remove(&guest_task);
2986 
2987                 if kind.is_none() {
2988                     bail!("`subtask.cancel` called after terminal status delivered");
2989                 }
2990 
2991                 return Ok(Status::StartCancelled as u32);
2992             } else if task.lift_result.is_some() {
2993                 // Started, but not yet returned or cancelled; send the
2994                 // `CANCELLED` event
2995                 task.cancel_sent = true;
2996                 // Note that this might overwrite an event that was set earlier
2997                 // (e.g. `Event::None` if the task is yielding, or
2998                 // `Event::Cancelled` if it was already cancelled), but that's
2999                 // okay -- this should supersede the previous state.
3000                 task.event = Some(Event::Cancelled);
3001                 if let Some(set) = task.wake_on_cancel.take() {
3002                     let item = match concurrent_state
3003                         .get_mut(set)?
3004                         .waiting
3005                         .remove(&guest_task)
3006                         .unwrap()
3007                     {
3008                         WaitMode::Fiber(fiber) => WorkItem::ResumeFiber(fiber),
3009                         WaitMode::Callback => WorkItem::GuestCall(GuestCall {
3010                             task: guest_task,
3011                             kind: GuestCallKind::DeliverEvent { set: None },
3012                         }),
3013                     };
3014                     concurrent_state.push_high_priority(item);
3015 
3016                     self.suspend(store, SuspendReason::Yielding { task: caller })?;
3017                 }
3018 
3019                 let concurrent_state = self.concurrent_state_mut(store);
3020                 let task = concurrent_state.get_mut(guest_task)?;
3021                 if task.lift_result.is_some() {
3022                     // Still not yet returned or cancelled; if `async_`, return
3023                     // `BLOCKED`; otherwise wait
3024                     if async_ {
3025                         return Ok(BLOCKED);
3026                     } else {
3027                         self.wait_for_event(store, Waitable::Guest(guest_task))?;
3028                     }
3029                 }
3030             }
3031         }
3032 
3033         let event = waitable.take_event(self.concurrent_state_mut(store))?;
3034         if let Some(Event::Subtask {
3035             status: status @ (Status::Returned | Status::ReturnCancelled),
3036         }) = event
3037         {
3038             Ok(status as u32)
3039         } else {
3040             bail!("`subtask.cancel` called after terminal status delivered");
3041         }
3042     }
3043 
3044     fn wait_for_event(self, store: &mut dyn VMStore, waitable: Waitable) -> Result<()> {
3045         let state = self.concurrent_state_mut(store);
3046         let caller = state.guest_task.unwrap();
3047         let old_set = waitable.common(state)?.set;
3048         let set = state.get_mut(caller)?.sync_call_set;
3049         waitable.join(state, Some(set))?;
3050         self.suspend(store, SuspendReason::Waiting { set, task: caller })?;
3051         let state = self.concurrent_state_mut(store);
3052         waitable.join(state, old_set)
3053     }
3054 
3055     /// Configures TLS state so `store` will be available via `tls::get` within
3056     /// the closure `f` provided.
3057     ///
3058     /// This is used to ensure that `Future::poll`, which doesn't take a `store`
3059     /// parameter, is able to get access to the `store` during future poll
3060     /// methods.
3061     fn set_tls<R>(self, store: &mut dyn VMStore, f: impl FnOnce() -> R) -> R {
3062         struct Reset<'a>(&'a mut dyn VMStore, Option<ComponentInstanceId>);
3063 
3064         impl Drop for Reset<'_> {
3065             fn drop(&mut self) {
3066                 self.0.concurrent_async_state_mut().current_instance = self.1;
3067             }
3068         }
3069         let prev = mem::replace(
3070             &mut store.concurrent_async_state_mut().current_instance,
3071             Some(self.id().instance()),
3072         );
3073         let reset = Reset(store, prev);
3074 
3075         tls::set(reset.0, f)
3076     }
3077 
3078     /// Convenience function to reduce boilerplate.
3079     pub(crate) fn concurrent_state_mut<'a>(
3080         &self,
3081         store: &'a mut StoreOpaque,
3082     ) -> &'a mut ConcurrentState {
3083         self.id().get_mut(store).concurrent_state_mut()
3084     }
3085 
3086     pub(crate) fn context_get(
3087         self,
3088         store: &mut dyn VMStore,
3089         caller: RuntimeComponentInstanceIndex,
3090         slot: u32,
3091     ) -> Result<u32> {
3092         self.id().get(store).check_may_leave(caller)?;
3093         self.concurrent_state_mut(store).context_get(slot)
3094     }
3095 
3096     pub(crate) fn context_set(
3097         self,
3098         store: &mut dyn VMStore,
3099         caller: RuntimeComponentInstanceIndex,
3100         slot: u32,
3101         value: u32,
3102     ) -> Result<()> {
3103         self.id().get(store).check_may_leave(caller)?;
3104         self.concurrent_state_mut(store).context_set(slot, value)
3105     }
3106 }
3107 
3108 /// Trait representing component model ABI async intrinsics and fused adapter
3109 /// helper functions.
3110 ///
3111 /// SAFETY (callers): Most of the methods in this trait accept raw pointers,
3112 /// which must be valid for at least the duration of the call (and possibly for
3113 /// as long as the relevant guest task exists, in the case of `*mut VMFuncRef`
3114 /// pointers used for async calls).
3115 pub trait VMComponentAsyncStore {
3116     /// A helper function for fused adapter modules involving calls where the
3117     /// one of the caller or callee is async.
3118     ///
3119     /// This helper is not used when the caller and callee both use the sync
3120     /// ABI, only when at least one is async is this used.
3121     unsafe fn prepare_call(
3122         &mut self,
3123         instance: Instance,
3124         memory: *mut VMMemoryDefinition,
3125         start: *mut VMFuncRef,
3126         return_: *mut VMFuncRef,
3127         caller_instance: RuntimeComponentInstanceIndex,
3128         callee_instance: RuntimeComponentInstanceIndex,
3129         task_return_type: TypeTupleIndex,
3130         string_encoding: u8,
3131         result_count: u32,
3132         storage: *mut ValRaw,
3133         storage_len: usize,
3134     ) -> Result<()>;
3135 
3136     /// A helper function for fused adapter modules involving calls where the
3137     /// caller is sync-lowered but the callee is async-lifted.
3138     unsafe fn sync_start(
3139         &mut self,
3140         instance: Instance,
3141         callback: *mut VMFuncRef,
3142         callee: *mut VMFuncRef,
3143         param_count: u32,
3144         storage: *mut MaybeUninit<ValRaw>,
3145         storage_len: usize,
3146     ) -> Result<()>;
3147 
3148     /// A helper function for fused adapter modules involving calls where the
3149     /// caller is async-lowered.
3150     unsafe fn async_start(
3151         &mut self,
3152         instance: Instance,
3153         callback: *mut VMFuncRef,
3154         post_return: *mut VMFuncRef,
3155         callee: *mut VMFuncRef,
3156         param_count: u32,
3157         result_count: u32,
3158         flags: u32,
3159     ) -> Result<u32>;
3160 
3161     /// The `future.write` intrinsic.
3162     fn future_write(
3163         &mut self,
3164         instance: Instance,
3165         caller: RuntimeComponentInstanceIndex,
3166         ty: TypeFutureTableIndex,
3167         options: OptionsIndex,
3168         future: u32,
3169         address: u32,
3170     ) -> Result<u32>;
3171 
3172     /// The `future.read` intrinsic.
3173     fn future_read(
3174         &mut self,
3175         instance: Instance,
3176         caller: RuntimeComponentInstanceIndex,
3177         ty: TypeFutureTableIndex,
3178         options: OptionsIndex,
3179         future: u32,
3180         address: u32,
3181     ) -> Result<u32>;
3182 
3183     /// The `future.drop-writable` intrinsic.
3184     fn future_drop_writable(
3185         &mut self,
3186         instance: Instance,
3187         caller: RuntimeComponentInstanceIndex,
3188         ty: TypeFutureTableIndex,
3189         writer: u32,
3190     ) -> Result<()>;
3191 
3192     /// The `stream.write` intrinsic.
3193     fn stream_write(
3194         &mut self,
3195         instance: Instance,
3196         caller: RuntimeComponentInstanceIndex,
3197         ty: TypeStreamTableIndex,
3198         options: OptionsIndex,
3199         stream: u32,
3200         address: u32,
3201         count: u32,
3202     ) -> Result<u32>;
3203 
3204     /// The `stream.read` intrinsic.
3205     fn stream_read(
3206         &mut self,
3207         instance: Instance,
3208         caller: RuntimeComponentInstanceIndex,
3209         ty: TypeStreamTableIndex,
3210         options: OptionsIndex,
3211         stream: u32,
3212         address: u32,
3213         count: u32,
3214     ) -> Result<u32>;
3215 
3216     /// The "fast-path" implementation of the `stream.write` intrinsic for
3217     /// "flat" (i.e. memcpy-able) payloads.
3218     fn flat_stream_write(
3219         &mut self,
3220         instance: Instance,
3221         caller: RuntimeComponentInstanceIndex,
3222         ty: TypeStreamTableIndex,
3223         options: OptionsIndex,
3224         payload_size: u32,
3225         payload_align: u32,
3226         stream: u32,
3227         address: u32,
3228         count: u32,
3229     ) -> Result<u32>;
3230 
3231     /// The "fast-path" implementation of the `stream.read` intrinsic for "flat"
3232     /// (i.e. memcpy-able) payloads.
3233     fn flat_stream_read(
3234         &mut self,
3235         instance: Instance,
3236         caller: RuntimeComponentInstanceIndex,
3237         ty: TypeStreamTableIndex,
3238         options: OptionsIndex,
3239         payload_size: u32,
3240         payload_align: u32,
3241         stream: u32,
3242         address: u32,
3243         count: u32,
3244     ) -> Result<u32>;
3245 
3246     /// The `stream.drop-writable` intrinsic.
3247     fn stream_drop_writable(
3248         &mut self,
3249         instance: Instance,
3250         caller: RuntimeComponentInstanceIndex,
3251         ty: TypeStreamTableIndex,
3252         writer: u32,
3253     ) -> Result<()>;
3254 
3255     /// The `error-context.debug-message` intrinsic.
3256     fn error_context_debug_message(
3257         &mut self,
3258         instance: Instance,
3259         caller: RuntimeComponentInstanceIndex,
3260         ty: TypeComponentLocalErrorContextTableIndex,
3261         options: OptionsIndex,
3262         err_ctx_handle: u32,
3263         debug_msg_address: u32,
3264     ) -> Result<()>;
3265 }
3266 
3267 /// SAFETY: See trait docs.
3268 impl<T: 'static> VMComponentAsyncStore for StoreInner<T> {
3269     unsafe fn prepare_call(
3270         &mut self,
3271         instance: Instance,
3272         memory: *mut VMMemoryDefinition,
3273         start: *mut VMFuncRef,
3274         return_: *mut VMFuncRef,
3275         caller_instance: RuntimeComponentInstanceIndex,
3276         callee_instance: RuntimeComponentInstanceIndex,
3277         task_return_type: TypeTupleIndex,
3278         string_encoding: u8,
3279         result_count_or_max_if_async: u32,
3280         storage: *mut ValRaw,
3281         storage_len: usize,
3282     ) -> Result<()> {
3283         // SAFETY: The `wasmtime_cranelift`-generated code that calls
3284         // this method will have ensured that `storage` is a valid
3285         // pointer containing at least `storage_len` items.
3286         let params = unsafe { std::slice::from_raw_parts(storage, storage_len) }.to_vec();
3287 
3288         unsafe {
3289             instance.prepare_call(
3290                 StoreContextMut(self),
3291                 start,
3292                 return_,
3293                 caller_instance,
3294                 callee_instance,
3295                 task_return_type,
3296                 memory,
3297                 string_encoding,
3298                 match result_count_or_max_if_async {
3299                     PREPARE_ASYNC_NO_RESULT => CallerInfo::Async {
3300                         params,
3301                         has_result: false,
3302                     },
3303                     PREPARE_ASYNC_WITH_RESULT => CallerInfo::Async {
3304                         params,
3305                         has_result: true,
3306                     },
3307                     result_count => CallerInfo::Sync {
3308                         params,
3309                         result_count,
3310                     },
3311                 },
3312             )
3313         }
3314     }
3315 
3316     unsafe fn sync_start(
3317         &mut self,
3318         instance: Instance,
3319         callback: *mut VMFuncRef,
3320         callee: *mut VMFuncRef,
3321         param_count: u32,
3322         storage: *mut MaybeUninit<ValRaw>,
3323         storage_len: usize,
3324     ) -> Result<()> {
3325         unsafe {
3326             instance
3327                 .start_call(
3328                     StoreContextMut(self),
3329                     callback,
3330                     ptr::null_mut(),
3331                     callee,
3332                     param_count,
3333                     1,
3334                     START_FLAG_ASYNC_CALLEE,
3335                     // SAFETY: The `wasmtime_cranelift`-generated code that calls
3336                     // this method will have ensured that `storage` is a valid
3337                     // pointer containing at least `storage_len` items.
3338                     Some(std::slice::from_raw_parts_mut(storage, storage_len)),
3339                 )
3340                 .map(drop)
3341         }
3342     }
3343 
3344     unsafe fn async_start(
3345         &mut self,
3346         instance: Instance,
3347         callback: *mut VMFuncRef,
3348         post_return: *mut VMFuncRef,
3349         callee: *mut VMFuncRef,
3350         param_count: u32,
3351         result_count: u32,
3352         flags: u32,
3353     ) -> Result<u32> {
3354         unsafe {
3355             instance.start_call(
3356                 StoreContextMut(self),
3357                 callback,
3358                 post_return,
3359                 callee,
3360                 param_count,
3361                 result_count,
3362                 flags,
3363                 None,
3364             )
3365         }
3366     }
3367 
3368     fn future_write(
3369         &mut self,
3370         instance: Instance,
3371         caller: RuntimeComponentInstanceIndex,
3372         ty: TypeFutureTableIndex,
3373         options: OptionsIndex,
3374         future: u32,
3375         address: u32,
3376     ) -> Result<u32> {
3377         instance.id().get(self).check_may_leave(caller)?;
3378         instance
3379             .guest_write(
3380                 StoreContextMut(self),
3381                 TransmitIndex::Future(ty),
3382                 options,
3383                 None,
3384                 future,
3385                 address,
3386                 1,
3387             )
3388             .map(|result| result.encode())
3389     }
3390 
3391     fn future_read(
3392         &mut self,
3393         instance: Instance,
3394         caller: RuntimeComponentInstanceIndex,
3395         ty: TypeFutureTableIndex,
3396         options: OptionsIndex,
3397         future: u32,
3398         address: u32,
3399     ) -> Result<u32> {
3400         instance.id().get(self).check_may_leave(caller)?;
3401         instance
3402             .guest_read(
3403                 StoreContextMut(self),
3404                 TransmitIndex::Future(ty),
3405                 options,
3406                 None,
3407                 future,
3408                 address,
3409                 1,
3410             )
3411             .map(|result| result.encode())
3412     }
3413 
3414     fn stream_write(
3415         &mut self,
3416         instance: Instance,
3417         caller: RuntimeComponentInstanceIndex,
3418         ty: TypeStreamTableIndex,
3419         options: OptionsIndex,
3420         stream: u32,
3421         address: u32,
3422         count: u32,
3423     ) -> Result<u32> {
3424         instance.id().get(self).check_may_leave(caller)?;
3425         instance
3426             .guest_write(
3427                 StoreContextMut(self),
3428                 TransmitIndex::Stream(ty),
3429                 options,
3430                 None,
3431                 stream,
3432                 address,
3433                 count,
3434             )
3435             .map(|result| result.encode())
3436     }
3437 
3438     fn stream_read(
3439         &mut self,
3440         instance: Instance,
3441         caller: RuntimeComponentInstanceIndex,
3442         ty: TypeStreamTableIndex,
3443         options: OptionsIndex,
3444         stream: u32,
3445         address: u32,
3446         count: u32,
3447     ) -> Result<u32> {
3448         instance.id().get(self).check_may_leave(caller)?;
3449         instance
3450             .guest_read(
3451                 StoreContextMut(self),
3452                 TransmitIndex::Stream(ty),
3453                 options,
3454                 None,
3455                 stream,
3456                 address,
3457                 count,
3458             )
3459             .map(|result| result.encode())
3460     }
3461 
3462     fn future_drop_writable(
3463         &mut self,
3464         instance: Instance,
3465         caller: RuntimeComponentInstanceIndex,
3466         ty: TypeFutureTableIndex,
3467         writer: u32,
3468     ) -> Result<()> {
3469         instance.id().get(self).check_may_leave(caller)?;
3470         instance.guest_drop_writable(StoreContextMut(self), TransmitIndex::Future(ty), writer)
3471     }
3472 
3473     fn flat_stream_write(
3474         &mut self,
3475         instance: Instance,
3476         caller: RuntimeComponentInstanceIndex,
3477         ty: TypeStreamTableIndex,
3478         options: OptionsIndex,
3479         payload_size: u32,
3480         payload_align: u32,
3481         stream: u32,
3482         address: u32,
3483         count: u32,
3484     ) -> Result<u32> {
3485         instance.id().get(self).check_may_leave(caller)?;
3486         instance
3487             .guest_write(
3488                 StoreContextMut(self),
3489                 TransmitIndex::Stream(ty),
3490                 options,
3491                 Some(FlatAbi {
3492                     size: payload_size,
3493                     align: payload_align,
3494                 }),
3495                 stream,
3496                 address,
3497                 count,
3498             )
3499             .map(|result| result.encode())
3500     }
3501 
3502     fn flat_stream_read(
3503         &mut self,
3504         instance: Instance,
3505         caller: RuntimeComponentInstanceIndex,
3506         ty: TypeStreamTableIndex,
3507         options: OptionsIndex,
3508         payload_size: u32,
3509         payload_align: u32,
3510         stream: u32,
3511         address: u32,
3512         count: u32,
3513     ) -> Result<u32> {
3514         instance.id().get(self).check_may_leave(caller)?;
3515         instance
3516             .guest_read(
3517                 StoreContextMut(self),
3518                 TransmitIndex::Stream(ty),
3519                 options,
3520                 Some(FlatAbi {
3521                     size: payload_size,
3522                     align: payload_align,
3523                 }),
3524                 stream,
3525                 address,
3526                 count,
3527             )
3528             .map(|result| result.encode())
3529     }
3530 
3531     fn stream_drop_writable(
3532         &mut self,
3533         instance: Instance,
3534         caller: RuntimeComponentInstanceIndex,
3535         ty: TypeStreamTableIndex,
3536         writer: u32,
3537     ) -> Result<()> {
3538         instance.id().get(self).check_may_leave(caller)?;
3539         instance.guest_drop_writable(StoreContextMut(self), TransmitIndex::Stream(ty), writer)
3540     }
3541 
3542     fn error_context_debug_message(
3543         &mut self,
3544         instance: Instance,
3545         caller: RuntimeComponentInstanceIndex,
3546         ty: TypeComponentLocalErrorContextTableIndex,
3547         options: OptionsIndex,
3548         err_ctx_handle: u32,
3549         debug_msg_address: u32,
3550     ) -> Result<()> {
3551         instance.id().get(self).check_may_leave(caller)?;
3552         instance.error_context_debug_message(
3553             StoreContextMut(self),
3554             ty,
3555             options,
3556             err_ctx_handle,
3557             debug_msg_address,
3558         )
3559     }
3560 }
3561 
3562 type HostTaskFuture = Pin<Box<dyn Future<Output = Result<()>> + Send + 'static>>;
3563 
3564 /// Represents the state of a pending host task.
3565 struct HostTask {
3566     common: WaitableCommon,
3567     caller_instance: RuntimeComponentInstanceIndex,
3568     join_handle: Option<JoinHandle>,
3569 }
3570 
3571 impl HostTask {
3572     fn new(
3573         caller_instance: RuntimeComponentInstanceIndex,
3574         join_handle: Option<JoinHandle>,
3575     ) -> Self {
3576         Self {
3577             common: WaitableCommon::default(),
3578             caller_instance,
3579             join_handle,
3580         }
3581     }
3582 }
3583 
3584 impl TableDebug for HostTask {
3585     fn type_name() -> &'static str {
3586         "HostTask"
3587     }
3588 }
3589 
3590 type CallbackFn = Box<
3591     dyn Fn(&mut dyn VMStore, Instance, RuntimeComponentInstanceIndex, Event, u32) -> Result<u32>
3592         + Send
3593         + Sync
3594         + 'static,
3595 >;
3596 
3597 /// Represents the caller of a given guest task.
3598 enum Caller {
3599     /// The host called the guest task.
3600     Host {
3601         /// If present, may be used to deliver the result.
3602         tx: Option<oneshot::Sender<LiftedResult>>,
3603         /// Channel to notify once all subtasks spawned by this caller have
3604         /// completed.
3605         ///
3606         /// Note that we'll never actually send anything to this channel;
3607         /// dropping it when the refcount goes to zero is sufficient to notify
3608         /// the receiver.
3609         exit_tx: Arc<oneshot::Sender<()>>,
3610         /// If true, remove the task from the concurrent state that owns it
3611         /// automatically after it completes.
3612         remove_task_automatically: bool,
3613         /// If true, call `post-return` function (if any) automatically.
3614         call_post_return_automatically: bool,
3615     },
3616     /// Another guest task called the guest task
3617     Guest {
3618         /// The id of the caller
3619         task: TableId<GuestTask>,
3620         /// The instance to use to enforce reentrance rules.
3621         ///
3622         /// Note that this might not be the same as the instance the caller task
3623         /// started executing in given that one or more synchronous guest->guest
3624         /// calls may have occurred involving multiple instances.
3625         instance: RuntimeComponentInstanceIndex,
3626     },
3627 }
3628 
3629 /// Represents a closure and related canonical ABI parameters required to
3630 /// validate a `task.return` call at runtime and lift the result.
3631 struct LiftResult {
3632     lift: RawLift,
3633     ty: TypeTupleIndex,
3634     memory: Option<SendSyncPtr<VMMemoryDefinition>>,
3635     string_encoding: StringEncoding,
3636 }
3637 
3638 /// Represents a pending guest task.
3639 struct GuestTask {
3640     /// See `WaitableCommon`
3641     common: WaitableCommon,
3642     /// Closure to lower the parameters passed to this task.
3643     lower_params: Option<RawLower>,
3644     /// See `LiftResult`
3645     lift_result: Option<LiftResult>,
3646     /// A place to stash the type-erased lifted result if it can't be delivered
3647     /// immediately.
3648     result: Option<LiftedResult>,
3649     /// Closure to call the callback function for an async-lifted export, if
3650     /// provided.
3651     callback: Option<CallbackFn>,
3652     /// See `Caller`
3653     caller: Caller,
3654     /// A place to stash the call context for managing resource borrows while
3655     /// switching between guest tasks.
3656     call_context: Option<CallContext>,
3657     /// A place to stash the lowered result for a sync-to-async call until it
3658     /// can be returned to the caller.
3659     sync_result: Option<Option<ValRaw>>,
3660     /// Whether or not the task has been cancelled (i.e. whether the task is
3661     /// permitted to call `task.cancel`).
3662     cancel_sent: bool,
3663     /// Whether or not we've sent a `Status::Starting` event to any current or
3664     /// future waiters for this waitable.
3665     starting_sent: bool,
3666     /// Context-local state used to implement the `context.{get,set}`
3667     /// intrinsics.
3668     context: [u32; 2],
3669     /// Pending guest subtasks created by this task (directly or indirectly).
3670     ///
3671     /// This is used to re-parent subtasks which are still running when their
3672     /// parent task is disposed.
3673     subtasks: HashSet<TableId<GuestTask>>,
3674     /// Scratch waitable set used to watch subtasks during synchronous calls.
3675     sync_call_set: TableId<WaitableSet>,
3676     /// The instance to which the exported function for this guest task belongs.
3677     ///
3678     /// Note that the task may do a sync->sync call via a fused adapter which
3679     /// results in that task executing code in a different instance, and it may
3680     /// call host functions and intrinsics from that other instance.
3681     instance: RuntimeComponentInstanceIndex,
3682     /// If present, a pending `Event::None` or `Event::Cancelled` to be
3683     /// delivered to this task.
3684     event: Option<Event>,
3685     /// If present, indicates that the task is currently waiting on the
3686     /// specified set but may be cancelled and woken immediately.
3687     wake_on_cancel: Option<TableId<WaitableSet>>,
3688     /// The `ExportIndex` of the guest function being called, if known.
3689     function_index: Option<ExportIndex>,
3690     /// Whether or not the task has exited.
3691     exited: bool,
3692 }
3693 
3694 impl GuestTask {
3695     fn new(
3696         state: &mut ConcurrentState,
3697         lower_params: RawLower,
3698         lift_result: LiftResult,
3699         caller: Caller,
3700         callback: Option<CallbackFn>,
3701         component_instance: RuntimeComponentInstanceIndex,
3702     ) -> Result<Self> {
3703         let sync_call_set = state.push(WaitableSet::default())?;
3704 
3705         Ok(Self {
3706             common: WaitableCommon::default(),
3707             lower_params: Some(lower_params),
3708             lift_result: Some(lift_result),
3709             result: None,
3710             callback,
3711             caller,
3712             call_context: Some(CallContext::default()),
3713             sync_result: None,
3714             cancel_sent: false,
3715             starting_sent: false,
3716             context: [0u32; 2],
3717             subtasks: HashSet::new(),
3718             sync_call_set,
3719             instance: component_instance,
3720             event: None,
3721             wake_on_cancel: None,
3722             function_index: None,
3723             exited: false,
3724         })
3725     }
3726 
3727     /// Dispose of this guest task, reparenting any pending subtasks to the
3728     /// caller.
3729     fn dispose(self, state: &mut ConcurrentState, me: TableId<GuestTask>) -> Result<()> {
3730         // If there are not-yet-delivered completion events for subtasks in
3731         // `self.sync_call_set`, recursively dispose of those subtasks as well.
3732         for waitable in mem::take(&mut state.get_mut(self.sync_call_set)?.ready) {
3733             if let Some(Event::Subtask {
3734                 status: Status::Returned | Status::ReturnCancelled,
3735             }) = waitable.common(state)?.event
3736             {
3737                 waitable.delete_from(state)?;
3738             }
3739         }
3740 
3741         state.delete(self.sync_call_set)?;
3742 
3743         // Reparent any pending subtasks to the caller.
3744         match &self.caller {
3745             Caller::Guest {
3746                 task,
3747                 instance: runtime_instance,
3748             } => {
3749                 let task_mut = state.get_mut(*task)?;
3750                 let present = task_mut.subtasks.remove(&me);
3751                 assert!(present);
3752 
3753                 for subtask in &self.subtasks {
3754                     task_mut.subtasks.insert(*subtask);
3755                 }
3756 
3757                 for subtask in &self.subtasks {
3758                     state.get_mut(*subtask)?.caller = Caller::Guest {
3759                         task: *task,
3760                         instance: *runtime_instance,
3761                     };
3762                 }
3763             }
3764             Caller::Host { exit_tx, .. } => {
3765                 for subtask in &self.subtasks {
3766                     state.get_mut(*subtask)?.caller = Caller::Host {
3767                         tx: None,
3768                         // Clone `exit_tx` to ensure that it is only dropped
3769                         // once all transitive subtasks of the host call have
3770                         // exited:
3771                         exit_tx: exit_tx.clone(),
3772                         remove_task_automatically: true,
3773                         call_post_return_automatically: true,
3774                     };
3775                 }
3776             }
3777         }
3778 
3779         Ok(())
3780     }
3781 
3782     fn call_post_return_automatically(&self) -> bool {
3783         matches!(
3784             self.caller,
3785             Caller::Guest { .. }
3786                 | Caller::Host {
3787                     call_post_return_automatically: true,
3788                     ..
3789                 }
3790         )
3791     }
3792 }
3793 
3794 impl TableDebug for GuestTask {
3795     fn type_name() -> &'static str {
3796         "GuestTask"
3797     }
3798 }
3799 
3800 /// Represents state common to all kinds of waitables.
3801 #[derive(Default)]
3802 struct WaitableCommon {
3803     /// The currently pending event for this waitable, if any.
3804     event: Option<Event>,
3805     /// The set to which this waitable belongs, if any.
3806     set: Option<TableId<WaitableSet>>,
3807     /// The handle with which the guest refers to this waitable, if any.
3808     handle: Option<u32>,
3809 }
3810 
3811 /// Represents a Component Model Async `waitable`.
3812 #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
3813 enum Waitable {
3814     /// A host task
3815     Host(TableId<HostTask>),
3816     /// A guest task
3817     Guest(TableId<GuestTask>),
3818     /// The read or write end of a stream or future
3819     Transmit(TableId<TransmitHandle>),
3820 }
3821 
3822 impl Waitable {
3823     /// Retrieve the `Waitable` corresponding to the specified guest-visible
3824     /// handle.
3825     fn from_instance(
3826         state: Pin<&mut ComponentInstance>,
3827         caller_instance: RuntimeComponentInstanceIndex,
3828         waitable: u32,
3829     ) -> Result<Self> {
3830         use crate::runtime::vm::component::Waitable;
3831 
3832         let (waitable, kind) = state.guest_tables().0[caller_instance].waitable_rep(waitable)?;
3833 
3834         Ok(match kind {
3835             Waitable::Subtask { is_host: true } => Self::Host(TableId::new(waitable)),
3836             Waitable::Subtask { is_host: false } => Self::Guest(TableId::new(waitable)),
3837             Waitable::Stream | Waitable::Future => Self::Transmit(TableId::new(waitable)),
3838         })
3839     }
3840 
3841     /// Retrieve the host-visible identifier for this `Waitable`.
3842     fn rep(&self) -> u32 {
3843         match self {
3844             Self::Host(id) => id.rep(),
3845             Self::Guest(id) => id.rep(),
3846             Self::Transmit(id) => id.rep(),
3847         }
3848     }
3849 
3850     /// Move this `Waitable` to the specified set (when `set` is `Some(_)`) or
3851     /// remove it from any set it may currently belong to (when `set` is
3852     /// `None`).
3853     fn join(&self, state: &mut ConcurrentState, set: Option<TableId<WaitableSet>>) -> Result<()> {
3854         log::trace!("waitable {self:?} join set {set:?}",);
3855 
3856         let old = mem::replace(&mut self.common(state)?.set, set);
3857 
3858         if let Some(old) = old {
3859             match *self {
3860                 Waitable::Host(id) => state.remove_child(id, old),
3861                 Waitable::Guest(id) => state.remove_child(id, old),
3862                 Waitable::Transmit(id) => state.remove_child(id, old),
3863             }?;
3864 
3865             state.get_mut(old)?.ready.remove(self);
3866         }
3867 
3868         if let Some(set) = set {
3869             match *self {
3870                 Waitable::Host(id) => state.add_child(id, set),
3871                 Waitable::Guest(id) => state.add_child(id, set),
3872                 Waitable::Transmit(id) => state.add_child(id, set),
3873             }?;
3874 
3875             if self.common(state)?.event.is_some() {
3876                 self.mark_ready(state)?;
3877             }
3878         }
3879 
3880         Ok(())
3881     }
3882 
3883     /// Retrieve mutable access to the `WaitableCommon` for this `Waitable`.
3884     fn common<'a>(&self, state: &'a mut ConcurrentState) -> Result<&'a mut WaitableCommon> {
3885         Ok(match self {
3886             Self::Host(id) => &mut state.get_mut(*id)?.common,
3887             Self::Guest(id) => &mut state.get_mut(*id)?.common,
3888             Self::Transmit(id) => &mut state.get_mut(*id)?.common,
3889         })
3890     }
3891 
3892     /// Set or clear the pending event for this waitable and either deliver it
3893     /// to the first waiter, if any, or mark it as ready to be delivered to the
3894     /// next waiter that arrives.
3895     fn set_event(&self, state: &mut ConcurrentState, event: Option<Event>) -> Result<()> {
3896         log::trace!("set event for {self:?}: {event:?}");
3897         self.common(state)?.event = event;
3898         self.mark_ready(state)
3899     }
3900 
3901     /// Take the pending event from this waitable, leaving `None` in its place.
3902     fn take_event(&self, state: &mut ConcurrentState) -> Result<Option<Event>> {
3903         let common = self.common(state)?;
3904         let event = common.event.take();
3905         if let Some(set) = self.common(state)?.set {
3906             state.get_mut(set)?.ready.remove(self);
3907         }
3908         Ok(event)
3909     }
3910 
3911     /// Deliver the current event for this waitable to the first waiter, if any,
3912     /// or else mark it as ready to be delivered to the next waiter that
3913     /// arrives.
3914     fn mark_ready(&self, state: &mut ConcurrentState) -> Result<()> {
3915         if let Some(set) = self.common(state)?.set {
3916             state.get_mut(set)?.ready.insert(*self);
3917             if let Some((task, mode)) = state.get_mut(set)?.waiting.pop_first() {
3918                 let wake_on_cancel = state.get_mut(task)?.wake_on_cancel.take();
3919                 assert!(wake_on_cancel.is_none() || wake_on_cancel == Some(set));
3920 
3921                 let item = match mode {
3922                     WaitMode::Fiber(fiber) => WorkItem::ResumeFiber(fiber),
3923                     WaitMode::Callback => WorkItem::GuestCall(GuestCall {
3924                         task,
3925                         kind: GuestCallKind::DeliverEvent { set: Some(set) },
3926                     }),
3927                 };
3928                 state.push_high_priority(item);
3929             }
3930         }
3931         Ok(())
3932     }
3933 
3934     /// Handle the imminent delivery of the specified event, e.g. by updating
3935     /// the state of the stream or future.
3936     fn on_delivery(&self, instance: Pin<&mut ComponentInstance>, event: Event) {
3937         match event {
3938             Event::FutureRead {
3939                 pending: Some((ty, handle)),
3940                 ..
3941             }
3942             | Event::FutureWrite {
3943                 pending: Some((ty, handle)),
3944                 ..
3945             } => {
3946                 let runtime_instance = instance.component().types()[ty].instance;
3947                 let (rep, state) = instance.guest_tables().0[runtime_instance]
3948                     .future_rep(ty, handle)
3949                     .unwrap();
3950                 assert_eq!(rep, self.rep());
3951                 assert_eq!(*state, TransmitLocalState::Busy);
3952                 *state = match event {
3953                     Event::FutureRead { .. } => TransmitLocalState::Read { done: false },
3954                     Event::FutureWrite { .. } => TransmitLocalState::Write { done: false },
3955                     _ => unreachable!(),
3956                 };
3957             }
3958             Event::StreamRead {
3959                 pending: Some((ty, handle)),
3960                 code,
3961             }
3962             | Event::StreamWrite {
3963                 pending: Some((ty, handle)),
3964                 code,
3965             } => {
3966                 let runtime_instance = instance.component().types()[ty].instance;
3967                 let (rep, state) = instance.guest_tables().0[runtime_instance]
3968                     .stream_rep(ty, handle)
3969                     .unwrap();
3970                 assert_eq!(rep, self.rep());
3971                 assert_eq!(*state, TransmitLocalState::Busy);
3972                 let done = matches!(code, ReturnCode::Dropped(_));
3973                 *state = match event {
3974                     Event::StreamRead { .. } => TransmitLocalState::Read { done },
3975                     Event::StreamWrite { .. } => TransmitLocalState::Write { done },
3976                     _ => unreachable!(),
3977                 };
3978             }
3979             _ => {}
3980         }
3981     }
3982 
3983     /// Remove this waitable from the instance's rep table.
3984     fn delete_from(&self, state: &mut ConcurrentState) -> Result<()> {
3985         match self {
3986             Self::Host(task) => {
3987                 log::trace!("delete host task {task:?}");
3988                 state.delete(*task)?;
3989             }
3990             Self::Guest(task) => {
3991                 log::trace!("delete guest task {task:?}");
3992                 state.delete(*task)?.dispose(state, *task)?;
3993             }
3994             Self::Transmit(task) => {
3995                 state.delete(*task)?;
3996             }
3997         }
3998 
3999         Ok(())
4000     }
4001 }
4002 
4003 impl fmt::Debug for Waitable {
4004     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4005         match self {
4006             Self::Host(id) => write!(f, "{id:?}"),
4007             Self::Guest(id) => write!(f, "{id:?}"),
4008             Self::Transmit(id) => write!(f, "{id:?}"),
4009         }
4010     }
4011 }
4012 
4013 /// Represents a Component Model Async `waitable-set`.
4014 #[derive(Default)]
4015 struct WaitableSet {
4016     /// Which waitables in this set have pending events, if any.
4017     ready: BTreeSet<Waitable>,
4018     /// Which guest tasks are currently waiting on this set, if any.
4019     waiting: BTreeMap<TableId<GuestTask>, WaitMode>,
4020 }
4021 
4022 impl TableDebug for WaitableSet {
4023     fn type_name() -> &'static str {
4024         "WaitableSet"
4025     }
4026 }
4027 
4028 /// Type-erased closure to lower the parameters for a guest task.
4029 type RawLower = Box<
4030     dyn FnOnce(&mut dyn VMStore, Instance, &mut [MaybeUninit<ValRaw>]) -> Result<()> + Send + Sync,
4031 >;
4032 
4033 /// Type-erased closure to lift the result for a guest task.
4034 type RawLift = Box<
4035     dyn FnOnce(&mut dyn VMStore, Instance, &[ValRaw]) -> Result<Box<dyn Any + Send + Sync>>
4036         + Send
4037         + Sync,
4038 >;
4039 
4040 /// Type erased result of a guest task which may be downcast to the expected
4041 /// type by a host caller (or simply ignored in the case of a guest caller; see
4042 /// `DummyResult`).
4043 type LiftedResult = Box<dyn Any + Send + Sync>;
4044 
4045 /// Used to return a result from a `LiftFn` when the actual result has already
4046 /// been lowered to a guest task's stack and linear memory.
4047 struct DummyResult;
4048 
4049 /// Represents the state of a currently executing fiber which has been resumed
4050 /// via `self::poll_fn`.
4051 pub(crate) struct AsyncState {
4052     /// The current instance being polled, if any, which is used to perform
4053     /// checks to ensure that futures are always polled within the correct
4054     /// instance.
4055     current_instance: Option<ComponentInstanceId>,
4056 }
4057 
4058 impl Default for AsyncState {
4059     fn default() -> Self {
4060         Self {
4061             current_instance: None,
4062         }
4063     }
4064 }
4065 
4066 /// Represents the Component Model Async state of a (sub-)component instance.
4067 #[derive(Default)]
4068 struct InstanceState {
4069     /// Whether backpressure is set for this instance (enabled if >0)
4070     backpressure: u16,
4071     /// Whether this instance can be entered
4072     do_not_enter: bool,
4073     /// Pending calls for this instance which require `Self::backpressure` to be
4074     /// `true` and/or `Self::do_not_enter` to be false before they can proceed.
4075     pending: BTreeMap<TableId<GuestTask>, GuestCallKind>,
4076 }
4077 
4078 /// Represents the Component Model Async state of a top-level component instance
4079 /// (i.e. a `super::ComponentInstance`).
4080 pub struct ConcurrentState {
4081     /// The currently running guest task, if any.
4082     guest_task: Option<TableId<GuestTask>>,
4083     /// The set of pending host and background tasks, if any.
4084     ///
4085     /// See `ComponentInstance::poll_until` for where we temporarily take this
4086     /// out, poll it, then put it back to avoid any mutable aliasing hazards.
4087     futures: AlwaysMut<Option<FuturesUnordered<HostTaskFuture>>>,
4088     /// The table of waitables, waitable sets, etc.
4089     table: AlwaysMut<ResourceTable>,
4090     /// Per (sub-)component instance states.
4091     ///
4092     /// See `InstanceState` for details and note that this map is lazily
4093     /// populated as needed.
4094     // TODO: this can and should be a `PrimaryMap`
4095     instance_states: HashMap<RuntimeComponentInstanceIndex, InstanceState>,
4096     /// The "high priority" work queue for this instance's event loop.
4097     high_priority: Vec<WorkItem>,
4098     /// The "high priority" work queue for this instance's event loop.
4099     low_priority: Vec<WorkItem>,
4100     /// A place to stash the reason a fiber is suspending so that the code which
4101     /// resumed it will know under what conditions the fiber should be resumed
4102     /// again.
4103     suspend_reason: Option<SuspendReason>,
4104     /// A cached fiber which is waiting for work to do.
4105     ///
4106     /// This helps us avoid creating a new fiber for each `GuestCall` work item.
4107     worker: Option<StoreFiber<'static>>,
4108     /// A place to stash the work item for which we're resuming a worker fiber.
4109     worker_item: Option<WorkerItem>,
4110 
4111     /// Reference counts for all component error contexts
4112     ///
4113     /// NOTE: it is possible the global ref count to be *greater* than the sum of
4114     /// (sub)component ref counts as tracked by `error_context_tables`, for
4115     /// example when the host holds one or more references to error contexts.
4116     ///
4117     /// The key of this primary map is often referred to as the "rep" (i.e. host-side
4118     /// component-wide representation) of the index into concurrent state for a given
4119     /// stored `ErrorContext`.
4120     ///
4121     /// Stated another way, `TypeComponentGlobalErrorContextTableIndex` is essentially the same
4122     /// as a `TableId<ErrorContextState>`.
4123     global_error_context_ref_counts:
4124         BTreeMap<TypeComponentGlobalErrorContextTableIndex, GlobalErrorContextRefCount>,
4125 
4126     /// Mirror of type information in `ComponentInstance`, placed here for
4127     /// convenience at the cost of an extra `Arc` clone.
4128     component: Component,
4129 }
4130 
4131 impl ConcurrentState {
4132     pub(crate) fn new(component: &Component) -> Self {
4133         Self {
4134             guest_task: None,
4135             table: AlwaysMut::new(ResourceTable::new()),
4136             futures: AlwaysMut::new(Some(FuturesUnordered::new())),
4137             instance_states: HashMap::new(),
4138             high_priority: Vec::new(),
4139             low_priority: Vec::new(),
4140             suspend_reason: None,
4141             worker: None,
4142             worker_item: None,
4143             global_error_context_ref_counts: BTreeMap::new(),
4144             component: component.clone(),
4145         }
4146     }
4147 
4148     /// Take ownership of any fibers and futures owned by this object.
4149     ///
4150     /// This should be used when disposing of the `Store` containing this object
4151     /// in order to gracefully resolve any and all fibers using
4152     /// `StoreFiber::dispose`.  This is necessary to avoid possible
4153     /// use-after-free bugs due to fibers which may still have access to the
4154     /// `Store`.
4155     ///
4156     /// Additionally, the futures collected with this function should be dropped
4157     /// within a `tls::set` call, which will ensure than any futures closing
4158     /// over an `&Accessor` will have access to the store when dropped, allowing
4159     /// e.g. `WithAccessor[AndValue]` instances to be disposed of without
4160     /// panicking.
4161     ///
4162     /// Note that this will leave the object in an inconsistent and unusable
4163     /// state, so it should only be used just prior to dropping it.
4164     pub(crate) fn take_fibers_and_futures(
4165         &mut self,
4166         fibers: &mut Vec<StoreFiber<'static>>,
4167         futures: &mut Vec<FuturesUnordered<HostTaskFuture>>,
4168     ) {
4169         for entry in self.table.get_mut().iter_mut() {
4170             if let Some(set) = entry.downcast_mut::<WaitableSet>() {
4171                 for mode in mem::take(&mut set.waiting).into_values() {
4172                     if let WaitMode::Fiber(fiber) = mode {
4173                         fibers.push(fiber);
4174                     }
4175                 }
4176             }
4177         }
4178 
4179         if let Some(fiber) = self.worker.take() {
4180             fibers.push(fiber);
4181         }
4182 
4183         let mut take_items = |list| {
4184             for item in mem::take(list) {
4185                 match item {
4186                     WorkItem::ResumeFiber(fiber) => {
4187                         fibers.push(fiber);
4188                     }
4189                     WorkItem::PushFuture(future) => {
4190                         self.futures
4191                             .get_mut()
4192                             .as_mut()
4193                             .unwrap()
4194                             .push(future.into_inner());
4195                     }
4196                     _ => {}
4197                 }
4198             }
4199         };
4200 
4201         take_items(&mut self.high_priority);
4202         take_items(&mut self.low_priority);
4203 
4204         if let Some(them) = self.futures.get_mut().take() {
4205             futures.push(them);
4206         }
4207     }
4208 
4209     fn instance_state(&mut self, instance: RuntimeComponentInstanceIndex) -> &mut InstanceState {
4210         self.instance_states.entry(instance).or_default()
4211     }
4212 
4213     fn push<V: Send + Sync + 'static>(
4214         &mut self,
4215         value: V,
4216     ) -> Result<TableId<V>, ResourceTableError> {
4217         self.table.get_mut().push(value).map(TableId::from)
4218     }
4219 
4220     fn get_mut<V: 'static>(&mut self, id: TableId<V>) -> Result<&mut V, ResourceTableError> {
4221         self.table.get_mut().get_mut(&Resource::from(id))
4222     }
4223 
4224     pub fn add_child<T: 'static, U: 'static>(
4225         &mut self,
4226         child: TableId<T>,
4227         parent: TableId<U>,
4228     ) -> Result<(), ResourceTableError> {
4229         self.table
4230             .get_mut()
4231             .add_child(Resource::from(child), Resource::from(parent))
4232     }
4233 
4234     pub fn remove_child<T: 'static, U: 'static>(
4235         &mut self,
4236         child: TableId<T>,
4237         parent: TableId<U>,
4238     ) -> Result<(), ResourceTableError> {
4239         self.table
4240             .get_mut()
4241             .remove_child(Resource::from(child), Resource::from(parent))
4242     }
4243 
4244     fn delete<V: 'static>(&mut self, id: TableId<V>) -> Result<V, ResourceTableError> {
4245         self.table.get_mut().delete(Resource::from(id))
4246     }
4247 
4248     fn push_future(&mut self, future: HostTaskFuture) {
4249         // Note that we can't directly push to `ConcurrentState::futures` here
4250         // since this may be called from a future that's being polled inside
4251         // `Self::poll_until`, which temporarily removes the `FuturesUnordered`
4252         // so it has exclusive access while polling it.  Therefore, we push a
4253         // work item to the "high priority" queue, which will actually push to
4254         // `ConcurrentState::futures` later.
4255         self.push_high_priority(WorkItem::PushFuture(AlwaysMut::new(future)));
4256     }
4257 
4258     fn push_high_priority(&mut self, item: WorkItem) {
4259         log::trace!("push high priority: {item:?}");
4260         self.high_priority.push(item);
4261     }
4262 
4263     fn push_low_priority(&mut self, item: WorkItem) {
4264         log::trace!("push low priority: {item:?}");
4265         self.low_priority.push(item);
4266     }
4267 
4268     /// Determine whether the instance associated with the specified guest task
4269     /// may be entered (i.e. is not already on the async call stack).
4270     ///
4271     /// This is an additional check on top of the "may_enter" instance flag;
4272     /// it's needed because async-lifted exports with callback functions must
4273     /// not call their own instances directly or indirectly, and due to the
4274     /// "stackless" nature of callback-enabled guest tasks this may happen even
4275     /// if there are no activation records on the stack (i.e. the "may_enter"
4276     /// field is `true`) for that instance.
4277     fn may_enter(&mut self, mut guest_task: TableId<GuestTask>) -> bool {
4278         let guest_instance = self.get_mut(guest_task).unwrap().instance;
4279 
4280         // Walk the task tree back to the root, looking for potential
4281         // reentrance.
4282         //
4283         // TODO: This could be optimized by maintaining a per-`GuestTask` bitset
4284         // such that each bit represents and instance which has been entered by
4285         // that task or an ancestor of that task, in which case this would be a
4286         // constant time check.
4287         loop {
4288             match &self.get_mut(guest_task).unwrap().caller {
4289                 Caller::Host { .. } => break true,
4290                 Caller::Guest { task, instance } => {
4291                     if *instance == guest_instance {
4292                         break false;
4293                     } else {
4294                         guest_task = *task;
4295                     }
4296                 }
4297             }
4298         }
4299     }
4300 
4301     /// Record that we're about to enter a (sub-)component instance which does
4302     /// not support more than one concurrent, stackful activation, meaning it
4303     /// cannot be entered again until the next call returns.
4304     fn enter_instance(&mut self, instance: RuntimeComponentInstanceIndex) {
4305         self.instance_state(instance).do_not_enter = true;
4306     }
4307 
4308     /// Record that we've exited a (sub-)component instance previously entered
4309     /// with `Self::enter_instance` and then calls `Self::partition_pending`.
4310     /// See the documentation for the latter for details.
4311     fn exit_instance(&mut self, instance: RuntimeComponentInstanceIndex) -> Result<()> {
4312         self.instance_state(instance).do_not_enter = false;
4313         self.partition_pending(instance)
4314     }
4315 
4316     /// Iterate over `InstanceState::pending`, moving any ready items into the
4317     /// "high priority" work item queue.
4318     ///
4319     /// See `GuestCall::is_ready` for details.
4320     fn partition_pending(&mut self, instance: RuntimeComponentInstanceIndex) -> Result<()> {
4321         for (task, kind) in mem::take(&mut self.instance_state(instance).pending).into_iter() {
4322             let call = GuestCall { task, kind };
4323             if call.is_ready(self)? {
4324                 self.push_high_priority(WorkItem::GuestCall(call));
4325             } else {
4326                 self.instance_state(instance)
4327                     .pending
4328                     .insert(call.task, call.kind);
4329             }
4330         }
4331 
4332         Ok(())
4333     }
4334 
4335     /// Implements the `backpressure.{set,inc,dec}` intrinsics.
4336     pub(crate) fn backpressure_modify(
4337         &mut self,
4338         caller_instance: RuntimeComponentInstanceIndex,
4339         modify: impl FnOnce(u16) -> Option<u16>,
4340     ) -> Result<()> {
4341         let state = self.instance_state(caller_instance);
4342         let old = state.backpressure;
4343         let new = modify(old).ok_or_else(|| anyhow!("backpressure counter overflow"))?;
4344         state.backpressure = new;
4345 
4346         if old > 0 && new == 0 {
4347             // Backpressure was previously enabled and is now disabled; move any
4348             // newly-eligible guest calls to the "high priority" queue.
4349             self.partition_pending(caller_instance)?;
4350         }
4351 
4352         Ok(())
4353     }
4354 
4355     /// Implements the `context.get` intrinsic.
4356     pub(crate) fn context_get(&mut self, slot: u32) -> Result<u32> {
4357         let task = self.guest_task.unwrap();
4358         let val = self.get_mut(task)?.context[usize::try_from(slot).unwrap()];
4359         log::trace!("context_get {task:?} slot {slot} val {val:#x}");
4360         Ok(val)
4361     }
4362 
4363     /// Implements the `context.set` intrinsic.
4364     pub(crate) fn context_set(&mut self, slot: u32, val: u32) -> Result<()> {
4365         let task = self.guest_task.unwrap();
4366         log::trace!("context_set {task:?} slot {slot} val {val:#x}");
4367         self.get_mut(task)?.context[usize::try_from(slot).unwrap()] = val;
4368         Ok(())
4369     }
4370 
4371     fn options(&self, options: OptionsIndex) -> &CanonicalOptions {
4372         &self.component.env_component().options[options]
4373     }
4374 }
4375 
4376 /// Provide a type hint to compiler about the shape of a parameter lower
4377 /// closure.
4378 fn for_any_lower<
4379     F: FnOnce(&mut dyn VMStore, Instance, &mut [MaybeUninit<ValRaw>]) -> Result<()> + Send + Sync,
4380 >(
4381     fun: F,
4382 ) -> F {
4383     fun
4384 }
4385 
4386 /// Provide a type hint to compiler about the shape of a result lift closure.
4387 fn for_any_lift<
4388     F: FnOnce(&mut dyn VMStore, Instance, &[ValRaw]) -> Result<Box<dyn Any + Send + Sync>>
4389         + Send
4390         + Sync,
4391 >(
4392     fun: F,
4393 ) -> F {
4394     fun
4395 }
4396 
4397 /// Wrap the specified future in a `poll_fn` which asserts that the future is
4398 /// only polled from the event loop of the specified `Instance`.
4399 ///
4400 /// See `Instance::run_concurrent` for details.
4401 fn checked<F: Future + Send + 'static>(
4402     instance: Instance,
4403     fut: F,
4404 ) -> impl Future<Output = F::Output> + Send + 'static {
4405     async move {
4406         let mut fut = pin!(fut);
4407         future::poll_fn(move |cx| {
4408             let message = "\
4409                 `Future`s which depend on asynchronous component tasks, streams, or \
4410                 futures to complete may only be polled from the event loop of the \
4411                 instance from which they originated.  Please use \
4412                 `Instance::{run_concurrent,spawn}` to poll or await them.\
4413             ";
4414             tls::try_get(|store| {
4415                 let matched = match store {
4416                     tls::TryGet::Some(store) => {
4417                         let a = store.concurrent_async_state_mut().current_instance;
4418                         a == Some(instance.id().instance())
4419                     }
4420                     tls::TryGet::Taken | tls::TryGet::None => false,
4421                 };
4422 
4423                 if !matched {
4424                     panic!("{message}")
4425                 }
4426             });
4427             fut.as_mut().poll(cx)
4428         })
4429         .await
4430     }
4431 }
4432 
4433 /// Assert that `Instance::run_concurrent` has not been called from within an
4434 /// instance's event loop.
4435 fn check_recursive_run() {
4436     tls::try_get(|store| {
4437         if !matches!(store, tls::TryGet::None) {
4438             panic!("Recursive `Instance::run_concurrent` calls not supported")
4439         }
4440     });
4441 }
4442 
4443 fn unpack_callback_code(code: u32) -> (u32, u32) {
4444     (code & 0xF, code >> 4)
4445 }
4446 
4447 /// Helper struct for packaging parameters to be passed to
4448 /// `ComponentInstance::waitable_check` for calls to `waitable-set.wait` or
4449 /// `waitable-set.poll`.
4450 struct WaitableCheckParams {
4451     set: TableId<WaitableSet>,
4452     options: OptionsIndex,
4453     payload: u32,
4454 }
4455 
4456 /// Helper enum for passing parameters to `ComponentInstance::waitable_check`.
4457 enum WaitableCheck {
4458     Wait(WaitableCheckParams),
4459     Poll(WaitableCheckParams),
4460     Yield,
4461 }
4462 
4463 /// Represents a guest task called from the host, prepared using `prepare_call`.
4464 pub(crate) struct PreparedCall<R> {
4465     /// The guest export to be called
4466     handle: Func,
4467     /// The guest task created by `prepare_call`
4468     task: TableId<GuestTask>,
4469     /// The number of lowered core Wasm parameters to pass to the call.
4470     param_count: usize,
4471     /// The `oneshot::Receiver` to which the result of the call will be
4472     /// delivered when it is available.
4473     rx: oneshot::Receiver<LiftedResult>,
4474     /// The `oneshot::Receiver` which will resolve when the task -- and any
4475     /// transitive subtasks -- have all exited.
4476     exit_rx: oneshot::Receiver<()>,
4477     _phantom: PhantomData<R>,
4478 }
4479 
4480 impl<R> PreparedCall<R> {
4481     /// Get a copy of the `TaskId` for this `PreparedCall`.
4482     pub(crate) fn task_id(&self) -> TaskId {
4483         TaskId {
4484             handle: self.handle,
4485             task: self.task,
4486         }
4487     }
4488 }
4489 
4490 /// Represents a task created by `prepare_call`.
4491 pub(crate) struct TaskId {
4492     handle: Func,
4493     task: TableId<GuestTask>,
4494 }
4495 
4496 impl TaskId {
4497     /// Remove the specified task from the concurrent state to which it belongs.
4498     ///
4499     /// This must be used with care to avoid use-after-delete or double-delete
4500     /// bugs.  Specifically, it should only be called on tasks created with the
4501     /// `remove_task_automatically` parameter to `prepare_call` set to `false`,
4502     /// which tells the runtime that the caller is responsible for removing the
4503     /// task from the state; otherwise, it will be removed automatically.  Also,
4504     /// it should only be called once for a given task, and only after either
4505     /// the task has completed or the instance has trapped.
4506     pub(crate) fn remove<T>(&self, store: StoreContextMut<T>) -> Result<()> {
4507         Waitable::Guest(self.task).delete_from(self.handle.instance().concurrent_state_mut(store.0))
4508     }
4509 }
4510 
4511 /// Prepare a call to the specified exported Wasm function, providing functions
4512 /// for lowering the parameters and lifting the result.
4513 ///
4514 /// To enqueue the returned `PreparedCall` in the `ComponentInstance`'s event
4515 /// loop, use `queue_call`.
4516 pub(crate) fn prepare_call<T, R>(
4517     mut store: StoreContextMut<T>,
4518     handle: Func,
4519     param_count: usize,
4520     remove_task_automatically: bool,
4521     call_post_return_automatically: bool,
4522     lower_params: impl FnOnce(Func, StoreContextMut<T>, &mut [MaybeUninit<ValRaw>]) -> Result<()>
4523     + Send
4524     + Sync
4525     + 'static,
4526     lift_result: impl FnOnce(Func, &mut StoreOpaque, &[ValRaw]) -> Result<Box<dyn Any + Send + Sync>>
4527     + Send
4528     + Sync
4529     + 'static,
4530 ) -> Result<PreparedCall<R>> {
4531     let (options, _flags, ty, raw_options) = handle.abi_info(store.0);
4532 
4533     let instance = handle.instance().id().get(store.0);
4534     let task_return_type = instance.component().types()[ty].results;
4535     let component_instance = raw_options.instance;
4536     let callback = options.callback();
4537     let memory = options.memory_raw().map(SendSyncPtr::new);
4538     let string_encoding = options.string_encoding();
4539     let token = StoreToken::new(store.as_context_mut());
4540     let state = handle.instance().concurrent_state_mut(store.0);
4541 
4542     assert!(state.guest_task.is_none());
4543 
4544     let (tx, rx) = oneshot::channel();
4545     let (exit_tx, exit_rx) = oneshot::channel();
4546 
4547     let mut task = GuestTask::new(
4548         state,
4549         Box::new(for_any_lower(move |store, instance, params| {
4550             debug_assert!(instance.id() == handle.instance().id());
4551             lower_params(handle, token.as_context_mut(store), params)
4552         })),
4553         LiftResult {
4554             lift: Box::new(for_any_lift(move |store, instance, result| {
4555                 debug_assert!(instance.id() == handle.instance().id());
4556                 lift_result(handle, store, result)
4557             })),
4558             ty: task_return_type,
4559             memory,
4560             string_encoding,
4561         },
4562         Caller::Host {
4563             tx: Some(tx),
4564             exit_tx: Arc::new(exit_tx),
4565             remove_task_automatically,
4566             call_post_return_automatically,
4567         },
4568         callback.map(|callback| {
4569             let callback = SendSyncPtr::new(callback);
4570             Box::new(
4571                 move |store: &mut dyn VMStore,
4572                       instance: Instance,
4573                       runtime_instance,
4574                       event,
4575                       handle| {
4576                     let store = token.as_context_mut(store);
4577                     // SAFETY: Per the contract of `prepare_call`, the callback
4578                     // will remain valid at least as long is this task exists.
4579                     unsafe {
4580                         instance.call_callback(
4581                             store,
4582                             runtime_instance,
4583                             callback,
4584                             event,
4585                             handle,
4586                             call_post_return_automatically,
4587                         )
4588                     }
4589                 },
4590             ) as CallbackFn
4591         }),
4592         component_instance,
4593     )?;
4594     task.function_index = Some(handle.index());
4595 
4596     let task = state.push(task)?;
4597 
4598     Ok(PreparedCall {
4599         handle,
4600         task,
4601         param_count,
4602         rx,
4603         exit_rx,
4604         _phantom: PhantomData,
4605     })
4606 }
4607 
4608 /// Queue a call previously prepared using `prepare_call` to be run as part of
4609 /// the associated `ComponentInstance`'s event loop.
4610 ///
4611 /// The returned future will resolve to the result once it is available, but
4612 /// must only be polled via the instance's event loop. See
4613 /// `Instance::run_concurrent` for details.
4614 pub(crate) fn queue_call<T: 'static, R: Send + 'static>(
4615     mut store: StoreContextMut<T>,
4616     prepared: PreparedCall<R>,
4617 ) -> Result<impl Future<Output = Result<(R, oneshot::Receiver<()>)>> + Send + 'static + use<T, R>> {
4618     let PreparedCall {
4619         handle,
4620         task,
4621         param_count,
4622         rx,
4623         exit_rx,
4624         ..
4625     } = prepared;
4626 
4627     queue_call0(store.as_context_mut(), handle, task, param_count)?;
4628 
4629     Ok(checked(
4630         handle.instance(),
4631         rx.map(move |result| {
4632             result
4633                 .map(|v| (*v.downcast().unwrap(), exit_rx))
4634                 .map_err(anyhow::Error::from)
4635         }),
4636     ))
4637 }
4638 
4639 /// Queue a call previously prepared using `prepare_call` to be run as part of
4640 /// the associated `ComponentInstance`'s event loop.
4641 fn queue_call0<T: 'static>(
4642     store: StoreContextMut<T>,
4643     handle: Func,
4644     guest_task: TableId<GuestTask>,
4645     param_count: usize,
4646 ) -> Result<()> {
4647     let (options, flags, _ty, raw_options) = handle.abi_info(store.0);
4648     let is_concurrent = raw_options.async_;
4649     let instance = handle.instance();
4650     let callee = handle.lifted_core_func(store.0);
4651     let callback = options.callback();
4652     let post_return = handle.post_return_core_func(store.0);
4653 
4654     log::trace!("queueing call {guest_task:?}");
4655 
4656     let instance_flags = if callback.is_none() {
4657         None
4658     } else {
4659         Some(flags)
4660     };
4661 
4662     // SAFETY: `callee`, `callback`, and `post_return` are valid pointers
4663     // (with signatures appropriate for this call) and will remain valid as
4664     // long as this instance is valid.
4665     unsafe {
4666         instance.queue_call(
4667             store,
4668             guest_task,
4669             SendSyncPtr::new(callee),
4670             param_count,
4671             1,
4672             instance_flags,
4673             is_concurrent,
4674             callback.map(SendSyncPtr::new),
4675             post_return.map(SendSyncPtr::new),
4676         )
4677     }
4678 }
4679