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