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     ErrorContext, FutureReader, FutureWriter, GuardedFutureReader, GuardedFutureWriter,
95     GuardedStreamReader, GuardedStreamWriter, ReadBuffer, StreamReader, StreamWriter, VecBuffer,
96     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     /// Changes this accessor to access `D2` instead of the current type
461     /// parameter `D`.
462     ///
463     /// This changes the underlying data access from `T` to `D2::Data<'_>`.
464     ///
465     /// Note that this is not a public or recommended API because it's easy to
466     /// cause panics with this by having two `Accessor` values live at the same
467     /// time. The returned `Accessor` does not refer to this `Accessor` meaning
468     /// that both can be used. You could, for example, call `Accessor::with`
469     /// simultaneously on both. That would cause a panic though.
470     ///
471     /// In short while there's nothing unsafe about this it's a footgun. It's
472     /// here for bindings generation where the provided accessor is transformed
473     /// into a new accessor and then this returned accessor is passed to
474     /// implementations.
475     ///
476     /// Note that one possible fix for this would be a lifetime parameter on
477     /// `Accessor` itself so the returned value could borrow from the original
478     /// value (or this could be `self`-by-value instead of `&mut self`) but in
479     /// attempting that it was found to be a bit too onerous in terms of
480     /// plumbing things around without a whole lot of benefit.
481     ///
482     /// In short, this works, but must be treated with care. The current main
483     /// user, bindings generation, treats this with care.
484     #[doc(hidden)]
485     pub fn with_data<D2: HasData>(&self, get_data: fn(&mut T) -> D2::Data<'_>) -> 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) =
1131             JoinHandle::run(async move { HostTaskOutput::Result(task.run(&accessor).await) });
1132         self.concurrent_state_mut(store.0)
1133             .push_future(Box::pin(async move {
1134                 future.await.unwrap_or(HostTaskOutput::Result(Ok(())))
1135             }));
1136 
1137         handle
1138     }
1139 
1140     /// Run this instance's event loop.
1141     ///
1142     /// The returned future will resolve when either the specified future
1143     /// completes (in which case we return its result) or no further progress
1144     /// can be made (in which case we trap with `Trap::AsyncDeadlock`).
1145     async fn poll_until<T, R>(
1146         self,
1147         mut store: StoreContextMut<'_, T>,
1148         mut future: Pin<&mut impl Future<Output = R>>,
1149     ) -> Result<R>
1150     where
1151         T: Send,
1152     {
1153         loop {
1154             // Take `ConcurrentState::futures` out of the instance so we can
1155             // poll it while also safely giving any of the futures inside access
1156             // to `self`.
1157             let mut futures = self
1158                 .concurrent_state_mut(store.0)
1159                 .futures
1160                 .get_mut()
1161                 .take()
1162                 .unwrap();
1163             let mut next = pin!(futures.next());
1164 
1165             let result = future::poll_fn(|cx| {
1166                 // First, poll the future we were passed as an argument and
1167                 // return immediately if it's ready.
1168                 if let Poll::Ready(value) = self.set_tls(store.0, || future.as_mut().poll(cx)) {
1169                     return Poll::Ready(Ok(Either::Left(value)));
1170                 }
1171 
1172                 // Next, poll `ConcurrentState::futures` (which includes any
1173                 // pending host tasks and/or background tasks), returning
1174                 // immediately if one of them fails.
1175                 let next = match self.set_tls(store.0, || next.as_mut().poll(cx)) {
1176                     Poll::Ready(Some(output)) => {
1177                         match output {
1178                             HostTaskOutput::Result(Err(e)) => return Poll::Ready(Err(e)),
1179                             HostTaskOutput::Result(Ok(())) => {}
1180                             HostTaskOutput::Function(fun) => {
1181                                 // Defer calling this function to a worker fiber
1182                                 // in case it involves calling a guest realloc
1183                                 // function as part of a lowering operation.
1184                                 //
1185                                 // TODO: This isn't necessary for _all_
1186                                 // `HostOutput::Function`s, so we could optimize
1187                                 // by adding another variant to `HostOutput` to
1188                                 // distinguish which ones need it and which
1189                                 // don't.
1190                                 self.concurrent_state_mut(store.0).push_high_priority(
1191                                     WorkItem::WorkerFunction(AlwaysMut::new(fun)),
1192                                 )
1193                             }
1194                         }
1195                         Poll::Ready(true)
1196                     }
1197                     Poll::Ready(None) => Poll::Ready(false),
1198                     Poll::Pending => Poll::Pending,
1199                 };
1200 
1201                 let mut instance = self.id().get_mut(store.0);
1202 
1203                 // Next, check the "high priority" work queue and return
1204                 // immediately if it has at least one item.
1205                 let state = instance.as_mut().concurrent_state_mut();
1206                 let ready = mem::take(&mut state.high_priority);
1207                 let ready = if ready.is_empty() {
1208                     // Next, check the "low priority" work queue and return
1209                     // immediately if it has at least one item.
1210                     let ready = mem::take(&mut state.low_priority);
1211                     if ready.is_empty() {
1212                         return match next {
1213                             Poll::Ready(true) => {
1214                                 // In this case, one of the futures in
1215                                 // `ConcurrentState::futures` completed
1216                                 // successfully, so we return now and continue
1217                                 // the outer loop in case there is another one
1218                                 // ready to complete.
1219                                 Poll::Ready(Ok(Either::Right(Vec::new())))
1220                             }
1221                             Poll::Ready(false) => {
1222                                 // Poll the future we were passed one last time
1223                                 // in case one of `ConcurrentState::futures` had
1224                                 // the side effect of unblocking it.
1225                                 if let Poll::Ready(value) =
1226                                     self.set_tls(store.0, || future.as_mut().poll(cx))
1227                                 {
1228                                     Poll::Ready(Ok(Either::Left(value)))
1229                                 } else {
1230                                     // In this case, there are no more pending
1231                                     // futures in `ConcurrentState::futures`,
1232                                     // there are no remaining work items, _and_
1233                                     // the future we were passed as an argument
1234                                     // still hasn't completed, meaning we're
1235                                     // stuck, so we return an error.  The
1236                                     // underlying assumption is that `future`
1237                                     // depends on this component instance making
1238                                     // such progress, and thus there's no point
1239                                     // in continuing to poll it given we've run
1240                                     // out of work to do.
1241                                     //
1242                                     // Note that we'd also reach this point if
1243                                     // the host embedder passed e.g. a
1244                                     // `std::future::Pending` to
1245                                     // `Instance::run_concurrent`, in which case
1246                                     // we'd return a "deadlock" error even when
1247                                     // any and all tasks have completed
1248                                     // normally.  However, that's not how
1249                                     // `Instance::run_concurrent` is intended
1250                                     // (and documented) to be used, so it seems
1251                                     // reasonable to lump that case in with
1252                                     // "real" deadlocks.
1253                                     //
1254                                     // TODO: Once we've added host APIs for
1255                                     // cancelling in-progress tasks, we can
1256                                     // return some other, non-error value here,
1257                                     // treating it as "normal" and giving the
1258                                     // host embedder a chance to intervene by
1259                                     // cancelling one or more tasks and/or
1260                                     // starting new tasks capable of waking the
1261                                     // existing ones.
1262                                     Poll::Ready(Err(anyhow!(crate::Trap::AsyncDeadlock)))
1263                                 }
1264                             }
1265                             // There is at least one pending future in
1266                             // `ConcurrentState::futures` and we have nothing
1267                             // else to do but wait for now, so we return
1268                             // `Pending`.
1269                             Poll::Pending => Poll::Pending,
1270                         };
1271                     } else {
1272                         ready
1273                     }
1274                 } else {
1275                     ready
1276                 };
1277 
1278                 Poll::Ready(Ok(Either::Right(ready)))
1279             })
1280             .await;
1281 
1282             // Put the `ConcurrentState::futures` back into the instance before
1283             // we return or handle any work items since one or more of those
1284             // items might append more futures.
1285             *self.concurrent_state_mut(store.0).futures.get_mut() = Some(futures);
1286 
1287             match result? {
1288                 // The future we were passed as an argument completed, so we
1289                 // return the result.
1290                 Either::Left(value) => break Ok(value),
1291                 // The future we were passed has not yet completed, so handle
1292                 // any work items and then loop again.
1293                 Either::Right(ready) => {
1294                     for item in ready {
1295                         self.handle_work_item(store.as_context_mut(), item).await?;
1296                     }
1297                 }
1298             }
1299         }
1300     }
1301 
1302     /// Handle the specified work item, possibly resuming a fiber if applicable.
1303     async fn handle_work_item<T: Send>(
1304         self,
1305         store: StoreContextMut<'_, T>,
1306         item: WorkItem,
1307     ) -> Result<()> {
1308         log::trace!("handle work item {item:?}");
1309         match item {
1310             WorkItem::PushFuture(future) => {
1311                 self.concurrent_state_mut(store.0)
1312                     .futures
1313                     .get_mut()
1314                     .as_mut()
1315                     .unwrap()
1316                     .push(future.into_inner());
1317             }
1318             WorkItem::ResumeFiber(fiber) => {
1319                 self.resume_fiber(store.0, fiber).await?;
1320             }
1321             WorkItem::GuestCall(call) => {
1322                 let state = self.concurrent_state_mut(store.0);
1323                 if call.is_ready(state)? {
1324                     self.run_on_worker(store, WorkerItem::GuestCall(call))
1325                         .await?;
1326                 } else {
1327                     let task = state.get_mut(call.task)?;
1328                     if !task.starting_sent {
1329                         task.starting_sent = true;
1330                         if let GuestCallKind::Start(_) = &call.kind {
1331                             Waitable::Guest(call.task).set_event(
1332                                 state,
1333                                 Some(Event::Subtask {
1334                                     status: Status::Starting,
1335                                 }),
1336                             )?;
1337                         }
1338                     }
1339 
1340                     let runtime_instance = state.get_mut(call.task)?.instance;
1341                     state
1342                         .instance_state(runtime_instance)
1343                         .pending
1344                         .insert(call.task, call.kind);
1345                 }
1346             }
1347             WorkItem::Poll(params) => {
1348                 let state = self.concurrent_state_mut(store.0);
1349                 if state.get_mut(params.task)?.event.is_some()
1350                     || !state.get_mut(params.set)?.ready.is_empty()
1351                 {
1352                     // There's at least one event immediately available; deliver
1353                     // it to the guest ASAP.
1354                     state.push_high_priority(WorkItem::GuestCall(GuestCall {
1355                         task: params.task,
1356                         kind: GuestCallKind::DeliverEvent {
1357                             set: Some(params.set),
1358                         },
1359                     }));
1360                 } else {
1361                     // There are no events immediately available; deliver
1362                     // `Event::None` to the guest.
1363                     state.get_mut(params.task)?.event = Some(Event::None);
1364                     state.push_high_priority(WorkItem::GuestCall(GuestCall {
1365                         task: params.task,
1366                         kind: GuestCallKind::DeliverEvent {
1367                             set: Some(params.set),
1368                         },
1369                     }));
1370                 }
1371             }
1372             WorkItem::WorkerFunction(fun) => {
1373                 self.run_on_worker(store, WorkerItem::Function(fun)).await?;
1374             }
1375         }
1376 
1377         Ok(())
1378     }
1379 
1380     /// Resume the specified fiber, giving it exclusive access to the specified
1381     /// store.
1382     async fn resume_fiber(self, store: &mut StoreOpaque, fiber: StoreFiber<'static>) -> Result<()> {
1383         let old_task = self.concurrent_state_mut(store).guest_task;
1384         log::trace!("resume_fiber: save current task {old_task:?}");
1385 
1386         let fiber = fiber::resolve_or_release(store, fiber).await?;
1387 
1388         let state = self.concurrent_state_mut(store);
1389 
1390         state.guest_task = old_task;
1391         log::trace!("resume_fiber: restore current task {old_task:?}");
1392 
1393         if let Some(mut fiber) = fiber {
1394             // See the `SuspendReason` documentation for what each case means.
1395             match state.suspend_reason.take().unwrap() {
1396                 SuspendReason::NeedWork => {
1397                     if state.worker.is_none() {
1398                         state.worker = Some(fiber);
1399                     } else {
1400                         fiber.dispose(store);
1401                     }
1402                 }
1403                 SuspendReason::Yielding { .. } => {
1404                     state.push_low_priority(WorkItem::ResumeFiber(fiber));
1405                 }
1406                 SuspendReason::Waiting { set, task } => {
1407                     let old = state
1408                         .get_mut(set)?
1409                         .waiting
1410                         .insert(task, WaitMode::Fiber(fiber));
1411                     assert!(old.is_none());
1412                 }
1413             }
1414         }
1415 
1416         Ok(())
1417     }
1418 
1419     /// Execute the specified guest call on a worker fiber.
1420     async fn run_on_worker<T: Send>(
1421         self,
1422         store: StoreContextMut<'_, T>,
1423         item: WorkerItem,
1424     ) -> Result<()> {
1425         let worker = if let Some(fiber) = self.concurrent_state_mut(store.0).worker.take() {
1426             fiber
1427         } else {
1428             fiber::make_fiber(store.0, move |store| {
1429                 loop {
1430                     match self.concurrent_state_mut(store).worker_item.take().unwrap() {
1431                         WorkerItem::GuestCall(call) => self.handle_guest_call(store, call)?,
1432                         WorkerItem::Function(fun) => fun.into_inner()(store, self)?,
1433                     }
1434 
1435                     self.suspend(store, SuspendReason::NeedWork)?;
1436                 }
1437             })?
1438         };
1439 
1440         let worker_item = &mut self.concurrent_state_mut(store.0).worker_item;
1441         assert!(worker_item.is_none());
1442         *worker_item = Some(item);
1443 
1444         self.resume_fiber(store.0, worker).await
1445     }
1446 
1447     /// Execute the specified guest call.
1448     fn handle_guest_call(self, store: &mut dyn VMStore, call: GuestCall) -> Result<()> {
1449         match call.kind {
1450             GuestCallKind::DeliverEvent { set } => {
1451                 let (event, waitable) =
1452                     self.id().get_mut(store).get_event(call.task, set)?.unwrap();
1453                 let state = self.concurrent_state_mut(store);
1454                 let task = state.get_mut(call.task)?;
1455                 let runtime_instance = task.instance;
1456                 let handle = waitable.map(|(_, v)| v).unwrap_or(0);
1457 
1458                 log::trace!(
1459                     "use callback to deliver event {event:?} to {:?} for {waitable:?}",
1460                     call.task,
1461                 );
1462 
1463                 let old_task = state.guest_task.replace(call.task);
1464                 log::trace!(
1465                     "GuestCallKind::DeliverEvent: replaced {old_task:?} with {:?} as current task",
1466                     call.task
1467                 );
1468 
1469                 self.maybe_push_call_context(store.store_opaque_mut(), call.task)?;
1470 
1471                 let state = self.concurrent_state_mut(store);
1472                 state.enter_instance(runtime_instance);
1473 
1474                 let callback = state.get_mut(call.task)?.callback.take().unwrap();
1475 
1476                 let code = callback(store, self, runtime_instance, event, handle)?;
1477 
1478                 let state = self.concurrent_state_mut(store);
1479 
1480                 state.get_mut(call.task)?.callback = Some(callback);
1481 
1482                 state.exit_instance(runtime_instance)?;
1483 
1484                 self.maybe_pop_call_context(store.store_opaque_mut(), call.task)?;
1485 
1486                 self.id().get_mut(store).handle_callback_code(
1487                     call.task,
1488                     runtime_instance,
1489                     code,
1490                     false,
1491                 )?;
1492 
1493                 self.concurrent_state_mut(store).guest_task = old_task;
1494                 log::trace!("GuestCallKind::DeliverEvent: restored {old_task:?} as current task");
1495             }
1496             GuestCallKind::Start(fun) => {
1497                 fun(store, self)?;
1498             }
1499         }
1500 
1501         Ok(())
1502     }
1503 
1504     /// Suspend the current fiber, storing the reason in
1505     /// `ConcurrentState::suspend_reason` to indicate the conditions under which
1506     /// it should be resumed.
1507     ///
1508     /// See the `SuspendReason` documentation for details.
1509     fn suspend(self, store: &mut dyn VMStore, reason: SuspendReason) -> Result<()> {
1510         log::trace!("suspend fiber: {reason:?}");
1511 
1512         // If we're yielding or waiting on behalf of a guest task, we'll need to
1513         // pop the call context which manages resource borrows before suspending
1514         // and then push it again once we've resumed.
1515         let task = match &reason {
1516             SuspendReason::Yielding { task } | SuspendReason::Waiting { task, .. } => Some(*task),
1517             SuspendReason::NeedWork => None,
1518         };
1519 
1520         let old_guest_task = if let Some(task) = task {
1521             self.maybe_pop_call_context(store, task)?;
1522             self.concurrent_state_mut(store).guest_task
1523         } else {
1524             None
1525         };
1526 
1527         let suspend_reason = &mut self.concurrent_state_mut(store).suspend_reason;
1528         assert!(suspend_reason.is_none());
1529         *suspend_reason = Some(reason);
1530 
1531         store.with_blocking(|_, cx| cx.suspend(StoreFiberYield::ReleaseStore))?;
1532 
1533         if let Some(task) = task {
1534             self.concurrent_state_mut(store).guest_task = old_guest_task;
1535             self.maybe_push_call_context(store, task)?;
1536         }
1537 
1538         Ok(())
1539     }
1540 
1541     /// Push 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_push_call_context(
1545         self,
1546         store: &mut StoreOpaque,
1547         guest_task: TableId<GuestTask>,
1548     ) -> Result<()> {
1549         let task = self.concurrent_state_mut(store).get_mut(guest_task)?;
1550         if task.lift_result.is_some() {
1551             log::trace!("push call context for {guest_task:?}");
1552             let call_context = task.call_context.take().unwrap();
1553             store.component_resource_state().0.push(call_context);
1554         }
1555         Ok(())
1556     }
1557 
1558     /// Pop the call context for managing resource borrows for the specified
1559     /// guest task if it has not yet either returned a result or cancelled
1560     /// itself.
1561     fn maybe_pop_call_context(
1562         self,
1563         store: &mut StoreOpaque,
1564         guest_task: TableId<GuestTask>,
1565     ) -> Result<()> {
1566         if self
1567             .concurrent_state_mut(store)
1568             .get_mut(guest_task)?
1569             .lift_result
1570             .is_some()
1571         {
1572             log::trace!("pop call context for {guest_task:?}");
1573             let call_context = Some(store.component_resource_state().0.pop().unwrap());
1574             self.concurrent_state_mut(store)
1575                 .get_mut(guest_task)?
1576                 .call_context = call_context;
1577         }
1578         Ok(())
1579     }
1580 
1581     /// Add the specified guest call to the "high priority" work item queue, to
1582     /// be started as soon as backpressure and/or reentrance rules allow.
1583     ///
1584     /// SAFETY: The raw pointer arguments must be valid references to guest
1585     /// functions (with the appropriate signatures) when the closures queued by
1586     /// this function are called.
1587     unsafe fn queue_call<T: 'static>(
1588         self,
1589         mut store: StoreContextMut<T>,
1590         guest_task: TableId<GuestTask>,
1591         callee: SendSyncPtr<VMFuncRef>,
1592         param_count: usize,
1593         result_count: usize,
1594         flags: Option<InstanceFlags>,
1595         async_: bool,
1596         callback: Option<SendSyncPtr<VMFuncRef>>,
1597         post_return: Option<SendSyncPtr<VMFuncRef>>,
1598     ) -> Result<()> {
1599         /// Return a closure which will call the specified function in the scope
1600         /// of the specified task.
1601         ///
1602         /// This will use `GuestTask::lower_params` to lower the parameters, but
1603         /// will not lift the result; instead, it returns a
1604         /// `[MaybeUninit<ValRaw>; MAX_FLAT_PARAMS]` from which the result, if
1605         /// any, may be lifted.  Note that an async-lifted export will have
1606         /// returned its result using the `task.return` intrinsic (or not
1607         /// returned a result at all, in the case of `task.cancel`), in which
1608         /// case the "result" of this call will either be a callback code or
1609         /// nothing.
1610         ///
1611         /// SAFETY: `callee` must be a valid `*mut VMFuncRef` at the time when
1612         /// the returned closure is called.
1613         unsafe fn make_call<T: 'static>(
1614             store: StoreContextMut<T>,
1615             guest_task: TableId<GuestTask>,
1616             callee: SendSyncPtr<VMFuncRef>,
1617             param_count: usize,
1618             result_count: usize,
1619             flags: Option<InstanceFlags>,
1620         ) -> impl FnOnce(
1621             &mut dyn VMStore,
1622             Instance,
1623         ) -> Result<[MaybeUninit<ValRaw>; MAX_FLAT_PARAMS]>
1624         + Send
1625         + Sync
1626         + 'static
1627         + use<T> {
1628             let token = StoreToken::new(store);
1629             move |store: &mut dyn VMStore, instance: Instance| {
1630                 let mut storage = [MaybeUninit::uninit(); MAX_FLAT_PARAMS];
1631                 let task = instance.concurrent_state_mut(store).get_mut(guest_task)?;
1632                 let may_enter_after_call = task.call_post_return_automatically();
1633                 let lower = task.lower_params.take().unwrap();
1634 
1635                 lower(store, instance, &mut storage[..param_count])?;
1636 
1637                 let mut store = token.as_context_mut(store);
1638 
1639                 // SAFETY: Per the contract documented in `make_call's`
1640                 // documentation, `callee` must be a valid pointer.
1641                 unsafe {
1642                     if let Some(mut flags) = flags {
1643                         flags.set_may_enter(false);
1644                     }
1645                     crate::Func::call_unchecked_raw(
1646                         &mut store,
1647                         callee.as_non_null(),
1648                         NonNull::new(
1649                             &mut storage[..param_count.max(result_count)]
1650                                 as *mut [MaybeUninit<ValRaw>] as _,
1651                         )
1652                         .unwrap(),
1653                     )?;
1654                     if let Some(mut flags) = flags {
1655                         flags.set_may_enter(may_enter_after_call);
1656                     }
1657                 }
1658 
1659                 Ok(storage)
1660             }
1661         }
1662 
1663         // SAFETY: Per the contract described in this function documentation,
1664         // the `callee` pointer which `call` closes over must be valid when
1665         // called by the closure we queue below.
1666         let call = unsafe {
1667             make_call(
1668                 store.as_context_mut(),
1669                 guest_task,
1670                 callee,
1671                 param_count,
1672                 result_count,
1673                 flags,
1674             )
1675         };
1676 
1677         let callee_instance = self
1678             .concurrent_state_mut(store.0)
1679             .get_mut(guest_task)?
1680             .instance;
1681         let fun = if callback.is_some() {
1682             assert!(async_);
1683 
1684             Box::new(move |store: &mut dyn VMStore, instance: Instance| {
1685                 let old_task = instance
1686                     .concurrent_state_mut(store)
1687                     .guest_task
1688                     .replace(guest_task);
1689                 log::trace!(
1690                     "stackless call: replaced {old_task:?} with {guest_task:?} as current task"
1691                 );
1692 
1693                 instance.maybe_push_call_context(store.store_opaque_mut(), guest_task)?;
1694 
1695                 instance
1696                     .concurrent_state_mut(store)
1697                     .enter_instance(callee_instance);
1698 
1699                 // SAFETY: See the documentation for `make_call` to review the
1700                 // contract we must uphold for `call` here.
1701                 //
1702                 // Per the contract described in the `queue_call`
1703                 // documentation, the `callee` pointer which `call` closes
1704                 // over must be valid.
1705                 let storage = call(store, instance)?;
1706 
1707                 instance
1708                     .concurrent_state_mut(store)
1709                     .exit_instance(callee_instance)?;
1710 
1711                 instance.maybe_pop_call_context(store.store_opaque_mut(), guest_task)?;
1712 
1713                 let state = instance.concurrent_state_mut(store);
1714                 state.guest_task = old_task;
1715                 log::trace!("stackless call: restored {old_task:?} as current task");
1716 
1717                 // SAFETY: `wasmparser` will have validated that the callback
1718                 // function returns a `i32` result.
1719                 let code = unsafe { storage[0].assume_init() }.get_i32() as u32;
1720 
1721                 instance.id().get_mut(store).handle_callback_code(
1722                     guest_task,
1723                     callee_instance,
1724                     code,
1725                     true,
1726                 )?;
1727 
1728                 Ok(())
1729             })
1730                 as Box<dyn FnOnce(&mut dyn VMStore, Instance) -> Result<()> + Send + Sync>
1731         } else {
1732             let token = StoreToken::new(store.as_context_mut());
1733             Box::new(move |store: &mut dyn VMStore, instance: Instance| {
1734                 let old_task = instance
1735                     .concurrent_state_mut(store)
1736                     .guest_task
1737                     .replace(guest_task);
1738                 log::trace!(
1739                     "stackful call: replaced {old_task:?} with {guest_task:?} as current task",
1740                 );
1741 
1742                 let mut flags = instance.id().get(store).instance_flags(callee_instance);
1743 
1744                 instance.maybe_push_call_context(store.store_opaque_mut(), guest_task)?;
1745 
1746                 // Unless this is a callback-less (i.e. stackful)
1747                 // async-lifted export, we need to record that the instance
1748                 // cannot be entered until the call returns.
1749                 if !async_ {
1750                     instance
1751                         .concurrent_state_mut(store)
1752                         .enter_instance(callee_instance);
1753                 }
1754 
1755                 // SAFETY: See the documentation for `make_call` to review the
1756                 // contract we must uphold for `call` here.
1757                 //
1758                 // Per the contract described in the `queue_call`
1759                 // documentation, the `callee` pointer which `call` closes
1760                 // over must be valid.
1761                 let storage = call(store, instance)?;
1762 
1763                 if async_ {
1764                     // This is a callback-less (i.e. stackful) async-lifted
1765                     // export, so there is no post-return function, and
1766                     // either `task.return` or `task.cancel` should have
1767                     // been called.
1768                     if instance
1769                         .concurrent_state_mut(store)
1770                         .get_mut(guest_task)?
1771                         .lift_result
1772                         .is_some()
1773                     {
1774                         return Err(anyhow!(crate::Trap::NoAsyncResult));
1775                     }
1776                 } else {
1777                     // This is a sync-lifted export, so now is when we lift the
1778                     // result, optionally call the post-return function, if any,
1779                     // and finally notify any current or future waiters that the
1780                     // subtask has returned.
1781 
1782                     let lift = {
1783                         let state = instance.concurrent_state_mut(store);
1784                         state.exit_instance(callee_instance)?;
1785 
1786                         assert!(state.get_mut(guest_task)?.result.is_none());
1787 
1788                         state.get_mut(guest_task)?.lift_result.take().unwrap()
1789                     };
1790 
1791                     // SAFETY: `result_count` represents the number of core Wasm
1792                     // results returned, per `wasmparser`.
1793                     let result = (lift.lift)(store, instance, unsafe {
1794                         mem::transmute::<&[MaybeUninit<ValRaw>], &[ValRaw]>(
1795                             &storage[..result_count],
1796                         )
1797                     })?;
1798 
1799                     let post_return_arg = match result_count {
1800                         0 => ValRaw::i32(0),
1801                         // SAFETY: `result_count` represents the number of
1802                         // core Wasm results returned, per `wasmparser`.
1803                         1 => unsafe { storage[0].assume_init() },
1804                         _ => unreachable!(),
1805                     };
1806 
1807                     if instance
1808                         .concurrent_state_mut(store)
1809                         .get_mut(guest_task)?
1810                         .call_post_return_automatically()
1811                     {
1812                         unsafe { flags.set_needs_post_return(false) }
1813 
1814                         if let Some(func) = post_return {
1815                             let mut store = token.as_context_mut(store);
1816 
1817                             // SAFETY: `func` is a valid `*mut VMFuncRef` from
1818                             // either `wasmtime-cranelift`-generated fused adapter
1819                             // code or `component::Options`.  Per `wasmparser`
1820                             // post-return signature validation, we know it takes a
1821                             // single parameter.
1822                             unsafe {
1823                                 crate::Func::call_unchecked_raw(
1824                                     &mut store,
1825                                     func.as_non_null(),
1826                                     slice::from_ref(&post_return_arg).into(),
1827                                 )?;
1828                             }
1829                         }
1830 
1831                         unsafe { flags.set_may_enter(true) }
1832                     }
1833 
1834                     instance.task_complete(
1835                         store,
1836                         guest_task,
1837                         result,
1838                         Status::Returned,
1839                         post_return_arg,
1840                     )?;
1841                 }
1842 
1843                 instance.maybe_pop_call_context(store.store_opaque_mut(), guest_task)?;
1844 
1845                 let task = instance.concurrent_state_mut(store).get_mut(guest_task)?;
1846 
1847                 match &task.caller {
1848                     Caller::Host {
1849                         remove_task_automatically,
1850                         ..
1851                     } => {
1852                         if *remove_task_automatically {
1853                             Waitable::Guest(guest_task)
1854                                 .delete_from(instance.concurrent_state_mut(store))?;
1855                         }
1856                     }
1857                     Caller::Guest { .. } => {
1858                         task.exited = true;
1859                     }
1860                 }
1861 
1862                 Ok(())
1863             })
1864         };
1865 
1866         self.concurrent_state_mut(store.0)
1867             .push_high_priority(WorkItem::GuestCall(GuestCall {
1868                 task: guest_task,
1869                 kind: GuestCallKind::Start(fun),
1870             }));
1871 
1872         Ok(())
1873     }
1874 
1875     /// Prepare (but do not start) a guest->guest call.
1876     ///
1877     /// This is called from fused adapter code generated in
1878     /// `wasmtime_environ::fact::trampoline::Compiler`.  `start` and `return_`
1879     /// are synthesized Wasm functions which move the parameters from the caller
1880     /// to the callee and the result from the callee to the caller,
1881     /// respectively.  The adapter will call `Self::start_call` immediately
1882     /// after calling this function.
1883     ///
1884     /// SAFETY: All the pointer arguments must be valid pointers to guest
1885     /// entities (and with the expected signatures for the function references
1886     /// -- see `wasmtime_environ::fact::trampoline::Compiler` for details).
1887     unsafe fn prepare_call<T: 'static>(
1888         self,
1889         mut store: StoreContextMut<T>,
1890         start: *mut VMFuncRef,
1891         return_: *mut VMFuncRef,
1892         caller_instance: RuntimeComponentInstanceIndex,
1893         callee_instance: RuntimeComponentInstanceIndex,
1894         task_return_type: TypeTupleIndex,
1895         memory: *mut VMMemoryDefinition,
1896         string_encoding: u8,
1897         caller_info: CallerInfo,
1898     ) -> Result<()> {
1899         enum ResultInfo {
1900             Heap { results: u32 },
1901             Stack { result_count: u32 },
1902         }
1903 
1904         let result_info = match &caller_info {
1905             CallerInfo::Async {
1906                 has_result: true,
1907                 params,
1908             } => ResultInfo::Heap {
1909                 results: params.last().unwrap().get_u32(),
1910             },
1911             CallerInfo::Async {
1912                 has_result: false, ..
1913             } => ResultInfo::Stack { result_count: 0 },
1914             CallerInfo::Sync {
1915                 result_count,
1916                 params,
1917             } if *result_count > u32::try_from(MAX_FLAT_RESULTS).unwrap() => ResultInfo::Heap {
1918                 results: params.last().unwrap().get_u32(),
1919             },
1920             CallerInfo::Sync { result_count, .. } => ResultInfo::Stack {
1921                 result_count: *result_count,
1922             },
1923         };
1924 
1925         let sync_caller = matches!(caller_info, CallerInfo::Sync { .. });
1926 
1927         // Create a new guest task for the call, closing over the `start` and
1928         // `return_` functions to lift the parameters and lower the result,
1929         // respectively.
1930         let start = SendSyncPtr::new(NonNull::new(start).unwrap());
1931         let return_ = SendSyncPtr::new(NonNull::new(return_).unwrap());
1932         let token = StoreToken::new(store.as_context_mut());
1933         let state = self.concurrent_state_mut(store.0);
1934         let old_task = state.guest_task.take();
1935         let new_task = GuestTask::new(
1936             state,
1937             Box::new(move |store, instance, dst| {
1938                 let mut store = token.as_context_mut(store);
1939                 assert!(dst.len() <= MAX_FLAT_PARAMS);
1940                 let mut src = [MaybeUninit::uninit(); MAX_FLAT_PARAMS];
1941                 let count = match caller_info {
1942                     // Async callers, if they have a result, use the last
1943                     // parameter as a return pointer so chop that off if
1944                     // relevant here.
1945                     CallerInfo::Async { params, has_result } => {
1946                         let params = &params[..params.len() - usize::from(has_result)];
1947                         for (param, src) in params.iter().zip(&mut src) {
1948                             src.write(*param);
1949                         }
1950                         params.len()
1951                     }
1952 
1953                     // Sync callers forward everything directly.
1954                     CallerInfo::Sync { params, .. } => {
1955                         for (param, src) in params.iter().zip(&mut src) {
1956                             src.write(*param);
1957                         }
1958                         params.len()
1959                     }
1960                 };
1961                 // SAFETY: `start` is a valid `*mut VMFuncRef` from
1962                 // `wasmtime-cranelift`-generated fused adapter code.  Based on
1963                 // how it was constructed (see
1964                 // `wasmtime_environ::fact::trampoline::Compiler::compile_async_start_adapter`
1965                 // for details) we know it takes count parameters and returns
1966                 // `dst.len()` results.
1967                 unsafe {
1968                     crate::Func::call_unchecked_raw(
1969                         &mut store,
1970                         start.as_non_null(),
1971                         NonNull::new(
1972                             &mut src[..count.max(dst.len())] as *mut [MaybeUninit<ValRaw>] as _,
1973                         )
1974                         .unwrap(),
1975                     )?;
1976                 }
1977                 dst.copy_from_slice(&src[..dst.len()]);
1978                 let state = instance.concurrent_state_mut(store.0);
1979                 let task = state.guest_task.unwrap();
1980                 Waitable::Guest(task).set_event(
1981                     state,
1982                     Some(Event::Subtask {
1983                         status: Status::Started,
1984                     }),
1985                 )?;
1986                 Ok(())
1987             }),
1988             LiftResult {
1989                 lift: Box::new(move |store, instance, src| {
1990                     // SAFETY: See comment in closure passed as `lower_params`
1991                     // parameter above.
1992                     let mut store = token.as_context_mut(store);
1993                     let mut my_src = src.to_owned(); // TODO: use stack to avoid allocation?
1994                     if let ResultInfo::Heap { results } = &result_info {
1995                         my_src.push(ValRaw::u32(*results));
1996                     }
1997                     // SAFETY: `return_` is a valid `*mut VMFuncRef` from
1998                     // `wasmtime-cranelift`-generated fused adapter code.  Based
1999                     // on how it was constructed (see
2000                     // `wasmtime_environ::fact::trampoline::Compiler::compile_async_return_adapter`
2001                     // for details) we know it takes `src.len()` parameters and
2002                     // returns up to 1 result.
2003                     unsafe {
2004                         crate::Func::call_unchecked_raw(
2005                             &mut store,
2006                             return_.as_non_null(),
2007                             my_src.as_mut_slice().into(),
2008                         )?;
2009                     }
2010                     let state = instance.concurrent_state_mut(store.0);
2011                     let task = state.guest_task.unwrap();
2012                     if sync_caller {
2013                         state.get_mut(task)?.sync_result =
2014                             Some(if let ResultInfo::Stack { result_count } = &result_info {
2015                                 match result_count {
2016                                     0 => None,
2017                                     1 => Some(my_src[0]),
2018                                     _ => unreachable!(),
2019                                 }
2020                             } else {
2021                                 None
2022                             });
2023                     }
2024                     Ok(Box::new(DummyResult) as Box<dyn Any + Send + Sync>)
2025                 }),
2026                 ty: task_return_type,
2027                 memory: NonNull::new(memory).map(SendSyncPtr::new),
2028                 string_encoding: StringEncoding::from_u8(string_encoding).unwrap(),
2029             },
2030             Caller::Guest {
2031                 task: old_task.unwrap(),
2032                 instance: caller_instance,
2033             },
2034             None,
2035             callee_instance,
2036         )?;
2037 
2038         let guest_task = state.push(new_task)?;
2039 
2040         if let Some(old_task) = old_task {
2041             if !state.may_enter(guest_task) {
2042                 bail!(crate::Trap::CannotEnterComponent);
2043             }
2044 
2045             state.get_mut(old_task)?.subtasks.insert(guest_task);
2046         };
2047 
2048         // Make the new task the current one so that `Self::start_call` knows
2049         // which one to start.
2050         state.guest_task = Some(guest_task);
2051         log::trace!("pushed {guest_task:?} as current task; old task was {old_task:?}");
2052 
2053         Ok(())
2054     }
2055 
2056     /// Call the specified callback function for an async-lifted export.
2057     ///
2058     /// SAFETY: `function` must be a valid reference to a guest function of the
2059     /// correct signature for a callback.
2060     unsafe fn call_callback<T>(
2061         self,
2062         mut store: StoreContextMut<T>,
2063         callee_instance: RuntimeComponentInstanceIndex,
2064         function: SendSyncPtr<VMFuncRef>,
2065         event: Event,
2066         handle: u32,
2067         may_enter_after_call: bool,
2068     ) -> Result<u32> {
2069         let mut flags = self.id().get(store.0).instance_flags(callee_instance);
2070 
2071         let (ordinal, result) = event.parts();
2072         let params = &mut [
2073             ValRaw::u32(ordinal),
2074             ValRaw::u32(handle),
2075             ValRaw::u32(result),
2076         ];
2077         // SAFETY: `func` is a valid `*mut VMFuncRef` from either
2078         // `wasmtime-cranelift`-generated fused adapter code or
2079         // `component::Options`.  Per `wasmparser` callback signature
2080         // validation, we know it takes three parameters and returns one.
2081         unsafe {
2082             flags.set_may_enter(false);
2083             crate::Func::call_unchecked_raw(
2084                 &mut store,
2085                 function.as_non_null(),
2086                 params.as_mut_slice().into(),
2087             )?;
2088             flags.set_may_enter(may_enter_after_call);
2089         }
2090         Ok(params[0].get_u32())
2091     }
2092 
2093     /// Start a guest->guest call previously prepared using
2094     /// `Self::prepare_call`.
2095     ///
2096     /// This is called from fused adapter code generated in
2097     /// `wasmtime_environ::fact::trampoline::Compiler`.  The adapter will call
2098     /// this function immediately after calling `Self::prepare_call`.
2099     ///
2100     /// SAFETY: The `*mut VMFuncRef` arguments must be valid pointers to guest
2101     /// functions with the appropriate signatures for the current guest task.
2102     /// If this is a call to an async-lowered import, the actual call may be
2103     /// deferred and run after this function returns, in which case the pointer
2104     /// arguments must also be valid when the call happens.
2105     unsafe fn start_call<T: 'static>(
2106         self,
2107         mut store: StoreContextMut<T>,
2108         callback: *mut VMFuncRef,
2109         post_return: *mut VMFuncRef,
2110         callee: *mut VMFuncRef,
2111         param_count: u32,
2112         result_count: u32,
2113         flags: u32,
2114         storage: Option<&mut [MaybeUninit<ValRaw>]>,
2115     ) -> Result<u32> {
2116         let token = StoreToken::new(store.as_context_mut());
2117         let async_caller = storage.is_none();
2118         let state = self.concurrent_state_mut(store.0);
2119         let guest_task = state.guest_task.unwrap();
2120         let may_enter_after_call = state.get_mut(guest_task)?.call_post_return_automatically();
2121         let callee = SendSyncPtr::new(NonNull::new(callee).unwrap());
2122         let param_count = usize::try_from(param_count).unwrap();
2123         assert!(param_count <= MAX_FLAT_PARAMS);
2124         let result_count = usize::try_from(result_count).unwrap();
2125         assert!(result_count <= MAX_FLAT_RESULTS);
2126 
2127         let task = state.get_mut(guest_task)?;
2128         if !callback.is_null() {
2129             // We're calling an async-lifted export with a callback, so store
2130             // the callback and related context as part of the task so we can
2131             // call it later when needed.
2132             let callback = SendSyncPtr::new(NonNull::new(callback).unwrap());
2133             task.callback = Some(Box::new(
2134                 move |store, instance, runtime_instance, event, handle| {
2135                     let store = token.as_context_mut(store);
2136                     unsafe {
2137                         instance.call_callback::<T>(
2138                             store,
2139                             runtime_instance,
2140                             callback,
2141                             event,
2142                             handle,
2143                             may_enter_after_call,
2144                         )
2145                     }
2146                 },
2147             ));
2148         }
2149 
2150         let Caller::Guest {
2151             task: caller,
2152             instance: runtime_instance,
2153         } = &task.caller
2154         else {
2155             // As of this writing, `start_call` is only used for guest->guest
2156             // calls.
2157             unreachable!()
2158         };
2159         let caller = *caller;
2160         let caller_instance = *runtime_instance;
2161 
2162         let callee_instance = task.instance;
2163 
2164         let instance_flags = if callback.is_null() {
2165             None
2166         } else {
2167             Some(self.id().get(store.0).instance_flags(callee_instance))
2168         };
2169 
2170         // Queue the call as a "high priority" work item.
2171         unsafe {
2172             self.queue_call(
2173                 store.as_context_mut(),
2174                 guest_task,
2175                 callee,
2176                 param_count,
2177                 result_count,
2178                 instance_flags,
2179                 (flags & START_FLAG_ASYNC_CALLEE) != 0,
2180                 NonNull::new(callback).map(SendSyncPtr::new),
2181                 NonNull::new(post_return).map(SendSyncPtr::new),
2182             )?;
2183         }
2184 
2185         let state = self.concurrent_state_mut(store.0);
2186 
2187         // Use the caller's `GuestTask::sync_call_set` to register interest in
2188         // the subtask...
2189         let guest_waitable = Waitable::Guest(guest_task);
2190         let old_set = guest_waitable.common(state)?.set;
2191         let set = state.get_mut(caller)?.sync_call_set;
2192         guest_waitable.join(state, Some(set))?;
2193 
2194         // ... and suspend this fiber temporarily while we wait for it to start.
2195         //
2196         // Note that we _could_ call the callee directly using the current fiber
2197         // rather than suspend this one, but that would make reasoning about the
2198         // event loop more complicated and is probably only worth doing if
2199         // there's a measurable performance benefit.  In addition, it would mean
2200         // blocking the caller if the callee calls a blocking sync-lowered
2201         // import, and as of this writing the spec says we must not do that.
2202         //
2203         // Alternatively, the fused adapter code could be modified to call the
2204         // callee directly without calling a host-provided intrinsic at all (in
2205         // which case it would need to do its own, inline backpressure checks,
2206         // etc.).  Again, we'd want to see a measurable performance benefit
2207         // before committing to such an optimization.  And again, we'd need to
2208         // update the spec to allow that.
2209         let (status, waitable) = loop {
2210             self.suspend(store.0, SuspendReason::Waiting { set, task: caller })?;
2211 
2212             let state = self.concurrent_state_mut(store.0);
2213 
2214             let event = guest_waitable.take_event(state)?;
2215             let Some(Event::Subtask { status }) = event else {
2216                 unreachable!();
2217             };
2218 
2219             log::trace!("status {status:?} for {guest_task:?}");
2220 
2221             if status == Status::Returned {
2222                 // It returned, so we can stop waiting.
2223                 break (status, None);
2224             } else if async_caller {
2225                 // It hasn't returned yet, but the caller is calling via an
2226                 // async-lowered import, so we generate a handle for the task
2227                 // waitable and return the status.
2228                 let handle = self.id().get_mut(store.0).guest_tables().0[caller_instance]
2229                     .subtask_insert_guest(guest_task.rep())?;
2230                 self.concurrent_state_mut(store.0)
2231                     .get_mut(guest_task)?
2232                     .common
2233                     .handle = Some(handle);
2234                 break (status, Some(handle));
2235             } else {
2236                 // The callee hasn't returned yet, and the caller is calling via
2237                 // a sync-lowered import, so we loop and keep waiting until the
2238                 // callee returns.
2239             }
2240         };
2241 
2242         let state = self.concurrent_state_mut(store.0);
2243 
2244         guest_waitable.join(state, old_set)?;
2245 
2246         if let Some(storage) = storage {
2247             // The caller used a sync-lowered import to call an async-lifted
2248             // export, in which case the result, if any, has been stashed in
2249             // `GuestTask::sync_result`.
2250             if let Some(result) = state.get_mut(guest_task)?.sync_result.take() {
2251                 if let Some(result) = result {
2252                     storage[0] = MaybeUninit::new(result);
2253                 }
2254 
2255                 Waitable::Guest(guest_task).delete_from(state)?;
2256             } else {
2257                 // This means the callee failed to call either `task.return` or
2258                 // `task.cancel` before exiting.
2259                 return Err(anyhow!(crate::Trap::NoAsyncResult));
2260             }
2261         }
2262 
2263         // Reset the current task to point to the caller as it resumes control.
2264         state.guest_task = Some(caller);
2265         log::trace!("popped current task {guest_task:?}; new task is {caller:?}");
2266 
2267         Ok(status.pack(waitable))
2268     }
2269 
2270     /// Wrap the specified host function in a future which will call it, passing
2271     /// it an `&Accessor<T>`.
2272     ///
2273     /// See the `Accessor` documentation for details.
2274     pub(crate) fn wrap_call<T, F, R>(
2275         self,
2276         store: StoreContextMut<T>,
2277         closure: F,
2278     ) -> impl Future<Output = Result<R>> + 'static
2279     where
2280         T: 'static,
2281         F: FnOnce(&Accessor<T>) -> Pin<Box<dyn Future<Output = Result<R>> + Send + '_>>
2282             + Send
2283             + Sync
2284             + 'static,
2285         R: Send + Sync + 'static,
2286     {
2287         let token = StoreToken::new(store);
2288         async move {
2289             let mut accessor = Accessor::new(token, Some(self));
2290             closure(&mut accessor).await
2291         }
2292     }
2293 
2294     /// Poll the specified future once on behalf of a guest->host call using an
2295     /// async-lowered import.
2296     ///
2297     /// If it returns `Ready`, return `Ok(None)`.  Otherwise, if it returns
2298     /// `Pending`, add it to the set of futures to be polled as part of this
2299     /// instance's event loop until it completes, and then return
2300     /// `Ok(Some(handle))` where `handle` is the waitable handle to return.
2301     ///
2302     /// Whether the future returns `Ready` immediately or later, the `lower`
2303     /// function will be used to lower the result, if any, into the guest caller's
2304     /// stack and linear memory unless the task has been cancelled.
2305     pub(crate) fn first_poll<T: 'static, R: Send + 'static>(
2306         self,
2307         mut store: StoreContextMut<T>,
2308         future: impl Future<Output = Result<R>> + Send + 'static,
2309         caller_instance: RuntimeComponentInstanceIndex,
2310         lower: impl FnOnce(StoreContextMut<T>, Instance, R) -> Result<()> + Send + 'static,
2311     ) -> Result<Option<u32>> {
2312         let token = StoreToken::new(store.as_context_mut());
2313         let state = self.concurrent_state_mut(store.0);
2314         let caller = state.guest_task.unwrap();
2315 
2316         // Create an abortable future which hooks calls to poll and manages call
2317         // context state for the future.
2318         let (join_handle, future) = JoinHandle::run(async move {
2319             let mut future = pin!(future);
2320             let mut call_context = None;
2321             future::poll_fn(move |cx| {
2322                 // Push the call context for managing any resource borrows
2323                 // for the task.
2324                 tls::get(|store| {
2325                     if let Some(call_context) = call_context.take() {
2326                         token
2327                             .as_context_mut(store)
2328                             .0
2329                             .component_resource_state()
2330                             .0
2331                             .push(call_context);
2332                     }
2333                 });
2334 
2335                 let result = future.as_mut().poll(cx);
2336 
2337                 if result.is_pending() {
2338                     // Pop the call context for managing any resource
2339                     // borrows for the task.
2340                     tls::get(|store| {
2341                         call_context = Some(
2342                             token
2343                                 .as_context_mut(store)
2344                                 .0
2345                                 .component_resource_state()
2346                                 .0
2347                                 .pop()
2348                                 .unwrap(),
2349                         );
2350                     });
2351                 }
2352                 result
2353             })
2354             .await
2355         });
2356 
2357         // We create a new host task even though it might complete immediately
2358         // (in which case we won't need to pass a waitable back to the guest).
2359         // If it does complete immediately, we'll remove it before we return.
2360         let task = state.push(HostTask::new(caller_instance, Some(join_handle)))?;
2361 
2362         log::trace!("new host task child of {caller:?}: {task:?}");
2363         let token = StoreToken::new(store.as_context_mut());
2364 
2365         // Map the output of the future to a `HostTaskOutput` responsible for
2366         // lowering the result into the guest's stack and memory, as well as
2367         // notifying any waiters that the task returned.
2368         let mut future = Box::pin(async move {
2369             let result = match future.await {
2370                 Some(result) => result,
2371                 // Task was cancelled; nothing left to do.
2372                 None => return HostTaskOutput::Result(Ok(())),
2373             };
2374             HostTaskOutput::Function(Box::new(move |store, instance| {
2375                 let mut store = token.as_context_mut(store);
2376                 lower(store.as_context_mut(), instance, result?)?;
2377                 let state = instance.concurrent_state_mut(store.0);
2378                 state.get_mut(task)?.join_handle.take();
2379                 Waitable::Host(task).set_event(
2380                     state,
2381                     Some(Event::Subtask {
2382                         status: Status::Returned,
2383                     }),
2384                 )?;
2385 
2386                 Ok(())
2387             }))
2388         });
2389 
2390         // Finally, poll the future.  We can use a dummy `Waker` here because
2391         // we'll add the future to `ConcurrentState::futures` and poll it
2392         // automatically from the event loop if it doesn't complete immediately
2393         // here.
2394         let poll = self.set_tls(store.0, || {
2395             future
2396                 .as_mut()
2397                 .poll(&mut Context::from_waker(&Waker::noop()))
2398         });
2399 
2400         Ok(match poll {
2401             Poll::Ready(output) => {
2402                 // It finished immediately; lower the result and delete the
2403                 // task.
2404                 output.consume(store.0, self)?;
2405                 log::trace!("delete host task {task:?} (already ready)");
2406                 self.concurrent_state_mut(store.0).delete(task)?;
2407                 None
2408             }
2409             Poll::Pending => {
2410                 // It hasn't finished yet; add the future to
2411                 // `ConcurrentState::futures` so it will be polled by the event
2412                 // loop and allocate a waitable handle to return to the guest.
2413                 self.concurrent_state_mut(store.0).push_future(future);
2414                 let handle = self.id().get_mut(store.0).guest_tables().0[caller_instance]
2415                     .subtask_insert_host(task.rep())?;
2416                 self.concurrent_state_mut(store.0)
2417                     .get_mut(task)?
2418                     .common
2419                     .handle = Some(handle);
2420                 log::trace!(
2421                     "assign {task:?} handle {handle} for {caller:?} instance {caller_instance:?}"
2422                 );
2423                 Some(handle)
2424             }
2425         })
2426     }
2427 
2428     /// Poll the specified future until it completes on behalf of a guest->host
2429     /// call using a sync-lowered import.
2430     ///
2431     /// This is similar to `Self::first_poll` except it's for sync-lowered
2432     /// imports, meaning we don't need to handle cancellation and we can block
2433     /// the caller until the task completes, at which point the caller can
2434     /// handle lowering the result to the guest's stack and linear memory.
2435     pub(crate) fn poll_and_block<R: Send + Sync + 'static>(
2436         self,
2437         store: &mut dyn VMStore,
2438         future: impl Future<Output = Result<R>> + Send + 'static,
2439         caller_instance: RuntimeComponentInstanceIndex,
2440     ) -> Result<R> {
2441         let state = self.concurrent_state_mut(store);
2442 
2443         // If there is no current guest task set, that means the host function
2444         // was registered using e.g. `LinkerInstance::func_wrap`, in which case
2445         // it should complete immediately.
2446         let Some(caller) = state.guest_task else {
2447             return match pin!(future).poll(&mut Context::from_waker(&Waker::noop())) {
2448                 Poll::Ready(result) => result,
2449                 Poll::Pending => {
2450                     unreachable!()
2451                 }
2452             };
2453         };
2454 
2455         // Save any existing result stashed in `GuestTask::result` so we can
2456         // replace it with the new result.
2457         let old_result = state
2458             .get_mut(caller)
2459             .with_context(|| format!("bad handle: {caller:?}"))?
2460             .result
2461             .take();
2462 
2463         // Add a temporary host task into the table so we can track its
2464         // progress.  Note that we'll never allocate a waitable handle for the
2465         // guest since we're being called synchronously.
2466         let task = state.push(HostTask::new(caller_instance, None))?;
2467 
2468         log::trace!("new host task child of {caller:?}: {task:?}");
2469 
2470         // Map the output of the future to a `HostTaskOutput` which will take
2471         // care of stashing the result in `GuestTask::result` and resuming this
2472         // fiber when the host task completes.
2473         let mut future = Box::pin(future.map(move |result| {
2474             HostTaskOutput::Function(Box::new(move |store, instance| {
2475                 let state = instance.concurrent_state_mut(store);
2476                 state.get_mut(caller)?.result = Some(Box::new(result?) as _);
2477 
2478                 Waitable::Host(task).set_event(
2479                     state,
2480                     Some(Event::Subtask {
2481                         status: Status::Returned,
2482                     }),
2483                 )?;
2484 
2485                 Ok(())
2486             }))
2487         })) as HostTaskFuture;
2488 
2489         // Finally, poll the future.  We can use a dummy `Waker` here because
2490         // we'll add the future to `ConcurrentState::futures` and poll it
2491         // automatically from the event loop if it doesn't complete immediately
2492         // here.
2493         let poll = self.set_tls(store, || {
2494             future
2495                 .as_mut()
2496                 .poll(&mut Context::from_waker(&Waker::noop()))
2497         });
2498 
2499         match poll {
2500             Poll::Ready(output) => {
2501                 // It completed immediately; run the `HostTaskOutput` function
2502                 // to stash the result and delete the task.
2503                 output.consume(store, self)?;
2504                 log::trace!("delete host task {task:?} (already ready)");
2505                 self.concurrent_state_mut(store).delete(task)?;
2506             }
2507             Poll::Pending => {
2508                 // It did not complete immediately; add it to
2509                 // `ConcurrentState::futures` so it will be polled via the event
2510                 // loop, then use `GuestTask::sync_call_set` to wait for the
2511                 // task to complete, suspending the current fiber until it does
2512                 // so.
2513                 let state = self.concurrent_state_mut(store);
2514                 state.push_future(future);
2515 
2516                 let set = state.get_mut(caller)?.sync_call_set;
2517                 Waitable::Host(task).join(state, Some(set))?;
2518 
2519                 self.suspend(store, SuspendReason::Waiting { set, task: caller })?;
2520             }
2521         }
2522 
2523         // Retrieve and return the result.
2524         Ok(*mem::replace(
2525             &mut self.concurrent_state_mut(store).get_mut(caller)?.result,
2526             old_result,
2527         )
2528         .unwrap()
2529         .downcast()
2530         .unwrap())
2531     }
2532 
2533     /// Implements the `task.return` intrinsic, lifting the result for the
2534     /// current guest task.
2535     pub(crate) fn task_return(
2536         self,
2537         store: &mut dyn VMStore,
2538         ty: TypeTupleIndex,
2539         options: OptionsIndex,
2540         storage: &[ValRaw],
2541     ) -> Result<()> {
2542         let state = self.concurrent_state_mut(store);
2543         let CanonicalOptions {
2544             string_encoding,
2545             data_model,
2546             ..
2547         } = *state.options(options);
2548         let guest_task = state.guest_task.unwrap();
2549         let lift = state
2550             .get_mut(guest_task)?
2551             .lift_result
2552             .take()
2553             .ok_or_else(|| {
2554                 anyhow!("`task.return` or `task.cancel` called more than once for current task")
2555             })?;
2556         assert!(state.get_mut(guest_task)?.result.is_none());
2557 
2558         let invalid = ty != lift.ty
2559             || string_encoding != lift.string_encoding
2560             || match data_model {
2561                 CanonicalOptionsDataModel::LinearMemory(opts) => match opts.memory {
2562                     Some(memory) => {
2563                         let expected = lift.memory.map(|v| v.as_ptr()).unwrap_or(ptr::null_mut());
2564                         let actual = self.id().get(store).runtime_memory(memory);
2565                         expected != actual
2566                     }
2567                     // Memory not specified, meaning it didn't need to be
2568                     // specified per validation, so not invalid.
2569                     None => false,
2570                 },
2571                 // Always invalid as this isn't supported.
2572                 CanonicalOptionsDataModel::Gc { .. } => true,
2573             };
2574 
2575         if invalid {
2576             bail!("invalid `task.return` signature and/or options for current task");
2577         }
2578 
2579         log::trace!("task.return for {guest_task:?}");
2580 
2581         let result = (lift.lift)(store, self, storage)?;
2582 
2583         self.task_complete(store, guest_task, result, Status::Returned, ValRaw::i32(0))
2584     }
2585 
2586     /// Implements the `task.cancel` intrinsic.
2587     pub(crate) fn task_cancel(
2588         self,
2589         store: &mut dyn VMStore,
2590         _caller_instance: RuntimeComponentInstanceIndex,
2591     ) -> Result<()> {
2592         let state = self.concurrent_state_mut(store);
2593         let guest_task = state.guest_task.unwrap();
2594         let task = state.get_mut(guest_task)?;
2595         if !task.cancel_sent {
2596             bail!("`task.cancel` called by task which has not been cancelled")
2597         }
2598         _ = task.lift_result.take().ok_or_else(|| {
2599             anyhow!("`task.return` or `task.cancel` called more than once for current task")
2600         })?;
2601 
2602         assert!(task.result.is_none());
2603 
2604         log::trace!("task.cancel for {guest_task:?}");
2605 
2606         self.task_complete(
2607             store,
2608             guest_task,
2609             Box::new(DummyResult),
2610             Status::ReturnCancelled,
2611             ValRaw::i32(0),
2612         )
2613     }
2614 
2615     /// Complete the specified guest task (i.e. indicate that it has either
2616     /// returned a (possibly empty) result or cancelled itself).
2617     ///
2618     /// This will return any resource borrows and notify any current or future
2619     /// waiters that the task has completed.
2620     fn task_complete(
2621         self,
2622         store: &mut dyn VMStore,
2623         guest_task: TableId<GuestTask>,
2624         result: Box<dyn Any + Send + Sync>,
2625         status: Status,
2626         post_return_arg: ValRaw,
2627     ) -> Result<()> {
2628         if self
2629             .concurrent_state_mut(store)
2630             .get_mut(guest_task)?
2631             .call_post_return_automatically()
2632         {
2633             let (calls, host_table, _, instance) = store
2634                 .store_opaque_mut()
2635                 .component_resource_state_with_instance(self);
2636             ResourceTables {
2637                 calls,
2638                 host_table: Some(host_table),
2639                 guest: Some(instance.guest_tables()),
2640             }
2641             .exit_call()?;
2642         } else {
2643             // As of this writing, the only scenario where `call_post_return_automatically`
2644             // would be false for a `GuestTask` is for host-to-guest calls using
2645             // `[Typed]Func::call_async`, in which case the `function_index`
2646             // should be a non-`None` value.
2647             let function_index = self
2648                 .concurrent_state_mut(store)
2649                 .get_mut(guest_task)?
2650                 .function_index
2651                 .unwrap();
2652 
2653             self.id()
2654                 .get_mut(store)
2655                 .post_return_arg_set(function_index, post_return_arg);
2656         }
2657 
2658         let state = self.concurrent_state_mut(store);
2659         let task = state.get_mut(guest_task)?;
2660 
2661         if let Caller::Host { tx, .. } = &mut task.caller {
2662             if let Some(tx) = tx.take() {
2663                 _ = tx.send(result);
2664             }
2665         } else {
2666             task.result = Some(result);
2667             Waitable::Guest(guest_task).set_event(state, Some(Event::Subtask { status }))?;
2668         }
2669 
2670         Ok(())
2671     }
2672 
2673     /// Implements the `waitable-set.wait` intrinsic.
2674     pub(crate) fn waitable_set_wait(
2675         self,
2676         store: &mut dyn VMStore,
2677         options: OptionsIndex,
2678         set: u32,
2679         payload: u32,
2680     ) -> Result<u32> {
2681         let opts = self.concurrent_state_mut(store).options(options);
2682         let async_ = opts.async_;
2683         let caller_instance = opts.instance;
2684         let rep =
2685             self.id().get_mut(store).guest_tables().0[caller_instance].waitable_set_rep(set)?;
2686 
2687         self.waitable_check(
2688             store,
2689             async_,
2690             WaitableCheck::Wait(WaitableCheckParams {
2691                 set: TableId::new(rep),
2692                 options,
2693                 payload,
2694             }),
2695         )
2696     }
2697 
2698     /// Implements the `waitable-set.poll` intrinsic.
2699     pub(crate) fn waitable_set_poll(
2700         self,
2701         store: &mut dyn VMStore,
2702         options: OptionsIndex,
2703         set: u32,
2704         payload: u32,
2705     ) -> Result<u32> {
2706         let opts = self.concurrent_state_mut(store).options(options);
2707         let async_ = opts.async_;
2708         let caller_instance = opts.instance;
2709         let rep =
2710             self.id().get_mut(store).guest_tables().0[caller_instance].waitable_set_rep(set)?;
2711 
2712         self.waitable_check(
2713             store,
2714             async_,
2715             WaitableCheck::Poll(WaitableCheckParams {
2716                 set: TableId::new(rep),
2717                 options,
2718                 payload,
2719             }),
2720         )
2721     }
2722 
2723     /// Implements the `yield` intrinsic.
2724     pub(crate) fn yield_(self, store: &mut dyn VMStore, async_: bool) -> Result<bool> {
2725         self.waitable_check(store, async_, WaitableCheck::Yield)
2726             .map(|_| {
2727                 let state = self.concurrent_state_mut(store);
2728                 let task = state.guest_task.unwrap();
2729                 if let Some(event) = state.get_mut(task).unwrap().event.take() {
2730                     assert!(matches!(event, Event::Cancelled));
2731                     true
2732                 } else {
2733                     false
2734                 }
2735             })
2736     }
2737 
2738     /// Helper function for the `waitable-set.wait`, `waitable-set.poll`, and
2739     /// `yield` intrinsics.
2740     fn waitable_check(
2741         self,
2742         store: &mut dyn VMStore,
2743         async_: bool,
2744         check: WaitableCheck,
2745     ) -> Result<u32> {
2746         if async_ {
2747             bail!(
2748                 "todo: async `waitable-set.wait`, `waitable-set.poll`, and `yield` not yet implemented"
2749             );
2750         }
2751 
2752         let guest_task = self.concurrent_state_mut(store).guest_task.unwrap();
2753 
2754         let (wait, set) = match &check {
2755             WaitableCheck::Wait(params) => (true, Some(params.set)),
2756             WaitableCheck::Poll(params) => (false, Some(params.set)),
2757             WaitableCheck::Yield => (false, None),
2758         };
2759 
2760         // First, suspend this fiber, allowing any other tasks to run.
2761         self.suspend(store, SuspendReason::Yielding { task: guest_task })?;
2762 
2763         log::trace!("waitable check for {guest_task:?}; set {set:?}");
2764 
2765         let state = self.concurrent_state_mut(store);
2766         let task = state.get_mut(guest_task)?;
2767 
2768         if wait && task.callback.is_some() {
2769             bail!("cannot call `task.wait` from async-lifted export with callback");
2770         }
2771 
2772         // If we're waiting, and there are no events immediately available,
2773         // suspend the fiber until that changes.
2774         if wait {
2775             let set = set.unwrap();
2776 
2777             if task.event.is_none() && state.get_mut(set)?.ready.is_empty() {
2778                 let old = state.get_mut(guest_task)?.wake_on_cancel.replace(set);
2779                 assert!(old.is_none());
2780 
2781                 self.suspend(
2782                     store,
2783                     SuspendReason::Waiting {
2784                         set,
2785                         task: guest_task,
2786                     },
2787                 )?;
2788             }
2789         }
2790 
2791         log::trace!("waitable check for {guest_task:?}; set {set:?}, part two");
2792 
2793         let result = match check {
2794             // Deliver any pending events to the guest and return.
2795             WaitableCheck::Wait(params) | WaitableCheck::Poll(params) => {
2796                 let event = self
2797                     .id()
2798                     .get_mut(store)
2799                     .get_event(guest_task, Some(params.set))?;
2800 
2801                 let (ordinal, handle, result) = if wait {
2802                     let (event, waitable) = event.unwrap();
2803                     let handle = waitable.map(|(_, v)| v).unwrap_or(0);
2804                     let (ordinal, result) = event.parts();
2805                     (ordinal, handle, result)
2806                 } else {
2807                     if let Some((event, waitable)) = event {
2808                         let handle = waitable.map(|(_, v)| v).unwrap_or(0);
2809                         let (ordinal, result) = event.parts();
2810                         (ordinal, handle, result)
2811                     } else {
2812                         log::trace!(
2813                             "no events ready to deliver via waitable-set.poll to {guest_task:?}; set {:?}",
2814                             params.set
2815                         );
2816                         let (ordinal, result) = Event::None.parts();
2817                         (ordinal, 0, result)
2818                     }
2819                 };
2820                 let store = store.store_opaque_mut();
2821                 let options = Options::new_index(store, self, params.options);
2822                 let ptr = func::validate_inbounds::<(u32, u32)>(
2823                     options.memory_mut(store),
2824                     &ValRaw::u32(params.payload),
2825                 )?;
2826                 options.memory_mut(store)[ptr + 0..][..4].copy_from_slice(&handle.to_le_bytes());
2827                 options.memory_mut(store)[ptr + 4..][..4].copy_from_slice(&result.to_le_bytes());
2828                 Ok(ordinal)
2829             }
2830             WaitableCheck::Yield => Ok(0),
2831         };
2832 
2833         result
2834     }
2835 
2836     /// Implements the `subtask.cancel` intrinsic.
2837     pub(crate) fn subtask_cancel(
2838         self,
2839         store: &mut dyn VMStore,
2840         caller_instance: RuntimeComponentInstanceIndex,
2841         async_: bool,
2842         task_id: u32,
2843     ) -> Result<u32> {
2844         let (rep, is_host) =
2845             self.id().get_mut(store).guest_tables().0[caller_instance].subtask_rep(task_id)?;
2846         let (waitable, expected_caller_instance) = if is_host {
2847             let id = TableId::<HostTask>::new(rep);
2848             (
2849                 Waitable::Host(id),
2850                 self.concurrent_state_mut(store)
2851                     .get_mut(id)?
2852                     .caller_instance,
2853             )
2854         } else {
2855             let id = TableId::<GuestTask>::new(rep);
2856             if let Caller::Guest { instance, .. } =
2857                 &self.concurrent_state_mut(store).get_mut(id)?.caller
2858             {
2859                 (Waitable::Guest(id), *instance)
2860             } else {
2861                 unreachable!()
2862             }
2863         };
2864         // Since waitables can neither be passed between instances nor forged,
2865         // this should never fail unless there's a bug in Wasmtime, but we check
2866         // here to be sure:
2867         assert_eq!(expected_caller_instance, caller_instance);
2868 
2869         log::trace!("subtask_cancel {waitable:?} (handle {task_id})");
2870 
2871         let concurrent_state = self.concurrent_state_mut(store);
2872         if let Waitable::Host(host_task) = waitable {
2873             if let Some(handle) = concurrent_state.get_mut(host_task)?.join_handle.take() {
2874                 handle.abort();
2875                 return Ok(Status::ReturnCancelled as u32);
2876             }
2877         } else {
2878             let caller = concurrent_state.guest_task.unwrap();
2879             let guest_task = TableId::<GuestTask>::new(rep);
2880             let task = concurrent_state.get_mut(guest_task)?;
2881             if task.lower_params.is_some() {
2882                 task.lower_params = None;
2883                 task.lift_result = None;
2884 
2885                 // Not yet started; cancel and remove from pending
2886                 let callee_instance = task.instance;
2887 
2888                 let kind = concurrent_state
2889                     .instance_state(callee_instance)
2890                     .pending
2891                     .remove(&guest_task);
2892 
2893                 if kind.is_none() {
2894                     bail!("`subtask.cancel` called after terminal status delivered");
2895                 }
2896 
2897                 return Ok(Status::StartCancelled as u32);
2898             } else if task.lift_result.is_some() {
2899                 // Started, but not yet returned or cancelled; send the
2900                 // `CANCELLED` event
2901                 task.cancel_sent = true;
2902                 // Note that this might overwrite an event that was set earlier
2903                 // (e.g. `Event::None` if the task is yielding, or
2904                 // `Event::Cancelled` if it was already cancelled), but that's
2905                 // okay -- this should supersede the previous state.
2906                 task.event = Some(Event::Cancelled);
2907                 if let Some(set) = task.wake_on_cancel.take() {
2908                     let item = match concurrent_state
2909                         .get_mut(set)?
2910                         .waiting
2911                         .remove(&guest_task)
2912                         .unwrap()
2913                     {
2914                         WaitMode::Fiber(fiber) => WorkItem::ResumeFiber(fiber),
2915                         WaitMode::Callback => WorkItem::GuestCall(GuestCall {
2916                             task: guest_task,
2917                             kind: GuestCallKind::DeliverEvent { set: None },
2918                         }),
2919                     };
2920                     concurrent_state.push_high_priority(item);
2921 
2922                     self.suspend(store, SuspendReason::Yielding { task: caller })?;
2923                 }
2924 
2925                 let concurrent_state = self.concurrent_state_mut(store);
2926                 let task = concurrent_state.get_mut(guest_task)?;
2927                 if task.lift_result.is_some() {
2928                     // Still not yet returned or cancelled; if `async_`, return
2929                     // `BLOCKED`; otherwise wait
2930                     if async_ {
2931                         return Ok(BLOCKED);
2932                     } else {
2933                         let waitable = Waitable::Guest(guest_task);
2934                         let old_set = waitable.common(concurrent_state)?.set;
2935                         let set = concurrent_state.get_mut(caller)?.sync_call_set;
2936                         waitable.join(concurrent_state, Some(set))?;
2937 
2938                         self.suspend(store, SuspendReason::Waiting { set, task: caller })?;
2939 
2940                         waitable.join(self.concurrent_state_mut(store), old_set)?;
2941                     }
2942                 }
2943             }
2944         }
2945 
2946         let event = waitable.take_event(self.concurrent_state_mut(store))?;
2947         if let Some(Event::Subtask {
2948             status: status @ (Status::Returned | Status::ReturnCancelled),
2949         }) = event
2950         {
2951             Ok(status as u32)
2952         } else {
2953             bail!("`subtask.cancel` called after terminal status delivered");
2954         }
2955     }
2956 
2957     /// Configures TLS state so `store` will be available via `tls::get` within
2958     /// the closure `f` provided.
2959     ///
2960     /// This is used to ensure that `Future::poll`, which doesn't take a `store`
2961     /// parameter, is able to get access to the `store` during future poll
2962     /// methods.
2963     fn set_tls<R>(self, store: &mut dyn VMStore, f: impl FnOnce() -> R) -> R {
2964         struct Reset<'a>(&'a mut dyn VMStore, Option<ComponentInstanceId>);
2965 
2966         impl Drop for Reset<'_> {
2967             fn drop(&mut self) {
2968                 self.0.concurrent_async_state_mut().current_instance = self.1;
2969             }
2970         }
2971         let prev = mem::replace(
2972             &mut store.concurrent_async_state_mut().current_instance,
2973             Some(self.id().instance()),
2974         );
2975         let reset = Reset(store, prev);
2976 
2977         tls::set(reset.0, f)
2978     }
2979 
2980     /// Convenience function to reduce boilerplate.
2981     pub(crate) fn concurrent_state_mut<'a>(
2982         &self,
2983         store: &'a mut StoreOpaque,
2984     ) -> &'a mut ConcurrentState {
2985         self.id().get_mut(store).concurrent_state_mut()
2986     }
2987 }
2988 
2989 /// Trait representing component model ABI async intrinsics and fused adapter
2990 /// helper functions.
2991 ///
2992 /// SAFETY (callers): Most of the methods in this trait accept raw pointers,
2993 /// which must be valid for at least the duration of the call (and possibly for
2994 /// as long as the relevant guest task exists, in the case of `*mut VMFuncRef`
2995 /// pointers used for async calls).
2996 pub trait VMComponentAsyncStore {
2997     /// A helper function for fused adapter modules involving calls where the
2998     /// one of the caller or callee is async.
2999     ///
3000     /// This helper is not used when the caller and callee both use the sync
3001     /// ABI, only when at least one is async is this used.
3002     unsafe fn prepare_call(
3003         &mut self,
3004         instance: Instance,
3005         memory: *mut VMMemoryDefinition,
3006         start: *mut VMFuncRef,
3007         return_: *mut VMFuncRef,
3008         caller_instance: RuntimeComponentInstanceIndex,
3009         callee_instance: RuntimeComponentInstanceIndex,
3010         task_return_type: TypeTupleIndex,
3011         string_encoding: u8,
3012         result_count: u32,
3013         storage: *mut ValRaw,
3014         storage_len: usize,
3015     ) -> Result<()>;
3016 
3017     /// A helper function for fused adapter modules involving calls where the
3018     /// caller is sync-lowered but the callee is async-lifted.
3019     unsafe fn sync_start(
3020         &mut self,
3021         instance: Instance,
3022         callback: *mut VMFuncRef,
3023         callee: *mut VMFuncRef,
3024         param_count: u32,
3025         storage: *mut MaybeUninit<ValRaw>,
3026         storage_len: usize,
3027     ) -> Result<()>;
3028 
3029     /// A helper function for fused adapter modules involving calls where the
3030     /// caller is async-lowered.
3031     unsafe fn async_start(
3032         &mut self,
3033         instance: Instance,
3034         callback: *mut VMFuncRef,
3035         post_return: *mut VMFuncRef,
3036         callee: *mut VMFuncRef,
3037         param_count: u32,
3038         result_count: u32,
3039         flags: u32,
3040     ) -> Result<u32>;
3041 
3042     /// The `future.write` intrinsic.
3043     fn future_write(
3044         &mut self,
3045         instance: Instance,
3046         ty: TypeFutureTableIndex,
3047         options: OptionsIndex,
3048         future: u32,
3049         address: u32,
3050     ) -> Result<u32>;
3051 
3052     /// The `future.read` intrinsic.
3053     fn future_read(
3054         &mut self,
3055         instance: Instance,
3056         ty: TypeFutureTableIndex,
3057         options: OptionsIndex,
3058         future: u32,
3059         address: u32,
3060     ) -> Result<u32>;
3061 
3062     /// The `future.drop-writable` intrinsic.
3063     fn future_drop_writable(
3064         &mut self,
3065         instance: Instance,
3066         ty: TypeFutureTableIndex,
3067         writer: u32,
3068     ) -> Result<()>;
3069 
3070     /// The `stream.write` intrinsic.
3071     fn stream_write(
3072         &mut self,
3073         instance: Instance,
3074         ty: TypeStreamTableIndex,
3075         options: OptionsIndex,
3076         stream: u32,
3077         address: u32,
3078         count: u32,
3079     ) -> Result<u32>;
3080 
3081     /// The `stream.read` intrinsic.
3082     fn stream_read(
3083         &mut self,
3084         instance: Instance,
3085         ty: TypeStreamTableIndex,
3086         options: OptionsIndex,
3087         stream: u32,
3088         address: u32,
3089         count: u32,
3090     ) -> Result<u32>;
3091 
3092     /// The "fast-path" implementation of the `stream.write` intrinsic for
3093     /// "flat" (i.e. memcpy-able) payloads.
3094     fn flat_stream_write(
3095         &mut self,
3096         instance: Instance,
3097         ty: TypeStreamTableIndex,
3098         options: OptionsIndex,
3099         payload_size: u32,
3100         payload_align: u32,
3101         stream: u32,
3102         address: u32,
3103         count: u32,
3104     ) -> Result<u32>;
3105 
3106     /// The "fast-path" implementation of the `stream.read` intrinsic for "flat"
3107     /// (i.e. memcpy-able) payloads.
3108     fn flat_stream_read(
3109         &mut self,
3110         instance: Instance,
3111         ty: TypeStreamTableIndex,
3112         options: OptionsIndex,
3113         payload_size: u32,
3114         payload_align: u32,
3115         stream: u32,
3116         address: u32,
3117         count: u32,
3118     ) -> Result<u32>;
3119 
3120     /// The `stream.drop-writable` intrinsic.
3121     fn stream_drop_writable(
3122         &mut self,
3123         instance: Instance,
3124         ty: TypeStreamTableIndex,
3125         writer: u32,
3126     ) -> Result<()>;
3127 
3128     /// The `error-context.debug-message` intrinsic.
3129     fn error_context_debug_message(
3130         &mut self,
3131         instance: Instance,
3132         ty: TypeComponentLocalErrorContextTableIndex,
3133         options: OptionsIndex,
3134         err_ctx_handle: u32,
3135         debug_msg_address: u32,
3136     ) -> Result<()>;
3137 }
3138 
3139 /// SAFETY: See trait docs.
3140 impl<T: 'static> VMComponentAsyncStore for StoreInner<T> {
3141     unsafe fn prepare_call(
3142         &mut self,
3143         instance: Instance,
3144         memory: *mut VMMemoryDefinition,
3145         start: *mut VMFuncRef,
3146         return_: *mut VMFuncRef,
3147         caller_instance: RuntimeComponentInstanceIndex,
3148         callee_instance: RuntimeComponentInstanceIndex,
3149         task_return_type: TypeTupleIndex,
3150         string_encoding: u8,
3151         result_count_or_max_if_async: u32,
3152         storage: *mut ValRaw,
3153         storage_len: usize,
3154     ) -> Result<()> {
3155         // SAFETY: The `wasmtime_cranelift`-generated code that calls
3156         // this method will have ensured that `storage` is a valid
3157         // pointer containing at least `storage_len` items.
3158         let params = unsafe { std::slice::from_raw_parts(storage, storage_len) }.to_vec();
3159 
3160         unsafe {
3161             instance.prepare_call(
3162                 StoreContextMut(self),
3163                 start,
3164                 return_,
3165                 caller_instance,
3166                 callee_instance,
3167                 task_return_type,
3168                 memory,
3169                 string_encoding,
3170                 match result_count_or_max_if_async {
3171                     PREPARE_ASYNC_NO_RESULT => CallerInfo::Async {
3172                         params,
3173                         has_result: false,
3174                     },
3175                     PREPARE_ASYNC_WITH_RESULT => CallerInfo::Async {
3176                         params,
3177                         has_result: true,
3178                     },
3179                     result_count => CallerInfo::Sync {
3180                         params,
3181                         result_count,
3182                     },
3183                 },
3184             )
3185         }
3186     }
3187 
3188     unsafe fn sync_start(
3189         &mut self,
3190         instance: Instance,
3191         callback: *mut VMFuncRef,
3192         callee: *mut VMFuncRef,
3193         param_count: u32,
3194         storage: *mut MaybeUninit<ValRaw>,
3195         storage_len: usize,
3196     ) -> Result<()> {
3197         unsafe {
3198             instance
3199                 .start_call(
3200                     StoreContextMut(self),
3201                     callback,
3202                     ptr::null_mut(),
3203                     callee,
3204                     param_count,
3205                     1,
3206                     START_FLAG_ASYNC_CALLEE,
3207                     // SAFETY: The `wasmtime_cranelift`-generated code that calls
3208                     // this method will have ensured that `storage` is a valid
3209                     // pointer containing at least `storage_len` items.
3210                     Some(std::slice::from_raw_parts_mut(storage, storage_len)),
3211                 )
3212                 .map(drop)
3213         }
3214     }
3215 
3216     unsafe fn async_start(
3217         &mut self,
3218         instance: Instance,
3219         callback: *mut VMFuncRef,
3220         post_return: *mut VMFuncRef,
3221         callee: *mut VMFuncRef,
3222         param_count: u32,
3223         result_count: u32,
3224         flags: u32,
3225     ) -> Result<u32> {
3226         unsafe {
3227             instance.start_call(
3228                 StoreContextMut(self),
3229                 callback,
3230                 post_return,
3231                 callee,
3232                 param_count,
3233                 result_count,
3234                 flags,
3235                 None,
3236             )
3237         }
3238     }
3239 
3240     fn future_write(
3241         &mut self,
3242         instance: Instance,
3243         ty: TypeFutureTableIndex,
3244         options: OptionsIndex,
3245         future: u32,
3246         address: u32,
3247     ) -> Result<u32> {
3248         instance
3249             .guest_write(
3250                 StoreContextMut(self),
3251                 TransmitIndex::Future(ty),
3252                 options,
3253                 None,
3254                 future,
3255                 address,
3256                 1,
3257             )
3258             .map(|result| result.encode())
3259     }
3260 
3261     fn future_read(
3262         &mut self,
3263         instance: Instance,
3264         ty: TypeFutureTableIndex,
3265         options: OptionsIndex,
3266         future: u32,
3267         address: u32,
3268     ) -> Result<u32> {
3269         instance
3270             .guest_read(
3271                 StoreContextMut(self),
3272                 TransmitIndex::Future(ty),
3273                 options,
3274                 None,
3275                 future,
3276                 address,
3277                 1,
3278             )
3279             .map(|result| result.encode())
3280     }
3281 
3282     fn stream_write(
3283         &mut self,
3284         instance: Instance,
3285         ty: TypeStreamTableIndex,
3286         options: OptionsIndex,
3287         stream: u32,
3288         address: u32,
3289         count: u32,
3290     ) -> Result<u32> {
3291         instance
3292             .guest_write(
3293                 StoreContextMut(self),
3294                 TransmitIndex::Stream(ty),
3295                 options,
3296                 None,
3297                 stream,
3298                 address,
3299                 count,
3300             )
3301             .map(|result| result.encode())
3302     }
3303 
3304     fn stream_read(
3305         &mut self,
3306         instance: Instance,
3307         ty: TypeStreamTableIndex,
3308         options: OptionsIndex,
3309         stream: u32,
3310         address: u32,
3311         count: u32,
3312     ) -> Result<u32> {
3313         instance
3314             .guest_read(
3315                 StoreContextMut(self),
3316                 TransmitIndex::Stream(ty),
3317                 options,
3318                 None,
3319                 stream,
3320                 address,
3321                 count,
3322             )
3323             .map(|result| result.encode())
3324     }
3325 
3326     fn future_drop_writable(
3327         &mut self,
3328         instance: Instance,
3329         ty: TypeFutureTableIndex,
3330         writer: u32,
3331     ) -> Result<()> {
3332         instance.guest_drop_writable(StoreContextMut(self), TransmitIndex::Future(ty), writer)
3333     }
3334 
3335     fn flat_stream_write(
3336         &mut self,
3337         instance: Instance,
3338         ty: TypeStreamTableIndex,
3339         options: OptionsIndex,
3340         payload_size: u32,
3341         payload_align: u32,
3342         stream: u32,
3343         address: u32,
3344         count: u32,
3345     ) -> Result<u32> {
3346         instance
3347             .guest_write(
3348                 StoreContextMut(self),
3349                 TransmitIndex::Stream(ty),
3350                 options,
3351                 Some(FlatAbi {
3352                     size: payload_size,
3353                     align: payload_align,
3354                 }),
3355                 stream,
3356                 address,
3357                 count,
3358             )
3359             .map(|result| result.encode())
3360     }
3361 
3362     fn flat_stream_read(
3363         &mut self,
3364         instance: Instance,
3365         ty: TypeStreamTableIndex,
3366         options: OptionsIndex,
3367         payload_size: u32,
3368         payload_align: u32,
3369         stream: u32,
3370         address: u32,
3371         count: u32,
3372     ) -> Result<u32> {
3373         instance
3374             .guest_read(
3375                 StoreContextMut(self),
3376                 TransmitIndex::Stream(ty),
3377                 options,
3378                 Some(FlatAbi {
3379                     size: payload_size,
3380                     align: payload_align,
3381                 }),
3382                 stream,
3383                 address,
3384                 count,
3385             )
3386             .map(|result| result.encode())
3387     }
3388 
3389     fn stream_drop_writable(
3390         &mut self,
3391         instance: Instance,
3392         ty: TypeStreamTableIndex,
3393         writer: u32,
3394     ) -> Result<()> {
3395         instance.guest_drop_writable(StoreContextMut(self), TransmitIndex::Stream(ty), writer)
3396     }
3397 
3398     fn error_context_debug_message(
3399         &mut self,
3400         instance: Instance,
3401         ty: TypeComponentLocalErrorContextTableIndex,
3402         options: OptionsIndex,
3403         err_ctx_handle: u32,
3404         debug_msg_address: u32,
3405     ) -> Result<()> {
3406         instance.error_context_debug_message(
3407             StoreContextMut(self),
3408             ty,
3409             options,
3410             err_ctx_handle,
3411             debug_msg_address,
3412         )
3413     }
3414 }
3415 
3416 /// Represents the output of a host task or background task.
3417 pub(crate) enum HostTaskOutput {
3418     /// A plain result
3419     Result(Result<()>),
3420     /// A function to be run after the future completes (e.g. post-processing
3421     /// which requires access to the store and instance).
3422     Function(Box<dyn FnOnce(&mut dyn VMStore, Instance) -> Result<()> + Send>),
3423 }
3424 
3425 impl HostTaskOutput {
3426     /// Retrieve the result of the host or background task, running the
3427     /// post-processing function if present.
3428     fn consume(self, store: &mut dyn VMStore, instance: Instance) -> Result<()> {
3429         match self {
3430             Self::Function(fun) => fun(store, instance),
3431             Self::Result(result) => result,
3432         }
3433     }
3434 }
3435 
3436 type HostTaskFuture = Pin<Box<dyn Future<Output = HostTaskOutput> + Send + 'static>>;
3437 
3438 /// Represents the state of a pending host task.
3439 struct HostTask {
3440     common: WaitableCommon,
3441     caller_instance: RuntimeComponentInstanceIndex,
3442     join_handle: Option<JoinHandle>,
3443 }
3444 
3445 impl HostTask {
3446     fn new(
3447         caller_instance: RuntimeComponentInstanceIndex,
3448         join_handle: Option<JoinHandle>,
3449     ) -> Self {
3450         Self {
3451             common: WaitableCommon::default(),
3452             caller_instance,
3453             join_handle,
3454         }
3455     }
3456 }
3457 
3458 impl TableDebug for HostTask {
3459     fn type_name() -> &'static str {
3460         "HostTask"
3461     }
3462 }
3463 
3464 type CallbackFn = Box<
3465     dyn Fn(&mut dyn VMStore, Instance, RuntimeComponentInstanceIndex, Event, u32) -> Result<u32>
3466         + Send
3467         + Sync
3468         + 'static,
3469 >;
3470 
3471 /// Represents the caller of a given guest task.
3472 enum Caller {
3473     /// The host called the guest task.
3474     Host {
3475         /// If present, may be used to deliver the result.
3476         tx: Option<oneshot::Sender<LiftedResult>>,
3477         /// If true, remove the task from the concurrent state that owns it
3478         /// automatically after it completes.
3479         remove_task_automatically: bool,
3480         /// If true, call `post-return` function (if any) automatically.
3481         call_post_return_automatically: bool,
3482     },
3483     /// Another guest task called the guest task
3484     Guest {
3485         /// The id of the caller
3486         task: TableId<GuestTask>,
3487         /// The instance to use to enforce reentrance rules.
3488         ///
3489         /// Note that this might not be the same as the instance the caller task
3490         /// started executing in given that one or more synchronous guest->guest
3491         /// calls may have occurred involving multiple instances.
3492         instance: RuntimeComponentInstanceIndex,
3493     },
3494 }
3495 
3496 /// Represents a closure and related canonical ABI parameters required to
3497 /// validate a `task.return` call at runtime and lift the result.
3498 struct LiftResult {
3499     lift: RawLift,
3500     ty: TypeTupleIndex,
3501     memory: Option<SendSyncPtr<VMMemoryDefinition>>,
3502     string_encoding: StringEncoding,
3503 }
3504 
3505 /// Represents a pending guest task.
3506 struct GuestTask {
3507     /// See `WaitableCommon`
3508     common: WaitableCommon,
3509     /// Closure to lower the parameters passed to this task.
3510     lower_params: Option<RawLower>,
3511     /// See `LiftResult`
3512     lift_result: Option<LiftResult>,
3513     /// A place to stash the type-erased lifted result if it can't be delivered
3514     /// immediately.
3515     result: Option<LiftedResult>,
3516     /// Closure to call the callback function for an async-lifted export, if
3517     /// provided.
3518     callback: Option<CallbackFn>,
3519     /// See `Caller`
3520     caller: Caller,
3521     /// A place to stash the call context for managing resource borrows while
3522     /// switching between guest tasks.
3523     call_context: Option<CallContext>,
3524     /// A place to stash the lowered result for a sync-to-async call until it
3525     /// can be returned to the caller.
3526     sync_result: Option<Option<ValRaw>>,
3527     /// Whether or not the task has been cancelled (i.e. whether the task is
3528     /// permitted to call `task.cancel`).
3529     cancel_sent: bool,
3530     /// Whether or not we've sent a `Status::Starting` event to any current or
3531     /// future waiters for this waitable.
3532     starting_sent: bool,
3533     /// Context-local state used to implement the `context.{get,set}`
3534     /// intrinsics.
3535     context: [u32; 2],
3536     /// Pending guest subtasks created by this task (directly or indirectly).
3537     ///
3538     /// This is used to re-parent subtasks which are still running when their
3539     /// parent task is disposed.
3540     subtasks: HashSet<TableId<GuestTask>>,
3541     /// Scratch waitable set used to watch subtasks during synchronous calls.
3542     sync_call_set: TableId<WaitableSet>,
3543     /// The instance to which the exported function for this guest task belongs.
3544     ///
3545     /// Note that the task may do a sync->sync call via a fused adapter which
3546     /// results in that task executing code in a different instance, and it may
3547     /// call host functions and intrinsics from that other instance.
3548     instance: RuntimeComponentInstanceIndex,
3549     /// If present, a pending `Event::None` or `Event::Cancelled` to be
3550     /// delivered to this task.
3551     event: Option<Event>,
3552     /// If present, indicates that the task is currently waiting on the
3553     /// specified set but may be cancelled and woken immediately.
3554     wake_on_cancel: Option<TableId<WaitableSet>>,
3555     /// The `ExportIndex` of the guest function being called, if known.
3556     function_index: Option<ExportIndex>,
3557     /// Whether or not the task has exited.
3558     exited: bool,
3559 }
3560 
3561 impl GuestTask {
3562     fn new(
3563         state: &mut ConcurrentState,
3564         lower_params: RawLower,
3565         lift_result: LiftResult,
3566         caller: Caller,
3567         callback: Option<CallbackFn>,
3568         component_instance: RuntimeComponentInstanceIndex,
3569     ) -> Result<Self> {
3570         let sync_call_set = state.push(WaitableSet::default())?;
3571 
3572         Ok(Self {
3573             common: WaitableCommon::default(),
3574             lower_params: Some(lower_params),
3575             lift_result: Some(lift_result),
3576             result: None,
3577             callback,
3578             caller,
3579             call_context: Some(CallContext::default()),
3580             sync_result: None,
3581             cancel_sent: false,
3582             starting_sent: false,
3583             context: [0u32; 2],
3584             subtasks: HashSet::new(),
3585             sync_call_set,
3586             instance: component_instance,
3587             event: None,
3588             wake_on_cancel: None,
3589             function_index: None,
3590             exited: false,
3591         })
3592     }
3593 
3594     /// Dispose of this guest task, reparenting any pending subtasks to the
3595     /// caller.
3596     fn dispose(self, state: &mut ConcurrentState, me: TableId<GuestTask>) -> Result<()> {
3597         // If there are not-yet-delivered completion events for subtasks in
3598         // `self.sync_call_set`, recursively dispose of those subtasks as well.
3599         for waitable in mem::take(&mut state.get_mut(self.sync_call_set)?.ready) {
3600             if let Some(Event::Subtask {
3601                 status: Status::Returned | Status::ReturnCancelled,
3602             }) = waitable.common(state)?.event
3603             {
3604                 waitable.delete_from(state)?;
3605             }
3606         }
3607 
3608         state.delete(self.sync_call_set)?;
3609 
3610         // Reparent any pending subtasks to the caller.
3611         if let Caller::Guest {
3612             task,
3613             instance: runtime_instance,
3614         } = &self.caller
3615         {
3616             let task_mut = state.get_mut(*task)?;
3617             let present = task_mut.subtasks.remove(&me);
3618             assert!(present);
3619 
3620             for subtask in &self.subtasks {
3621                 task_mut.subtasks.insert(*subtask);
3622             }
3623 
3624             for subtask in &self.subtasks {
3625                 state.get_mut(*subtask)?.caller = Caller::Guest {
3626                     task: *task,
3627                     instance: *runtime_instance,
3628                 };
3629             }
3630         } else {
3631             for subtask in &self.subtasks {
3632                 state.get_mut(*subtask)?.caller = Caller::Host {
3633                     tx: None,
3634                     remove_task_automatically: true,
3635                     call_post_return_automatically: true,
3636                 };
3637             }
3638         }
3639 
3640         Ok(())
3641     }
3642 
3643     fn call_post_return_automatically(&self) -> bool {
3644         matches!(
3645             self.caller,
3646             Caller::Guest { .. }
3647                 | Caller::Host {
3648                     call_post_return_automatically: true,
3649                     ..
3650                 }
3651         )
3652     }
3653 }
3654 
3655 impl TableDebug for GuestTask {
3656     fn type_name() -> &'static str {
3657         "GuestTask"
3658     }
3659 }
3660 
3661 /// Represents state common to all kinds of waitables.
3662 #[derive(Default)]
3663 struct WaitableCommon {
3664     /// The currently pending event for this waitable, if any.
3665     event: Option<Event>,
3666     /// The set to which this waitable belongs, if any.
3667     set: Option<TableId<WaitableSet>>,
3668     /// The handle with which the guest refers to this waitable, if any.
3669     handle: Option<u32>,
3670 }
3671 
3672 /// Represents a Component Model Async `waitable`.
3673 #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
3674 enum Waitable {
3675     /// A host task
3676     Host(TableId<HostTask>),
3677     /// A guest task
3678     Guest(TableId<GuestTask>),
3679     /// The read or write end of a stream or future
3680     Transmit(TableId<TransmitHandle>),
3681 }
3682 
3683 impl Waitable {
3684     /// Retrieve the `Waitable` corresponding to the specified guest-visible
3685     /// handle.
3686     fn from_instance(
3687         state: Pin<&mut ComponentInstance>,
3688         caller_instance: RuntimeComponentInstanceIndex,
3689         waitable: u32,
3690     ) -> Result<Self> {
3691         use crate::runtime::vm::component::Waitable;
3692 
3693         let (waitable, kind) = state.guest_tables().0[caller_instance].waitable_rep(waitable)?;
3694 
3695         Ok(match kind {
3696             Waitable::Subtask { is_host: true } => Self::Host(TableId::new(waitable)),
3697             Waitable::Subtask { is_host: false } => Self::Guest(TableId::new(waitable)),
3698             Waitable::Stream | Waitable::Future => Self::Transmit(TableId::new(waitable)),
3699         })
3700     }
3701 
3702     /// Retrieve the host-visible identifier for this `Waitable`.
3703     fn rep(&self) -> u32 {
3704         match self {
3705             Self::Host(id) => id.rep(),
3706             Self::Guest(id) => id.rep(),
3707             Self::Transmit(id) => id.rep(),
3708         }
3709     }
3710 
3711     /// Move this `Waitable` to the specified set (when `set` is `Some(_)`) or
3712     /// remove it from any set it may currently belong to (when `set` is
3713     /// `None`).
3714     fn join(&self, state: &mut ConcurrentState, set: Option<TableId<WaitableSet>>) -> Result<()> {
3715         log::trace!("waitable {self:?} join set {set:?}",);
3716 
3717         let old = mem::replace(&mut self.common(state)?.set, set);
3718 
3719         if let Some(old) = old {
3720             match *self {
3721                 Waitable::Host(id) => state.remove_child(id, old),
3722                 Waitable::Guest(id) => state.remove_child(id, old),
3723                 Waitable::Transmit(id) => state.remove_child(id, old),
3724             }?;
3725 
3726             state.get_mut(old)?.ready.remove(self);
3727         }
3728 
3729         if let Some(set) = set {
3730             match *self {
3731                 Waitable::Host(id) => state.add_child(id, set),
3732                 Waitable::Guest(id) => state.add_child(id, set),
3733                 Waitable::Transmit(id) => state.add_child(id, set),
3734             }?;
3735 
3736             if self.common(state)?.event.is_some() {
3737                 self.mark_ready(state)?;
3738             }
3739         }
3740 
3741         Ok(())
3742     }
3743 
3744     /// Retrieve mutable access to the `WaitableCommon` for this `Waitable`.
3745     fn common<'a>(&self, state: &'a mut ConcurrentState) -> Result<&'a mut WaitableCommon> {
3746         Ok(match self {
3747             Self::Host(id) => &mut state.get_mut(*id)?.common,
3748             Self::Guest(id) => &mut state.get_mut(*id)?.common,
3749             Self::Transmit(id) => &mut state.get_mut(*id)?.common,
3750         })
3751     }
3752 
3753     /// Set or clear the pending event for this waitable and either deliver it
3754     /// to the first waiter, if any, or mark it as ready to be delivered to the
3755     /// next waiter that arrives.
3756     fn set_event(&self, state: &mut ConcurrentState, event: Option<Event>) -> Result<()> {
3757         log::trace!("set event for {self:?}: {event:?}");
3758         self.common(state)?.event = event;
3759         self.mark_ready(state)
3760     }
3761 
3762     /// Take the pending event from this waitable, leaving `None` in its place.
3763     fn take_event(&self, state: &mut ConcurrentState) -> Result<Option<Event>> {
3764         let common = self.common(state)?;
3765         let event = common.event.take();
3766         if let Some(set) = self.common(state)?.set {
3767             state.get_mut(set)?.ready.remove(self);
3768         }
3769         Ok(event)
3770     }
3771 
3772     /// Deliver the current event for this waitable to the first waiter, if any,
3773     /// or else mark it as ready to be delivered to the next waiter that
3774     /// arrives.
3775     fn mark_ready(&self, state: &mut ConcurrentState) -> Result<()> {
3776         if let Some(set) = self.common(state)?.set {
3777             state.get_mut(set)?.ready.insert(*self);
3778             if let Some((task, mode)) = state.get_mut(set)?.waiting.pop_first() {
3779                 let wake_on_cancel = state.get_mut(task)?.wake_on_cancel.take();
3780                 assert!(wake_on_cancel.is_none() || wake_on_cancel == Some(set));
3781 
3782                 let item = match mode {
3783                     WaitMode::Fiber(fiber) => WorkItem::ResumeFiber(fiber),
3784                     WaitMode::Callback => WorkItem::GuestCall(GuestCall {
3785                         task,
3786                         kind: GuestCallKind::DeliverEvent { set: Some(set) },
3787                     }),
3788                 };
3789                 state.push_high_priority(item);
3790             }
3791         }
3792         Ok(())
3793     }
3794 
3795     /// Handle the imminent delivery of the specified event, e.g. by updating
3796     /// the state of the stream or future.
3797     fn on_delivery(&self, instance: Pin<&mut ComponentInstance>, event: Event) {
3798         match event {
3799             Event::FutureRead {
3800                 pending: Some((ty, handle)),
3801                 ..
3802             }
3803             | Event::FutureWrite {
3804                 pending: Some((ty, handle)),
3805                 ..
3806             } => {
3807                 let runtime_instance = instance.component().types()[ty].instance;
3808                 let (rep, state) = instance.guest_tables().0[runtime_instance]
3809                     .future_rep(ty, handle)
3810                     .unwrap();
3811                 assert_eq!(rep, self.rep());
3812                 assert_eq!(*state, TransmitLocalState::Busy);
3813                 *state = match event {
3814                     Event::FutureRead { .. } => TransmitLocalState::Read { done: false },
3815                     Event::FutureWrite { .. } => TransmitLocalState::Write { done: false },
3816                     _ => unreachable!(),
3817                 };
3818             }
3819             Event::StreamRead {
3820                 pending: Some((ty, handle)),
3821                 code,
3822             }
3823             | Event::StreamWrite {
3824                 pending: Some((ty, handle)),
3825                 code,
3826             } => {
3827                 let runtime_instance = instance.component().types()[ty].instance;
3828                 let (rep, state) = instance.guest_tables().0[runtime_instance]
3829                     .stream_rep(ty, handle)
3830                     .unwrap();
3831                 assert_eq!(rep, self.rep());
3832                 assert_eq!(*state, TransmitLocalState::Busy);
3833                 let done = matches!(code, ReturnCode::Dropped(_));
3834                 *state = match event {
3835                     Event::StreamRead { .. } => TransmitLocalState::Read { done },
3836                     Event::StreamWrite { .. } => TransmitLocalState::Write { done },
3837                     _ => unreachable!(),
3838                 };
3839             }
3840             _ => {}
3841         }
3842     }
3843 
3844     /// Remove this waitable from the instance's rep table.
3845     fn delete_from(&self, state: &mut ConcurrentState) -> Result<()> {
3846         match self {
3847             Self::Host(task) => {
3848                 log::trace!("delete host task {task:?}");
3849                 state.delete(*task)?;
3850             }
3851             Self::Guest(task) => {
3852                 log::trace!("delete guest task {task:?}");
3853                 state.delete(*task)?.dispose(state, *task)?;
3854             }
3855             Self::Transmit(task) => {
3856                 state.delete(*task)?;
3857             }
3858         }
3859 
3860         Ok(())
3861     }
3862 }
3863 
3864 impl fmt::Debug for Waitable {
3865     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3866         match self {
3867             Self::Host(id) => write!(f, "{id:?}"),
3868             Self::Guest(id) => write!(f, "{id:?}"),
3869             Self::Transmit(id) => write!(f, "{id:?}"),
3870         }
3871     }
3872 }
3873 
3874 /// Represents a Component Model Async `waitable-set`.
3875 #[derive(Default)]
3876 struct WaitableSet {
3877     /// Which waitables in this set have pending events, if any.
3878     ready: BTreeSet<Waitable>,
3879     /// Which guest tasks are currently waiting on this set, if any.
3880     waiting: BTreeMap<TableId<GuestTask>, WaitMode>,
3881 }
3882 
3883 impl TableDebug for WaitableSet {
3884     fn type_name() -> &'static str {
3885         "WaitableSet"
3886     }
3887 }
3888 
3889 /// Type-erased closure to lower the parameters for a guest task.
3890 type RawLower = Box<
3891     dyn FnOnce(&mut dyn VMStore, Instance, &mut [MaybeUninit<ValRaw>]) -> Result<()> + Send + Sync,
3892 >;
3893 
3894 /// Type-erased closure to lift the result for a guest task.
3895 type RawLift = Box<
3896     dyn FnOnce(&mut dyn VMStore, Instance, &[ValRaw]) -> Result<Box<dyn Any + Send + Sync>>
3897         + Send
3898         + Sync,
3899 >;
3900 
3901 /// Type erased result of a guest task which may be downcast to the expected
3902 /// type by a host caller (or simply ignored in the case of a guest caller; see
3903 /// `DummyResult`).
3904 type LiftedResult = Box<dyn Any + Send + Sync>;
3905 
3906 /// Used to return a result from a `LiftFn` when the actual result has already
3907 /// been lowered to a guest task's stack and linear memory.
3908 struct DummyResult;
3909 
3910 /// Represents the state of a currently executing fiber which has been resumed
3911 /// via `self::poll_fn`.
3912 pub(crate) struct AsyncState {
3913     /// The current instance being polled, if any, which is used to perform
3914     /// checks to ensure that futures are always polled within the correct
3915     /// instance.
3916     current_instance: Option<ComponentInstanceId>,
3917 }
3918 
3919 impl Default for AsyncState {
3920     fn default() -> Self {
3921         Self {
3922             current_instance: None,
3923         }
3924     }
3925 }
3926 
3927 /// Represents the Component Model Async state of a (sub-)component instance.
3928 #[derive(Default)]
3929 struct InstanceState {
3930     /// Whether backpressure is set for this instance
3931     backpressure: bool,
3932     /// Whether this instance can be entered
3933     do_not_enter: bool,
3934     /// Pending calls for this instance which require `Self::backpressure` to be
3935     /// `true` and/or `Self::do_not_enter` to be false before they can proceed.
3936     pending: BTreeMap<TableId<GuestTask>, GuestCallKind>,
3937 }
3938 
3939 /// Represents the Component Model Async state of a top-level component instance
3940 /// (i.e. a `super::ComponentInstance`).
3941 pub struct ConcurrentState {
3942     /// The currently running guest task, if any.
3943     guest_task: Option<TableId<GuestTask>>,
3944     /// The set of pending host and background tasks, if any.
3945     ///
3946     /// See `ComponentInstance::poll_until` for where we temporarily take this
3947     /// out, poll it, then put it back to avoid any mutable aliasing hazards.
3948     futures: AlwaysMut<Option<FuturesUnordered<HostTaskFuture>>>,
3949     /// The table of waitables, waitable sets, etc.
3950     table: AlwaysMut<ResourceTable>,
3951     /// Per (sub-)component instance states.
3952     ///
3953     /// See `InstanceState` for details and note that this map is lazily
3954     /// populated as needed.
3955     // TODO: this can and should be a `PrimaryMap`
3956     instance_states: HashMap<RuntimeComponentInstanceIndex, InstanceState>,
3957     /// The "high priority" work queue for this instance's event loop.
3958     high_priority: Vec<WorkItem>,
3959     /// The "high priority" work queue for this instance's event loop.
3960     low_priority: Vec<WorkItem>,
3961     /// A place to stash the reason a fiber is suspending so that the code which
3962     /// resumed it will know under what conditions the fiber should be resumed
3963     /// again.
3964     suspend_reason: Option<SuspendReason>,
3965     /// A cached fiber which is waiting for work to do.
3966     ///
3967     /// This helps us avoid creating a new fiber for each `GuestCall` work item.
3968     worker: Option<StoreFiber<'static>>,
3969     /// A place to stash the work item for which we're resuming a worker fiber.
3970     worker_item: Option<WorkerItem>,
3971 
3972     /// Reference counts for all component error contexts
3973     ///
3974     /// NOTE: it is possible the global ref count to be *greater* than the sum of
3975     /// (sub)component ref counts as tracked by `error_context_tables`, for
3976     /// example when the host holds one or more references to error contexts.
3977     ///
3978     /// The key of this primary map is often referred to as the "rep" (i.e. host-side
3979     /// component-wide representation) of the index into concurrent state for a given
3980     /// stored `ErrorContext`.
3981     ///
3982     /// Stated another way, `TypeComponentGlobalErrorContextTableIndex` is essentially the same
3983     /// as a `TableId<ErrorContextState>`.
3984     global_error_context_ref_counts:
3985         BTreeMap<TypeComponentGlobalErrorContextTableIndex, GlobalErrorContextRefCount>,
3986 
3987     /// Mirror of type information in `ComponentInstance`, placed here for
3988     /// convenience at the cost of an extra `Arc` clone.
3989     component: Component,
3990 }
3991 
3992 impl ConcurrentState {
3993     pub(crate) fn new(component: &Component) -> Self {
3994         Self {
3995             guest_task: None,
3996             table: AlwaysMut::new(ResourceTable::new()),
3997             futures: AlwaysMut::new(Some(FuturesUnordered::new())),
3998             instance_states: HashMap::new(),
3999             high_priority: Vec::new(),
4000             low_priority: Vec::new(),
4001             suspend_reason: None,
4002             worker: None,
4003             worker_item: None,
4004             global_error_context_ref_counts: BTreeMap::new(),
4005             component: component.clone(),
4006         }
4007     }
4008 
4009     /// Take ownership of any fibers and futures owned by this object.
4010     ///
4011     /// This should be used when disposing of the `Store` containing this object
4012     /// in order to gracefully resolve any and all fibers using
4013     /// `StoreFiber::dispose`.  This is necessary to avoid possible
4014     /// use-after-free bugs due to fibers which may still have access to the
4015     /// `Store`.
4016     ///
4017     /// Additionally, the futures collected with this function should be dropped
4018     /// within a `tls::set` call, which will ensure than any futures closing
4019     /// over an `&Accessor` will have access to the store when dropped, allowing
4020     /// e.g. `WithAccessor[AndValue]` instances to be disposed of without
4021     /// panicking.
4022     ///
4023     /// Note that this will leave the object in an inconsistent and unusable
4024     /// state, so it should only be used just prior to dropping it.
4025     pub(crate) fn take_fibers_and_futures(
4026         &mut self,
4027         fibers: &mut Vec<StoreFiber<'static>>,
4028         futures: &mut Vec<FuturesUnordered<HostTaskFuture>>,
4029     ) {
4030         for entry in self.table.get_mut().iter_mut() {
4031             if let Some(set) = entry.downcast_mut::<WaitableSet>() {
4032                 for mode in mem::take(&mut set.waiting).into_values() {
4033                     if let WaitMode::Fiber(fiber) = mode {
4034                         fibers.push(fiber);
4035                     }
4036                 }
4037             }
4038         }
4039 
4040         if let Some(fiber) = self.worker.take() {
4041             fibers.push(fiber);
4042         }
4043 
4044         let mut take_items = |list| {
4045             for item in mem::take(list) {
4046                 match item {
4047                     WorkItem::ResumeFiber(fiber) => {
4048                         fibers.push(fiber);
4049                     }
4050                     WorkItem::PushFuture(future) => {
4051                         self.futures
4052                             .get_mut()
4053                             .as_mut()
4054                             .unwrap()
4055                             .push(future.into_inner());
4056                     }
4057                     _ => {}
4058                 }
4059             }
4060         };
4061 
4062         take_items(&mut self.high_priority);
4063         take_items(&mut self.low_priority);
4064 
4065         if let Some(them) = self.futures.get_mut().take() {
4066             futures.push(them);
4067         }
4068     }
4069 
4070     fn instance_state(&mut self, instance: RuntimeComponentInstanceIndex) -> &mut InstanceState {
4071         self.instance_states.entry(instance).or_default()
4072     }
4073 
4074     fn push<V: Send + Sync + 'static>(
4075         &mut self,
4076         value: V,
4077     ) -> Result<TableId<V>, ResourceTableError> {
4078         self.table.get_mut().push(value).map(TableId::from)
4079     }
4080 
4081     fn get_mut<V: 'static>(&mut self, id: TableId<V>) -> Result<&mut V, ResourceTableError> {
4082         self.table.get_mut().get_mut(&Resource::from(id))
4083     }
4084 
4085     pub fn add_child<T: 'static, U: 'static>(
4086         &mut self,
4087         child: TableId<T>,
4088         parent: TableId<U>,
4089     ) -> Result<(), ResourceTableError> {
4090         self.table
4091             .get_mut()
4092             .add_child(Resource::from(child), Resource::from(parent))
4093     }
4094 
4095     pub fn remove_child<T: 'static, U: 'static>(
4096         &mut self,
4097         child: TableId<T>,
4098         parent: TableId<U>,
4099     ) -> Result<(), ResourceTableError> {
4100         self.table
4101             .get_mut()
4102             .remove_child(Resource::from(child), Resource::from(parent))
4103     }
4104 
4105     fn delete<V: 'static>(&mut self, id: TableId<V>) -> Result<V, ResourceTableError> {
4106         self.table.get_mut().delete(Resource::from(id))
4107     }
4108 
4109     fn push_future(&mut self, future: HostTaskFuture) {
4110         // Note that we can't directly push to `ConcurrentState::futures` here
4111         // since this may be called from a future that's being polled inside
4112         // `Self::poll_until`, which temporarily removes the `FuturesUnordered`
4113         // so it has exclusive access while polling it.  Therefore, we push a
4114         // work item to the "high priority" queue, which will actually push to
4115         // `ConcurrentState::futures` later.
4116         self.push_high_priority(WorkItem::PushFuture(AlwaysMut::new(future)));
4117     }
4118 
4119     fn push_high_priority(&mut self, item: WorkItem) {
4120         log::trace!("push high priority: {item:?}");
4121         self.high_priority.push(item);
4122     }
4123 
4124     fn push_low_priority(&mut self, item: WorkItem) {
4125         log::trace!("push low priority: {item:?}");
4126         self.low_priority.push(item);
4127     }
4128 
4129     /// Determine whether the instance associated with the specified guest task
4130     /// may be entered (i.e. is not already on the async call stack).
4131     ///
4132     /// This is an additional check on top of the "may_enter" instance flag;
4133     /// it's needed because async-lifted exports with callback functions must
4134     /// not call their own instances directly or indirectly, and due to the
4135     /// "stackless" nature of callback-enabled guest tasks this may happen even
4136     /// if there are no activation records on the stack (i.e. the "may_enter"
4137     /// field is `true`) for that instance.
4138     fn may_enter(&mut self, mut guest_task: TableId<GuestTask>) -> bool {
4139         let guest_instance = self.get_mut(guest_task).unwrap().instance;
4140 
4141         // Walk the task tree back to the root, looking for potential
4142         // reentrance.
4143         //
4144         // TODO: This could be optimized by maintaining a per-`GuestTask` bitset
4145         // such that each bit represents and instance which has been entered by
4146         // that task or an ancestor of that task, in which case this would be a
4147         // constant time check.
4148         loop {
4149             match &self.get_mut(guest_task).unwrap().caller {
4150                 Caller::Host { .. } => break true,
4151                 Caller::Guest { task, instance } => {
4152                     if *instance == guest_instance {
4153                         break false;
4154                     } else {
4155                         guest_task = *task;
4156                     }
4157                 }
4158             }
4159         }
4160     }
4161 
4162     /// Record that we're about to enter a (sub-)component instance which does
4163     /// not support more than one concurrent, stackful activation, meaning it
4164     /// cannot be entered again until the next call returns.
4165     fn enter_instance(&mut self, instance: RuntimeComponentInstanceIndex) {
4166         self.instance_state(instance).do_not_enter = true;
4167     }
4168 
4169     /// Record that we've exited a (sub-)component instance previously entered
4170     /// with `Self::enter_instance` and then calls `Self::partition_pending`.
4171     /// See the documentation for the latter for details.
4172     fn exit_instance(&mut self, instance: RuntimeComponentInstanceIndex) -> Result<()> {
4173         self.instance_state(instance).do_not_enter = false;
4174         self.partition_pending(instance)
4175     }
4176 
4177     /// Iterate over `InstanceState::pending`, moving any ready items into the
4178     /// "high priority" work item queue.
4179     ///
4180     /// See `GuestCall::is_ready` for details.
4181     fn partition_pending(&mut self, instance: RuntimeComponentInstanceIndex) -> Result<()> {
4182         for (task, kind) in mem::take(&mut self.instance_state(instance).pending).into_iter() {
4183             let call = GuestCall { task, kind };
4184             if call.is_ready(self)? {
4185                 self.push_high_priority(WorkItem::GuestCall(call));
4186             } else {
4187                 self.instance_state(instance)
4188                     .pending
4189                     .insert(call.task, call.kind);
4190             }
4191         }
4192 
4193         Ok(())
4194     }
4195 
4196     /// Implements the `backpressure.set` intrinsic.
4197     pub(crate) fn backpressure_set(
4198         &mut self,
4199         caller_instance: RuntimeComponentInstanceIndex,
4200         enabled: u32,
4201     ) -> Result<()> {
4202         let state = self.instance_state(caller_instance);
4203         let old = state.backpressure;
4204         let new = enabled != 0;
4205         state.backpressure = new;
4206 
4207         if old && !new {
4208             // Backpressure was previously enabled and is now disabled; move any
4209             // newly-eligible guest calls to the "high priority" queue.
4210             self.partition_pending(caller_instance)?;
4211         }
4212 
4213         Ok(())
4214     }
4215 
4216     /// Implements the `context.get` intrinsic.
4217     pub(crate) fn context_get(&mut self, slot: u32) -> Result<u32> {
4218         let task = self.guest_task.unwrap();
4219         let val = self.get_mut(task)?.context[usize::try_from(slot).unwrap()];
4220         log::trace!("context_get {task:?} slot {slot} val {val:#x}");
4221         Ok(val)
4222     }
4223 
4224     /// Implements the `context.set` intrinsic.
4225     pub(crate) fn context_set(&mut self, slot: u32, val: u32) -> Result<()> {
4226         let task = self.guest_task.unwrap();
4227         log::trace!("context_set {task:?} slot {slot} val {val:#x}");
4228         self.get_mut(task)?.context[usize::try_from(slot).unwrap()] = val;
4229         Ok(())
4230     }
4231 
4232     fn options(&self, options: OptionsIndex) -> &CanonicalOptions {
4233         &self.component.env_component().options[options]
4234     }
4235 }
4236 
4237 /// Provide a type hint to compiler about the shape of a parameter lower
4238 /// closure.
4239 fn for_any_lower<
4240     F: FnOnce(&mut dyn VMStore, Instance, &mut [MaybeUninit<ValRaw>]) -> Result<()> + Send + Sync,
4241 >(
4242     fun: F,
4243 ) -> F {
4244     fun
4245 }
4246 
4247 /// Provide a type hint to compiler about the shape of a result lift closure.
4248 fn for_any_lift<
4249     F: FnOnce(&mut dyn VMStore, Instance, &[ValRaw]) -> Result<Box<dyn Any + Send + Sync>>
4250         + Send
4251         + Sync,
4252 >(
4253     fun: F,
4254 ) -> F {
4255     fun
4256 }
4257 
4258 /// Wrap the specified future in a `poll_fn` which asserts that the future is
4259 /// only polled from the event loop of the specified `Instance`.
4260 ///
4261 /// See `Instance::run_concurrent` for details.
4262 fn checked<F: Future + Send + 'static>(
4263     instance: Instance,
4264     fut: F,
4265 ) -> impl Future<Output = F::Output> + Send + 'static {
4266     async move {
4267         let mut fut = pin!(fut);
4268         future::poll_fn(move |cx| {
4269             let message = "\
4270                 `Future`s which depend on asynchronous component tasks, streams, or \
4271                 futures to complete may only be polled from the event loop of the \
4272                 instance from which they originated.  Please use \
4273                 `Instance::{run_concurrent,spawn}` to poll or await them.\
4274             ";
4275             tls::try_get(|store| {
4276                 let matched = match store {
4277                     tls::TryGet::Some(store) => {
4278                         let a = store.concurrent_async_state_mut().current_instance;
4279                         a == Some(instance.id().instance())
4280                     }
4281                     tls::TryGet::Taken | tls::TryGet::None => false,
4282                 };
4283 
4284                 if !matched {
4285                     panic!("{message}")
4286                 }
4287             });
4288             fut.as_mut().poll(cx)
4289         })
4290         .await
4291     }
4292 }
4293 
4294 /// Assert that `Instance::run_concurrent` has not been called from within an
4295 /// instance's event loop.
4296 fn check_recursive_run() {
4297     tls::try_get(|store| {
4298         if !matches!(store, tls::TryGet::None) {
4299             panic!("Recursive `Instance::run_concurrent` calls not supported")
4300         }
4301     });
4302 }
4303 
4304 fn unpack_callback_code(code: u32) -> (u32, u32) {
4305     (code & 0xF, code >> 4)
4306 }
4307 
4308 /// Helper struct for packaging parameters to be passed to
4309 /// `ComponentInstance::waitable_check` for calls to `waitable-set.wait` or
4310 /// `waitable-set.poll`.
4311 struct WaitableCheckParams {
4312     set: TableId<WaitableSet>,
4313     options: OptionsIndex,
4314     payload: u32,
4315 }
4316 
4317 /// Helper enum for passing parameters to `ComponentInstance::waitable_check`.
4318 enum WaitableCheck {
4319     Wait(WaitableCheckParams),
4320     Poll(WaitableCheckParams),
4321     Yield,
4322 }
4323 
4324 /// Represents a guest task called from the host, prepared using `prepare_call`.
4325 pub(crate) struct PreparedCall<R> {
4326     /// The guest export to be called
4327     handle: Func,
4328     /// The guest task created by `prepare_call`
4329     task: TableId<GuestTask>,
4330     /// The number of lowered core Wasm parameters to pass to the call.
4331     param_count: usize,
4332     /// The `oneshot::Receiver` to which the result of the call will be
4333     /// delivered when it is available.
4334     rx: oneshot::Receiver<LiftedResult>,
4335     _phantom: PhantomData<R>,
4336 }
4337 
4338 impl<R> PreparedCall<R> {
4339     /// Get a copy of the `TaskId` for this `PreparedCall`.
4340     pub(crate) fn task_id(&self) -> TaskId {
4341         TaskId {
4342             handle: self.handle,
4343             task: self.task,
4344         }
4345     }
4346 }
4347 
4348 /// Represents a task created by `prepare_call`.
4349 pub(crate) struct TaskId {
4350     handle: Func,
4351     task: TableId<GuestTask>,
4352 }
4353 
4354 impl TaskId {
4355     /// Remove the specified task from the concurrent state to which it belongs.
4356     ///
4357     /// This must be used with care to avoid use-after-delete or double-delete
4358     /// bugs.  Specifically, it should only be called on tasks created with the
4359     /// `remove_task_automatically` parameter to `prepare_call` set to `false`,
4360     /// which tells the runtime that the caller is responsible for removing the
4361     /// task from the state; otherwise, it will be removed automatically.  Also,
4362     /// it should only be called once for a given task, and only after either
4363     /// the task has completed or the instance has trapped.
4364     pub(crate) fn remove<T>(&self, store: StoreContextMut<T>) -> Result<()> {
4365         Waitable::Guest(self.task).delete_from(self.handle.instance().concurrent_state_mut(store.0))
4366     }
4367 }
4368 
4369 /// Prepare a call to the specified exported Wasm function, providing functions
4370 /// for lowering the parameters and lifting the result.
4371 ///
4372 /// To enqueue the returned `PreparedCall` in the `ComponentInstance`'s event
4373 /// loop, use `queue_call`.
4374 pub(crate) fn prepare_call<T, R>(
4375     mut store: StoreContextMut<T>,
4376     handle: Func,
4377     param_count: usize,
4378     remove_task_automatically: bool,
4379     call_post_return_automatically: bool,
4380     lower_params: impl FnOnce(Func, StoreContextMut<T>, &mut [MaybeUninit<ValRaw>]) -> Result<()>
4381     + Send
4382     + Sync
4383     + 'static,
4384     lift_result: impl FnOnce(Func, &mut StoreOpaque, &[ValRaw]) -> Result<Box<dyn Any + Send + Sync>>
4385     + Send
4386     + Sync
4387     + 'static,
4388 ) -> Result<PreparedCall<R>> {
4389     let (options, _flags, ty, raw_options) = handle.abi_info(store.0);
4390 
4391     let instance = handle.instance().id().get(store.0);
4392     let task_return_type = instance.component().types()[ty].results;
4393     let component_instance = raw_options.instance;
4394     let callback = options.callback();
4395     let memory = options.memory_raw().map(SendSyncPtr::new);
4396     let string_encoding = options.string_encoding();
4397     let token = StoreToken::new(store.as_context_mut());
4398     let state = handle.instance().concurrent_state_mut(store.0);
4399 
4400     assert!(state.guest_task.is_none());
4401 
4402     let (tx, rx) = oneshot::channel();
4403 
4404     let mut task = GuestTask::new(
4405         state,
4406         Box::new(for_any_lower(move |store, instance, params| {
4407             debug_assert!(instance.id() == handle.instance().id());
4408             lower_params(handle, token.as_context_mut(store), params)
4409         })),
4410         LiftResult {
4411             lift: Box::new(for_any_lift(move |store, instance, result| {
4412                 debug_assert!(instance.id() == handle.instance().id());
4413                 lift_result(handle, store, result)
4414             })),
4415             ty: task_return_type,
4416             memory,
4417             string_encoding,
4418         },
4419         Caller::Host {
4420             tx: Some(tx),
4421             remove_task_automatically,
4422             call_post_return_automatically,
4423         },
4424         callback.map(|callback| {
4425             let callback = SendSyncPtr::new(callback);
4426             Box::new(
4427                 move |store: &mut dyn VMStore,
4428                       instance: Instance,
4429                       runtime_instance,
4430                       event,
4431                       handle| {
4432                     let store = token.as_context_mut(store);
4433                     // SAFETY: Per the contract of `prepare_call`, the callback
4434                     // will remain valid at least as long is this task exists.
4435                     unsafe {
4436                         instance.call_callback(
4437                             store,
4438                             runtime_instance,
4439                             callback,
4440                             event,
4441                             handle,
4442                             call_post_return_automatically,
4443                         )
4444                     }
4445                 },
4446             ) as CallbackFn
4447         }),
4448         component_instance,
4449     )?;
4450     task.function_index = Some(handle.index());
4451 
4452     let task = state.push(task)?;
4453 
4454     Ok(PreparedCall {
4455         handle,
4456         task,
4457         param_count,
4458         rx,
4459         _phantom: PhantomData,
4460     })
4461 }
4462 
4463 /// Queue a call previously prepared using `prepare_call` to be run as part of
4464 /// the associated `ComponentInstance`'s event loop.
4465 ///
4466 /// The returned future will resolve to the result once it is available, but
4467 /// must only be polled via the instance's event loop. See
4468 /// `Instance::run_concurrent` for details.
4469 pub(crate) fn queue_call<T: 'static, R: Send + 'static>(
4470     mut store: StoreContextMut<T>,
4471     prepared: PreparedCall<R>,
4472 ) -> Result<impl Future<Output = Result<R>> + Send + 'static + use<T, R>> {
4473     let PreparedCall {
4474         handle,
4475         task,
4476         param_count,
4477         rx,
4478         ..
4479     } = prepared;
4480 
4481     queue_call0(store.as_context_mut(), handle, task, param_count)?;
4482 
4483     Ok(checked(
4484         handle.instance(),
4485         rx.map(|result| {
4486             result
4487                 .map(|v| *v.downcast().unwrap())
4488                 .map_err(anyhow::Error::from)
4489         }),
4490     ))
4491 }
4492 
4493 /// Queue a call previously prepared using `prepare_call` to be run as part of
4494 /// the associated `ComponentInstance`'s event loop.
4495 fn queue_call0<T: 'static>(
4496     store: StoreContextMut<T>,
4497     handle: Func,
4498     guest_task: TableId<GuestTask>,
4499     param_count: usize,
4500 ) -> Result<()> {
4501     let (options, flags, _ty, raw_options) = handle.abi_info(store.0);
4502     let is_concurrent = raw_options.async_;
4503     let instance = handle.instance();
4504     let callee = handle.lifted_core_func(store.0);
4505     let callback = options.callback();
4506     let post_return = handle.post_return_core_func(store.0);
4507 
4508     log::trace!("queueing call {guest_task:?}");
4509 
4510     let instance_flags = if callback.is_none() {
4511         None
4512     } else {
4513         Some(flags)
4514     };
4515 
4516     // SAFETY: `callee`, `callback`, and `post_return` are valid pointers
4517     // (with signatures appropriate for this call) and will remain valid as
4518     // long as this instance is valid.
4519     unsafe {
4520         instance.queue_call(
4521             store,
4522             guest_task,
4523             SendSyncPtr::new(callee),
4524             param_count,
4525             1,
4526             instance_flags,
4527             is_concurrent,
4528             callback.map(SendSyncPtr::new),
4529             post_return.map(SendSyncPtr::new),
4530         )
4531     }
4532 }
4533