1b271e452SJoel Dice use crate::component::RuntimeInstance;
2d4242001SAdam Bratschi-Kaye use crate::component::func::HostFunc;
3d4242001SAdam Bratschi-Kaye use crate::component::matching::InstanceType;
4e33836c0SAlex Crichton use crate::component::store::{ComponentInstanceId, StoreComponentInstanceId};
53171ef6dSAlex Crichton use crate::component::{
690ac295eSAlex Crichton     Component, ComponentExportIndex, ComponentNamedList, Func, Lift, Lower, ResourceType,
790ac295eSAlex Crichton     TypedFunc, types::ComponentItem,
83171ef6dSAlex Crichton };
9d4242001SAdam Bratschi-Kaye use crate::instance::OwnedImports;
10d4242001SAdam Bratschi-Kaye use crate::linker::DefinitionType;
1181a89169SAlex Crichton use crate::prelude::*;
1298499653SAlex Crichton use crate::runtime::vm::component::{ComponentInstance, TypedResource, TypedResourceIndex};
132b832281SAlex Crichton use crate::runtime::vm::{self, VMFuncRef};
14cc8d04f4SAlex Crichton use crate::store::{AsStoreOpaque, Asyncness, StoreOpaque};
151a9e6235SPat Hickey use crate::{AsContext, AsContextMut, Engine, Module, StoreContextMut};
1681a89169SAlex Crichton use alloc::sync::Arc;
1781a89169SAlex Crichton use core::marker;
187e28c254SAlex Crichton use core::pin::Pin;
19b86b9682SAlex Crichton use core::ptr::NonNull;
2090ac295eSAlex Crichton use wasmtime_environ::{EngineOrModuleTypeIndex, component::*};
212b832281SAlex Crichton use wasmtime_environ::{EntityIndex, EntityType, PrimaryMap};
22d4242001SAdam Bratschi-Kaye 
23d4242001SAdam Bratschi-Kaye /// An instantiated component.
24d4242001SAdam Bratschi-Kaye ///
256d105f4dSAlex Crichton /// This type represents an instantiated [`Component`](super::Component).
266d105f4dSAlex Crichton /// Instances have exports which can be accessed through functions such as
273171ef6dSAlex Crichton /// [`Instance::get_func`] or [`Instance::get_export`]. Instances are owned by a
286d105f4dSAlex Crichton /// [`Store`](crate::Store) and all methods require a handle to the store.
296d105f4dSAlex Crichton ///
306d105f4dSAlex Crichton /// Component instances are created through
316d105f4dSAlex Crichton /// [`Linker::instantiate`](super::Linker::instantiate) and its family of
326d105f4dSAlex Crichton /// methods.
336d105f4dSAlex Crichton ///
346d105f4dSAlex Crichton /// This type is similar to the core wasm version
356d105f4dSAlex Crichton /// [`wasmtime::Instance`](crate::Instance) except that it represents an
366d105f4dSAlex Crichton /// instantiated component instead of an instantiated module.
37e33836c0SAlex Crichton #[derive(Copy, Clone, Debug)]
38e33836c0SAlex Crichton #[repr(transparent)]
398fb9d189SAlex Crichton pub struct Instance {
40e33836c0SAlex Crichton     id: StoreComponentInstanceId,
41d4242001SAdam Bratschi-Kaye }
42d4242001SAdam Bratschi-Kaye 
438fb9d189SAlex Crichton // Double-check that the C representation in `component/instance.h` matches our
448fb9d189SAlex Crichton // in-Rust representation here in terms of size/alignment/etc.
458fb9d189SAlex Crichton const _: () = {
468fb9d189SAlex Crichton     #[repr(C)]
475603ee7bSAlex Crichton     struct C(u64, u32);
488fb9d189SAlex Crichton     assert!(core::mem::size_of::<C>() == core::mem::size_of::<Instance>());
498fb9d189SAlex Crichton     assert!(core::mem::align_of::<C>() == core::mem::align_of::<Instance>());
50e33836c0SAlex Crichton     assert!(core::mem::offset_of!(Instance, id) == 0);
518fb9d189SAlex Crichton };
528fb9d189SAlex Crichton 
53d4242001SAdam Bratschi-Kaye impl Instance {
548fb9d189SAlex Crichton     /// Creates a raw `Instance` from the internal identifiers within the store.
from_wasmtime(store: &StoreOpaque, id: ComponentInstanceId) -> Instance557aea45abSAlex Crichton     pub(crate) fn from_wasmtime(store: &StoreOpaque, id: ComponentInstanceId) -> Instance {
568fb9d189SAlex Crichton         Instance {
57e33836c0SAlex Crichton             id: StoreComponentInstanceId::new(store.id(), id),
588fb9d189SAlex Crichton         }
598fb9d189SAlex Crichton     }
608fb9d189SAlex Crichton 
613171ef6dSAlex Crichton     /// Looks up an exported function by name within this [`Instance`].
62d4242001SAdam Bratschi-Kaye     ///
633171ef6dSAlex Crichton     /// The `store` argument provided must be the store that this instance
643171ef6dSAlex Crichton     /// lives within and the `name` argument is the lookup key by which to find
653171ef6dSAlex Crichton     /// the exported function. If the function is found then `Some` is returned
663171ef6dSAlex Crichton     /// and otherwise `None` is returned.
67d4242001SAdam Bratschi-Kaye     ///
683171ef6dSAlex Crichton     /// The `name` here can be a string such as `&str` or it can be a
693171ef6dSAlex Crichton     /// [`ComponentExportIndex`] which is loaded prior from a [`Component`].
70d4242001SAdam Bratschi-Kaye     ///
71d4242001SAdam Bratschi-Kaye     /// # Panics
72d4242001SAdam Bratschi-Kaye     ///
73d4242001SAdam Bratschi-Kaye     /// Panics if `store` does not own this instance.
743171ef6dSAlex Crichton     ///
753171ef6dSAlex Crichton     /// # Examples
763171ef6dSAlex Crichton     ///
773171ef6dSAlex Crichton     /// Looking up a function which is exported from the root of a component:
783171ef6dSAlex Crichton     ///
793171ef6dSAlex Crichton     /// ```
803171ef6dSAlex Crichton     /// use wasmtime::{Engine, Store};
813171ef6dSAlex Crichton     /// use wasmtime::component::{Component, Linker};
823171ef6dSAlex Crichton     ///
833171ef6dSAlex Crichton     /// # fn main() -> wasmtime::Result<()> {
843171ef6dSAlex Crichton     /// let engine = Engine::default();
853171ef6dSAlex Crichton     /// let component = Component::new(
863171ef6dSAlex Crichton     ///     &engine,
873171ef6dSAlex Crichton     ///     r#"
883171ef6dSAlex Crichton     ///         (component
893171ef6dSAlex Crichton     ///             (core module $m
903171ef6dSAlex Crichton     ///                 (func (export "f"))
913171ef6dSAlex Crichton     ///             )
923171ef6dSAlex Crichton     ///             (core instance $i (instantiate $m))
933171ef6dSAlex Crichton     ///             (func (export "f")
943171ef6dSAlex Crichton     ///                 (canon lift (core func $i "f")))
953171ef6dSAlex Crichton     ///         )
963171ef6dSAlex Crichton     ///     "#,
973171ef6dSAlex Crichton     /// )?;
983171ef6dSAlex Crichton     ///
993171ef6dSAlex Crichton     /// // Look up the function by name
1003171ef6dSAlex Crichton     /// let mut store = Store::new(&engine, ());
1013171ef6dSAlex Crichton     /// let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
1023171ef6dSAlex Crichton     /// let func = instance.get_func(&mut store, "f").unwrap();
1033171ef6dSAlex Crichton     ///
1043171ef6dSAlex Crichton     /// // The function can also be looked up by an index via a precomputed index.
10595cc0297SPat Hickey     /// let export = component.get_export_index(None, "f").unwrap();
1063171ef6dSAlex Crichton     /// let func = instance.get_func(&mut store, &export).unwrap();
1073171ef6dSAlex Crichton     /// # Ok(())
1083171ef6dSAlex Crichton     /// # }
1093171ef6dSAlex Crichton     /// ```
1103171ef6dSAlex Crichton     ///
1113171ef6dSAlex Crichton     /// Looking up a function which is exported from a nested instance:
1123171ef6dSAlex Crichton     ///
1133171ef6dSAlex Crichton     /// ```
1143171ef6dSAlex Crichton     /// use wasmtime::{Engine, Store};
1153171ef6dSAlex Crichton     /// use wasmtime::component::{Component, Linker};
1163171ef6dSAlex Crichton     ///
1173171ef6dSAlex Crichton     /// # fn main() -> wasmtime::Result<()> {
1183171ef6dSAlex Crichton     /// let engine = Engine::default();
1193171ef6dSAlex Crichton     /// let component = Component::new(
1203171ef6dSAlex Crichton     ///     &engine,
1213171ef6dSAlex Crichton     ///     r#"
1223171ef6dSAlex Crichton     ///         (component
1233171ef6dSAlex Crichton     ///             (core module $m
1243171ef6dSAlex Crichton     ///                 (func (export "f"))
1253171ef6dSAlex Crichton     ///             )
1263171ef6dSAlex Crichton     ///             (core instance $i (instantiate $m))
1273171ef6dSAlex Crichton     ///             (func $f
1283171ef6dSAlex Crichton     ///                 (canon lift (core func $i "f")))
1293171ef6dSAlex Crichton     ///
1303171ef6dSAlex Crichton     ///             (instance $i
1313171ef6dSAlex Crichton     ///                 (export "f" (func $f)))
1323171ef6dSAlex Crichton     ///             (export "i" (instance $i))
1333171ef6dSAlex Crichton     ///         )
1343171ef6dSAlex Crichton     ///     "#,
1353171ef6dSAlex Crichton     /// )?;
1363171ef6dSAlex Crichton     ///
1373171ef6dSAlex Crichton     /// // First look up the exported instance, then use that to lookup the
1383171ef6dSAlex Crichton     /// // exported function.
13995cc0297SPat Hickey     /// let instance_index = component.get_export_index(None, "i").unwrap();
14095cc0297SPat Hickey     /// let func_index = component.get_export_index(Some(&instance_index), "f").unwrap();
1413171ef6dSAlex Crichton     ///
1423171ef6dSAlex Crichton     /// // Then use `func_index` at runtime.
1433171ef6dSAlex Crichton     /// let mut store = Store::new(&engine, ());
1443171ef6dSAlex Crichton     /// let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
1453171ef6dSAlex Crichton     /// let func = instance.get_func(&mut store, &func_index).unwrap();
1463171ef6dSAlex Crichton     ///
1473171ef6dSAlex Crichton     /// // Alternatively the `instance` can be used directly in conjunction with
14895cc0297SPat Hickey     /// // the `get_export_index` method.
14995cc0297SPat Hickey     /// let instance_index = instance.get_export_index(&mut store, None, "i").unwrap();
15095cc0297SPat Hickey     /// let func_index = instance.get_export_index(&mut store, Some(&instance_index), "f").unwrap();
1513171ef6dSAlex Crichton     /// let func = instance.get_func(&mut store, &func_index).unwrap();
1523171ef6dSAlex Crichton     /// # Ok(())
1533171ef6dSAlex Crichton     /// # }
1543171ef6dSAlex Crichton     /// ```
get_func( &self, mut store: impl AsContextMut, name: impl InstanceExportLookup, ) -> Option<Func>1553171ef6dSAlex Crichton     pub fn get_func(
1563171ef6dSAlex Crichton         &self,
1573171ef6dSAlex Crichton         mut store: impl AsContextMut,
1583171ef6dSAlex Crichton         name: impl InstanceExportLookup,
1593171ef6dSAlex Crichton     ) -> Option<Func> {
1603171ef6dSAlex Crichton         let store = store.as_context_mut().0;
1617e28c254SAlex Crichton         let instance = self.id.get(store);
162e33836c0SAlex Crichton         let component = instance.component();
163e33836c0SAlex Crichton 
164e33836c0SAlex Crichton         // Validate that `name` exists within `self.`
165e33836c0SAlex Crichton         let index = name.lookup(component)?;
166e33836c0SAlex Crichton 
167e33836c0SAlex Crichton         // Validate that `index` is indeed a lifted function.
168e33836c0SAlex Crichton         match &component.env_component().export_items[index] {
169e33836c0SAlex Crichton             Export::LiftedFunction { .. } => {}
170e33836c0SAlex Crichton             _ => return None,
1718fb9d189SAlex Crichton         }
172e33836c0SAlex Crichton 
173e33836c0SAlex Crichton         // And package up the indices!
174e33836c0SAlex Crichton         Some(Func::from_lifted_func(*self, index))
175d4242001SAdam Bratschi-Kaye     }
176d4242001SAdam Bratschi-Kaye 
177d4242001SAdam Bratschi-Kaye     /// Looks up an exported [`Func`] value by name and with its type.
178d4242001SAdam Bratschi-Kaye     ///
179d4242001SAdam Bratschi-Kaye     /// This function is a convenience wrapper over [`Instance::get_func`] and
180d4242001SAdam Bratschi-Kaye     /// [`Func::typed`]. For more information see the linked documentation.
181d4242001SAdam Bratschi-Kaye     ///
182d4242001SAdam Bratschi-Kaye     /// Returns an error if `name` isn't a function export or if the export's
183d4242001SAdam Bratschi-Kaye     /// type did not match `Params` or `Results`
184d4242001SAdam Bratschi-Kaye     ///
185d4242001SAdam Bratschi-Kaye     /// # Panics
186d4242001SAdam Bratschi-Kaye     ///
187d4242001SAdam Bratschi-Kaye     /// Panics if `store` does not own this instance.
get_typed_func<Params, Results>( &self, mut store: impl AsContextMut, name: impl InstanceExportLookup, ) -> Result<TypedFunc<Params, Results>> where Params: ComponentNamedList + Lower, Results: ComponentNamedList + Lift,188d4242001SAdam Bratschi-Kaye     pub fn get_typed_func<Params, Results>(
189d4242001SAdam Bratschi-Kaye         &self,
190d4242001SAdam Bratschi-Kaye         mut store: impl AsContextMut,
1913171ef6dSAlex Crichton         name: impl InstanceExportLookup,
192d4242001SAdam Bratschi-Kaye     ) -> Result<TypedFunc<Params, Results>>
193d4242001SAdam Bratschi-Kaye     where
194d4242001SAdam Bratschi-Kaye         Params: ComponentNamedList + Lower,
195d4242001SAdam Bratschi-Kaye         Results: ComponentNamedList + Lift,
196d4242001SAdam Bratschi-Kaye     {
197d4242001SAdam Bratschi-Kaye         let f = self
198d4242001SAdam Bratschi-Kaye             .get_func(store.as_context_mut(), name)
199ff33e949SNick Fitzgerald             .ok_or_else(|| format_err!("failed to find function export"))?;
200d4242001SAdam Bratschi-Kaye         Ok(f.typed::<Params, Results>(store)
2013171ef6dSAlex Crichton             .with_context(|| format!("failed to convert function to given type"))?)
202d4242001SAdam Bratschi-Kaye     }
203d4242001SAdam Bratschi-Kaye 
2043171ef6dSAlex Crichton     /// Looks up an exported module by name within this [`Instance`].
205d4242001SAdam Bratschi-Kaye     ///
2063171ef6dSAlex Crichton     /// The `store` argument provided must be the store that this instance
2073171ef6dSAlex Crichton     /// lives within and the `name` argument is the lookup key by which to find
2083171ef6dSAlex Crichton     /// the exported module. If the module is found then `Some` is returned
2093171ef6dSAlex Crichton     /// and otherwise `None` is returned.
2103171ef6dSAlex Crichton     ///
2113171ef6dSAlex Crichton     /// The `name` here can be a string such as `&str` or it can be a
2123171ef6dSAlex Crichton     /// [`ComponentExportIndex`] which is loaded prior from a [`Component`].
2133171ef6dSAlex Crichton     ///
2143171ef6dSAlex Crichton     /// For some examples see [`Instance::get_func`] for loading values from a
2153171ef6dSAlex Crichton     /// component.
216d4242001SAdam Bratschi-Kaye     ///
217d4242001SAdam Bratschi-Kaye     /// # Panics
218d4242001SAdam Bratschi-Kaye     ///
219d4242001SAdam Bratschi-Kaye     /// Panics if `store` does not own this instance.
get_module( &self, mut store: impl AsContextMut, name: impl InstanceExportLookup, ) -> Option<Module>2203171ef6dSAlex Crichton     pub fn get_module(
2213171ef6dSAlex Crichton         &self,
2223171ef6dSAlex Crichton         mut store: impl AsContextMut,
2233171ef6dSAlex Crichton         name: impl InstanceExportLookup,
2243171ef6dSAlex Crichton     ) -> Option<Module> {
2253171ef6dSAlex Crichton         let store = store.as_context_mut().0;
2268fb9d189SAlex Crichton         let (instance, export) = self.lookup_export(store, name)?;
2273171ef6dSAlex Crichton         match export {
2283171ef6dSAlex Crichton             Export::ModuleStatic { index, .. } => {
2298fb9d189SAlex Crichton                 Some(instance.component().static_module(*index).clone())
2303171ef6dSAlex Crichton             }
2318fb9d189SAlex Crichton             Export::ModuleImport { import, .. } => match instance.runtime_import(*import) {
2323171ef6dSAlex Crichton                 RuntimeImport::Module(m) => Some(m.clone()),
2333171ef6dSAlex Crichton                 _ => unreachable!(),
2343171ef6dSAlex Crichton             },
2353171ef6dSAlex Crichton             _ => None,
2363171ef6dSAlex Crichton         }
237d4242001SAdam Bratschi-Kaye     }
238d4242001SAdam Bratschi-Kaye 
239d4242001SAdam Bratschi-Kaye     /// Looks up an exported resource type by name within this [`Instance`].
240d4242001SAdam Bratschi-Kaye     ///
2413171ef6dSAlex Crichton     /// The `store` argument provided must be the store that this instance
2423171ef6dSAlex Crichton     /// lives within and the `name` argument is the lookup key by which to find
2433171ef6dSAlex Crichton     /// the exported resource. If the resource is found then `Some` is returned
2443171ef6dSAlex Crichton     /// and otherwise `None` is returned.
2453171ef6dSAlex Crichton     ///
2463171ef6dSAlex Crichton     /// The `name` here can be a string such as `&str` or it can be a
2473171ef6dSAlex Crichton     /// [`ComponentExportIndex`] which is loaded prior from a [`Component`].
2483171ef6dSAlex Crichton     ///
2493171ef6dSAlex Crichton     /// For some examples see [`Instance::get_func`] for loading values from a
2503171ef6dSAlex Crichton     /// component.
251d4242001SAdam Bratschi-Kaye     ///
252d4242001SAdam Bratschi-Kaye     /// # Panics
253d4242001SAdam Bratschi-Kaye     ///
254d4242001SAdam Bratschi-Kaye     /// Panics if `store` does not own this instance.
get_resource( &self, mut store: impl AsContextMut, name: impl InstanceExportLookup, ) -> Option<ResourceType>2553171ef6dSAlex Crichton     pub fn get_resource(
2563171ef6dSAlex Crichton         &self,
2573171ef6dSAlex Crichton         mut store: impl AsContextMut,
2583171ef6dSAlex Crichton         name: impl InstanceExportLookup,
2593171ef6dSAlex Crichton     ) -> Option<ResourceType> {
2603171ef6dSAlex Crichton         let store = store.as_context_mut().0;
2618fb9d189SAlex Crichton         let (instance, export) = self.lookup_export(store, name)?;
2623171ef6dSAlex Crichton         match export {
2638fb9d189SAlex Crichton             Export::Type(TypeDef::Resource(id)) => {
2648fb9d189SAlex Crichton                 Some(InstanceType::new(instance).resource_type(*id))
2658fb9d189SAlex Crichton             }
2663171ef6dSAlex Crichton             Export::Type(_)
2673171ef6dSAlex Crichton             | Export::LiftedFunction { .. }
2683171ef6dSAlex Crichton             | Export::ModuleStatic { .. }
2693171ef6dSAlex Crichton             | Export::ModuleImport { .. }
2703171ef6dSAlex Crichton             | Export::Instance { .. } => None,
2713171ef6dSAlex Crichton         }
2723171ef6dSAlex Crichton     }
2733171ef6dSAlex Crichton 
27495cc0297SPat Hickey     /// A methods similar to [`Component::get_export`] except for this
2753171ef6dSAlex Crichton     /// instance.
2763171ef6dSAlex Crichton     ///
2773171ef6dSAlex Crichton     /// This method will lookup the `name` provided within the `instance`
27895cc0297SPat Hickey     /// provided and return a [`ComponentItem`] describing the export,
27995cc0297SPat Hickey     /// and [`ComponentExportIndex`] which can be passed other `get_*`
28095cc0297SPat Hickey     /// functions like [`Instance::get_func`].
28195cc0297SPat Hickey     ///
28295cc0297SPat Hickey     /// The [`ComponentItem`] is more expensive to compute than the
28395cc0297SPat Hickey     /// [`ComponentExportIndex`]. If you are not consuming the
28495cc0297SPat Hickey     /// [`ComponentItem`], use [`Instance::get_export_index`] instead.
2853171ef6dSAlex Crichton     ///
2863171ef6dSAlex Crichton     /// # Panics
2873171ef6dSAlex Crichton     ///
2883171ef6dSAlex Crichton     /// Panics if `store` does not own this instance.
get_export( &self, mut store: impl AsContextMut, instance: Option<&ComponentExportIndex>, name: &str, ) -> Option<(ComponentItem, ComponentExportIndex)>2893171ef6dSAlex Crichton     pub fn get_export(
2903171ef6dSAlex Crichton         &self,
2913171ef6dSAlex Crichton         mut store: impl AsContextMut,
2923171ef6dSAlex Crichton         instance: Option<&ComponentExportIndex>,
2933171ef6dSAlex Crichton         name: &str,
29495cc0297SPat Hickey     ) -> Option<(ComponentItem, ComponentExportIndex)> {
2953171ef6dSAlex Crichton         self._get_export(store.as_context_mut().0, instance, name)
2963171ef6dSAlex Crichton     }
2973171ef6dSAlex Crichton 
_get_export( &self, store: &StoreOpaque, instance: Option<&ComponentExportIndex>, name: &str, ) -> Option<(ComponentItem, ComponentExportIndex)>2983171ef6dSAlex Crichton     fn _get_export(
2993171ef6dSAlex Crichton         &self,
3003171ef6dSAlex Crichton         store: &StoreOpaque,
3013171ef6dSAlex Crichton         instance: Option<&ComponentExportIndex>,
3023171ef6dSAlex Crichton         name: &str,
30395cc0297SPat Hickey     ) -> Option<(ComponentItem, ComponentExportIndex)> {
3047e28c254SAlex Crichton         let data = self.id().get(store);
3058fb9d189SAlex Crichton         let component = data.component();
3068fb9d189SAlex Crichton         let index = component.lookup_export_index(instance, name)?;
30795cc0297SPat Hickey         let item = ComponentItem::from_export(
30895cc0297SPat Hickey             &store.engine(),
3098fb9d189SAlex Crichton             &component.env_component().export_items[index],
3108fb9d189SAlex Crichton             &InstanceType::new(data),
31195cc0297SPat Hickey         );
31295cc0297SPat Hickey         Some((
31395cc0297SPat Hickey             item,
31495cc0297SPat Hickey             ComponentExportIndex {
3158fb9d189SAlex Crichton                 id: data.component().id(),
31695cc0297SPat Hickey                 index,
31795cc0297SPat Hickey             },
31895cc0297SPat Hickey         ))
31995cc0297SPat Hickey     }
32095cc0297SPat Hickey 
32195cc0297SPat Hickey     /// A methods similar to [`Component::get_export_index`] except for this
32295cc0297SPat Hickey     /// instance.
32395cc0297SPat Hickey     ///
32495cc0297SPat Hickey     /// This method will lookup the `name` provided within the `instance`
32595cc0297SPat Hickey     /// provided and return a [`ComponentExportIndex`] which can be passed
32695cc0297SPat Hickey     /// other `get_*` functions like [`Instance::get_func`].
32795cc0297SPat Hickey     ///
32895cc0297SPat Hickey     /// If you need the [`ComponentItem`] corresponding to this export, use
32995cc0297SPat Hickey     /// the [`Instance::get_export`] instead.
33095cc0297SPat Hickey     ///
33195cc0297SPat Hickey     /// # Panics
33295cc0297SPat Hickey     ///
33395cc0297SPat Hickey     /// Panics if `store` does not own this instance.
get_export_index( &self, mut store: impl AsContextMut, instance: Option<&ComponentExportIndex>, name: &str, ) -> Option<ComponentExportIndex>33495cc0297SPat Hickey     pub fn get_export_index(
33595cc0297SPat Hickey         &self,
33695cc0297SPat Hickey         mut store: impl AsContextMut,
33795cc0297SPat Hickey         instance: Option<&ComponentExportIndex>,
33895cc0297SPat Hickey         name: &str,
33995cc0297SPat Hickey     ) -> Option<ComponentExportIndex> {
3407e28c254SAlex Crichton         let data = self.id().get(store.as_context_mut().0);
3418fb9d189SAlex Crichton         let index = data.component().lookup_export_index(instance, name)?;
3423171ef6dSAlex Crichton         Some(ComponentExportIndex {
3438fb9d189SAlex Crichton             id: data.component().id(),
3443171ef6dSAlex Crichton             index,
3453171ef6dSAlex Crichton         })
3463171ef6dSAlex Crichton     }
3473171ef6dSAlex Crichton 
lookup_export<'a>( &self, store: &'a StoreOpaque, name: impl InstanceExportLookup, ) -> Option<(&'a ComponentInstance, &'a Export)>3483171ef6dSAlex Crichton     fn lookup_export<'a>(
3493171ef6dSAlex Crichton         &self,
3503171ef6dSAlex Crichton         store: &'a StoreOpaque,
3513171ef6dSAlex Crichton         name: impl InstanceExportLookup,
3528fb9d189SAlex Crichton     ) -> Option<(&'a ComponentInstance, &'a Export)> {
3537e28c254SAlex Crichton         let data = self.id().get(store);
3548fb9d189SAlex Crichton         let index = name.lookup(data.component())?;
3558fb9d189SAlex Crichton         Some((data, &data.component().env_component().export_items[index]))
3563171ef6dSAlex Crichton     }
3571a9e6235SPat Hickey 
3589d40c6ebSAlex Crichton     /// Returns the [`InstancePre`] that was used to create this instance.
instance_pre<T>(&self, store: impl AsContext<Data = T>) -> InstancePre<T>3598fb9d189SAlex Crichton     pub fn instance_pre<T>(&self, store: impl AsContext<Data = T>) -> InstancePre<T> {
3601a9e6235SPat Hickey         // This indexing operation asserts the Store owns the Instance.
3611a9e6235SPat Hickey         // Therefore, the InstancePre<T> must match the Store<T>.
3627e28c254SAlex Crichton         let data = self.id().get(store.as_context().0);
3638fb9d189SAlex Crichton 
3648fb9d189SAlex Crichton         // SAFETY: calling this method safely here relies on matching the `T`
3658fb9d189SAlex Crichton         // in `InstancePre<T>` to the store itself, which is happening in the
3668fb9d189SAlex Crichton         // type signature just above by ensuring the store's data is `T` which
3678fb9d189SAlex Crichton         // matches the return value.
3688fb9d189SAlex Crichton         unsafe { data.instance_pre() }
3691a9e6235SPat Hickey     }
3708fb9d189SAlex Crichton 
id(&self) -> StoreComponentInstanceId371e33836c0SAlex Crichton     pub(crate) fn id(&self) -> StoreComponentInstanceId {
372e33836c0SAlex Crichton         self.id
3731a9e6235SPat Hickey     }
3744233014bSAlex Crichton 
3754233014bSAlex Crichton     /// Implementation of the `resource.new` intrinsic for `i32`
3764233014bSAlex Crichton     /// representations.
resource_new32( self, store: &mut StoreOpaque, ty: TypeResourceTableIndex, rep: u32, ) -> Result<u32>3774233014bSAlex Crichton     pub(crate) fn resource_new32(
3784233014bSAlex Crichton         self,
3794233014bSAlex Crichton         store: &mut StoreOpaque,
3804233014bSAlex Crichton         ty: TypeResourceTableIndex,
3814233014bSAlex Crichton         rep: u32,
3824233014bSAlex Crichton     ) -> Result<u32> {
38398499653SAlex Crichton         store
38498499653SAlex Crichton             .component_resource_tables(Some(self))
38598499653SAlex Crichton             .resource_new(TypedResource::Component { ty, rep })
3864233014bSAlex Crichton     }
3874233014bSAlex Crichton 
3884233014bSAlex Crichton     /// Implementation of the `resource.rep` intrinsic for `i32`
3894233014bSAlex Crichton     /// representations.
resource_rep32( self, store: &mut StoreOpaque, ty: TypeResourceTableIndex, index: u32, ) -> Result<u32>3904233014bSAlex Crichton     pub(crate) fn resource_rep32(
3914233014bSAlex Crichton         self,
3924233014bSAlex Crichton         store: &mut StoreOpaque,
3934233014bSAlex Crichton         ty: TypeResourceTableIndex,
3944233014bSAlex Crichton         index: u32,
3954233014bSAlex Crichton     ) -> Result<u32> {
39698499653SAlex Crichton         store
39798499653SAlex Crichton             .component_resource_tables(Some(self))
39898499653SAlex Crichton             .resource_rep(TypedResourceIndex::Component { ty, index })
3994233014bSAlex Crichton     }
4004233014bSAlex Crichton 
4014233014bSAlex Crichton     /// Implementation of the `resource.drop` intrinsic.
resource_drop( self, store: &mut StoreOpaque, ty: TypeResourceTableIndex, index: u32, ) -> Result<Option<u32>>4024233014bSAlex Crichton     pub(crate) fn resource_drop(
4034233014bSAlex Crichton         self,
4044233014bSAlex Crichton         store: &mut StoreOpaque,
4054233014bSAlex Crichton         ty: TypeResourceTableIndex,
4064233014bSAlex Crichton         index: u32,
4074233014bSAlex Crichton     ) -> Result<Option<u32>> {
40898499653SAlex Crichton         store
40998499653SAlex Crichton             .component_resource_tables(Some(self))
41098499653SAlex Crichton             .resource_drop(TypedResourceIndex::Component { ty, index })
4114233014bSAlex Crichton     }
4124233014bSAlex Crichton 
resource_transfer_own( self, store: &mut StoreOpaque, index: u32, src: TypeResourceTableIndex, dst: TypeResourceTableIndex, ) -> Result<u32>4134233014bSAlex Crichton     pub(crate) fn resource_transfer_own(
4144233014bSAlex Crichton         self,
4154233014bSAlex Crichton         store: &mut StoreOpaque,
4164233014bSAlex Crichton         index: u32,
4174233014bSAlex Crichton         src: TypeResourceTableIndex,
4184233014bSAlex Crichton         dst: TypeResourceTableIndex,
4194233014bSAlex Crichton     ) -> Result<u32> {
42098499653SAlex Crichton         let mut tables = store.component_resource_tables(Some(self));
4214233014bSAlex Crichton         let rep = tables.resource_lift_own(TypedResourceIndex::Component { ty: src, index })?;
4224233014bSAlex Crichton         tables.resource_lower_own(TypedResource::Component { ty: dst, rep })
4234233014bSAlex Crichton     }
4244233014bSAlex Crichton 
resource_transfer_borrow( self, store: &mut StoreOpaque, index: u32, src: TypeResourceTableIndex, dst: TypeResourceTableIndex, ) -> Result<u32>4254233014bSAlex Crichton     pub(crate) fn resource_transfer_borrow(
4264233014bSAlex Crichton         self,
4274233014bSAlex Crichton         store: &mut StoreOpaque,
4284233014bSAlex Crichton         index: u32,
4294233014bSAlex Crichton         src: TypeResourceTableIndex,
4304233014bSAlex Crichton         dst: TypeResourceTableIndex,
4314233014bSAlex Crichton     ) -> Result<u32> {
4327e28c254SAlex Crichton         let dst_owns_resource = self.id().get(store).resource_owned_by_own_instance(dst);
43398499653SAlex Crichton         let mut tables = store.component_resource_tables(Some(self));
4344233014bSAlex Crichton         let rep = tables.resource_lift_borrow(TypedResourceIndex::Component { ty: src, index })?;
4354233014bSAlex Crichton         // Implement `lower_borrow`'s special case here where if a borrow's
4364233014bSAlex Crichton         // resource type is owned by `dst` then the destination receives the
4374233014bSAlex Crichton         // representation directly rather than a handle to the representation.
4384233014bSAlex Crichton         //
4394233014bSAlex Crichton         // This can perhaps become a different libcall in the future to avoid
4404233014bSAlex Crichton         // this check at runtime since we know at compile time whether the
4414233014bSAlex Crichton         // destination type owns the resource, but that's left as a future
4424233014bSAlex Crichton         // refactoring if truly necessary.
4434233014bSAlex Crichton         if dst_owns_resource {
4444233014bSAlex Crichton             return Ok(rep);
4454233014bSAlex Crichton         }
4464233014bSAlex Crichton         tables.resource_lower_borrow(TypedResource::Component { ty: dst, rep })
4474233014bSAlex Crichton     }
4484233014bSAlex Crichton 
lookup_vmdef(&self, store: &mut StoreOpaque, def: &CoreDef) -> vm::Export449078bc37bSAlex Crichton     pub(crate) fn lookup_vmdef(&self, store: &mut StoreOpaque, def: &CoreDef) -> vm::Export {
450078bc37bSAlex Crichton         lookup_vmdef(store, self.id.instance(), def)
451078bc37bSAlex Crichton     }
452ec9b62abSAlex Crichton 
options<'a>( &self, store: &'a StoreOpaque, options: OptionsIndex, ) -> &'a CanonicalOptions453ec9b62abSAlex Crichton     pub(crate) fn options<'a>(
454ec9b62abSAlex Crichton         &self,
455ec9b62abSAlex Crichton         store: &'a StoreOpaque,
456ec9b62abSAlex Crichton         options: OptionsIndex,
457ec9b62abSAlex Crichton     ) -> &'a CanonicalOptions {
458ec9b62abSAlex Crichton         &self.id.get(store).component().env_component().options[options]
459ec9b62abSAlex Crichton     }
460ec9b62abSAlex Crichton 
options_memory_raw( &self, store: &StoreOpaque, options: OptionsIndex, ) -> Option<NonNull<vm::VMMemoryDefinition>>461ec9b62abSAlex Crichton     fn options_memory_raw(
462ec9b62abSAlex Crichton         &self,
463ec9b62abSAlex Crichton         store: &StoreOpaque,
464ec9b62abSAlex Crichton         options: OptionsIndex,
465ec9b62abSAlex Crichton     ) -> Option<NonNull<vm::VMMemoryDefinition>> {
466ec9b62abSAlex Crichton         let instance = self.id.get(store);
467ec9b62abSAlex Crichton         let options = &instance.component().env_component().options[options];
468ec9b62abSAlex Crichton         let memory = match options.data_model {
469ec9b62abSAlex Crichton             CanonicalOptionsDataModel::Gc { .. } => return None,
470ec9b62abSAlex Crichton             CanonicalOptionsDataModel::LinearMemory(o) => match o.memory {
471ec9b62abSAlex Crichton                 Some(m) => m,
472ec9b62abSAlex Crichton                 None => return None,
473ec9b62abSAlex Crichton             },
474ec9b62abSAlex Crichton         };
475ec9b62abSAlex Crichton 
476ec9b62abSAlex Crichton         Some(instance.runtime_memory(memory))
477ec9b62abSAlex Crichton     }
478ec9b62abSAlex Crichton 
options_memory<'a>( &self, store: &'a StoreOpaque, options: OptionsIndex, ) -> &'a [u8]479ec9b62abSAlex Crichton     pub(crate) fn options_memory<'a>(
480ec9b62abSAlex Crichton         &self,
481ec9b62abSAlex Crichton         store: &'a StoreOpaque,
482ec9b62abSAlex Crichton         options: OptionsIndex,
483ec9b62abSAlex Crichton     ) -> &'a [u8] {
484ec9b62abSAlex Crichton         let memory = match self.options_memory_raw(store, options) {
485ec9b62abSAlex Crichton             Some(m) => m,
486ec9b62abSAlex Crichton             None => return &[],
487ec9b62abSAlex Crichton         };
488ec9b62abSAlex Crichton         // SAFETY: we're borrowing the entire `StoreOpaque` which owns the
489ec9b62abSAlex Crichton         // memory allocation to return the result of memory. That means that the
490ec9b62abSAlex Crichton         // lifetime connection here should be safe and the actual ptr/length are
491ec9b62abSAlex Crichton         // trusted parts of the runtime here.
492ec9b62abSAlex Crichton         unsafe {
493ec9b62abSAlex Crichton             let memory = memory.as_ref();
494ec9b62abSAlex Crichton             core::slice::from_raw_parts(memory.base.as_ptr(), memory.current_length())
495ec9b62abSAlex Crichton         }
496ec9b62abSAlex Crichton     }
497ec9b62abSAlex Crichton 
options_memory_mut<'a>( &self, store: &'a mut StoreOpaque, options: OptionsIndex, ) -> &'a mut [u8]498ec9b62abSAlex Crichton     pub(crate) fn options_memory_mut<'a>(
499ec9b62abSAlex Crichton         &self,
500ec9b62abSAlex Crichton         store: &'a mut StoreOpaque,
501ec9b62abSAlex Crichton         options: OptionsIndex,
502ec9b62abSAlex Crichton     ) -> &'a mut [u8] {
503ec9b62abSAlex Crichton         let memory = match self.options_memory_raw(store, options) {
504ec9b62abSAlex Crichton             Some(m) => m,
505ec9b62abSAlex Crichton             None => return &mut [],
506ec9b62abSAlex Crichton         };
507ec9b62abSAlex Crichton         // SAFETY: See `options_memory` comment above, and note that this is
508ec9b62abSAlex Crichton         // taking `&mut StoreOpaque` to thread the lifetime through instead.
509ec9b62abSAlex Crichton         unsafe {
510ec9b62abSAlex Crichton             let memory = memory.as_ref();
511ec9b62abSAlex Crichton             core::slice::from_raw_parts_mut(memory.base.as_ptr(), memory.current_length())
512ec9b62abSAlex Crichton         }
513ec9b62abSAlex Crichton     }
514ec9b62abSAlex Crichton 
515ec9b62abSAlex Crichton     /// Helper function to simultaneously get a borrow to this instance's
516ec9b62abSAlex Crichton     /// component as well as the store that this component is contained within.
517ec9b62abSAlex Crichton     ///
518ec9b62abSAlex Crichton     /// Note that this function signature is not possible with safe Rust, so
519ec9b62abSAlex Crichton     /// this is using `unsafe` internally.
component_and_store_mut<'a, S>( &self, store: &'a mut S, ) -> (&'a Component, &'a mut S) where S: AsStoreOpaque,520ec9b62abSAlex Crichton     pub(crate) fn component_and_store_mut<'a, S>(
521ec9b62abSAlex Crichton         &self,
522ec9b62abSAlex Crichton         store: &'a mut S,
523ec9b62abSAlex Crichton     ) -> (&'a Component, &'a mut S)
524ec9b62abSAlex Crichton     where
525ec9b62abSAlex Crichton         S: AsStoreOpaque,
526ec9b62abSAlex Crichton     {
527ec9b62abSAlex Crichton         let store_opaque = store.as_store_opaque();
528ec9b62abSAlex Crichton         let instance = self.id.get_mut(store_opaque);
529ec9b62abSAlex Crichton         let component = instance.component();
530ec9b62abSAlex Crichton 
531ec9b62abSAlex Crichton         // SAFETY: the goal of this function is to derive a pointer from
532ec9b62abSAlex Crichton         // `&mut S`, here `&Component`, and then return both so they can both be
533ec9b62abSAlex Crichton         // used at the same time. In general this is not safe operation since
534ec9b62abSAlex Crichton         // the original mutable pointer could be mutated or overwritten which
535ec9b62abSAlex Crichton         // would invalidate the derived pointer.
536ec9b62abSAlex Crichton         //
537ec9b62abSAlex Crichton         // In this case though we have a few guarantees which should make this
538ec9b62abSAlex Crichton         // safe:
539ec9b62abSAlex Crichton         //
540ec9b62abSAlex Crichton         // * Embedders never have the ability to overwrite a `StoreOpaque`. For
541ec9b62abSAlex Crichton         //   example the closest thing of `StoreContextMut` wraps up the
542ec9b62abSAlex Crichton         //   reference internally so it's inaccessible to the outside world.
543ec9b62abSAlex Crichton         //   This means that while mutations can still happen it's not possible
544ec9b62abSAlex Crichton         //   to overwrite a `StoreOpaque` directly.
545ec9b62abSAlex Crichton         //
546ec9b62abSAlex Crichton         // * Components are referred to by `vm::ComponentInstance` which holds a
547ec9b62abSAlex Crichton         //   strong reference. All `ComponentInstance` structures are allocated
548ec9b62abSAlex Crichton         //   within the store and unconditionally live as long as the entire
549ec9b62abSAlex Crichton         //   store itself. This means that there's no worry of the rooting
550ec9b62abSAlex Crichton         //   container going away or otherwise getting deallocated.
551ec9b62abSAlex Crichton         //
552ec9b62abSAlex Crichton         // * The `ComponentInstance` container has an invariant that after
553ec9b62abSAlex Crichton         //   creation the component used to create it cannot be changed. This is
554ec9b62abSAlex Crichton         //   enforced through `Pin<&mut ComponentInstance>` which disallows
555ec9b62abSAlex Crichton         //   mutable access to the `component` field, instead only allowing
556ec9b62abSAlex Crichton         //   read-only access.
557ec9b62abSAlex Crichton         //
558ec9b62abSAlex Crichton         // Putting all of this together it's not possible for a component,
559ec9b62abSAlex Crichton         // within a component instance, within a store, to be deallocated or mutated while
560ec9b62abSAlex Crichton         // a store is in use. Consequently it should be safe to simultaneously
561ec9b62abSAlex Crichton         // have a borrow to both at the same time, even if the store has a
562ec9b62abSAlex Crichton         // mutable borrow itself.
563ec9b62abSAlex Crichton         unsafe {
564ec9b62abSAlex Crichton             let component: *const Component = component;
565ec9b62abSAlex Crichton             (&*component, store)
566ec9b62abSAlex Crichton         }
567ec9b62abSAlex Crichton     }
568078bc37bSAlex Crichton }
569078bc37bSAlex Crichton 
570078bc37bSAlex Crichton /// Translates a `CoreDef`, a definition of a core wasm item, to an
571078bc37bSAlex Crichton /// [`Export`] which is the runtime core wasm definition.
lookup_vmdef( store: &mut StoreOpaque, id: ComponentInstanceId, def: &CoreDef, ) -> vm::Export572078bc37bSAlex Crichton pub(crate) fn lookup_vmdef(
573078bc37bSAlex Crichton     store: &mut StoreOpaque,
574078bc37bSAlex Crichton     id: ComponentInstanceId,
575078bc37bSAlex Crichton     def: &CoreDef,
576078bc37bSAlex Crichton ) -> vm::Export {
577078bc37bSAlex Crichton     match def {
578078bc37bSAlex Crichton         CoreDef::Export(e) => lookup_vmexport(store, id, e),
5792b832281SAlex Crichton         CoreDef::Trampoline(idx) => {
5802b832281SAlex Crichton             let funcref = store
581078bc37bSAlex Crichton                 .store_data_mut()
582078bc37bSAlex Crichton                 .component_instance_mut(id)
5832b832281SAlex Crichton                 .trampoline_func_ref(*idx);
5842b832281SAlex Crichton             // SAFETY: the `funcref` is owned by `store` and is valid within
5852b832281SAlex Crichton             // that store, so it's safe to create a `Func`.
5862b832281SAlex Crichton             vm::Export::Function(unsafe { crate::Func::from_vm_func_ref(store.id(), funcref) })
5872b832281SAlex Crichton         }
588078bc37bSAlex Crichton         CoreDef::InstanceFlags(idx) => {
5892b832281SAlex Crichton             let id = StoreComponentInstanceId::new(store.id(), id);
5902b832281SAlex Crichton             vm::Export::Global(crate::Global::from_component_flags(id, *idx))
591078bc37bSAlex Crichton         }
592ad56ff98SNick Fitzgerald         CoreDef::UnsafeIntrinsic(intrinsic) => {
593ad56ff98SNick Fitzgerald             let funcref = store
594ad56ff98SNick Fitzgerald                 .store_data_mut()
595ad56ff98SNick Fitzgerald                 .component_instance_mut(id)
596ad56ff98SNick Fitzgerald                 .unsafe_intrinsic_func_ref(*intrinsic);
597ad56ff98SNick Fitzgerald             // SAFETY: as above, the `funcref` is owned by `store` and is valid
598ad56ff98SNick Fitzgerald             // within that store, so it's safe to create a `Func`.
599ad56ff98SNick Fitzgerald             vm::Export::Function(unsafe { crate::Func::from_vm_func_ref(store.id(), funcref) })
600ad56ff98SNick Fitzgerald         }
601fae9e6afSJoel Dice         CoreDef::TaskMayBlock => vm::Export::Global(crate::Global::from_task_may_block(
602fae9e6afSJoel Dice             StoreComponentInstanceId::new(store.id(), id),
603fae9e6afSJoel Dice         )),
604078bc37bSAlex Crichton     }
605078bc37bSAlex Crichton }
606078bc37bSAlex Crichton 
607078bc37bSAlex Crichton /// Translates a `CoreExport<T>`, an export of some core instance within
608078bc37bSAlex Crichton /// this component, to the actual runtime definition of that item.
lookup_vmexport<T>( store: &mut StoreOpaque, id: ComponentInstanceId, item: &CoreExport<T>, ) -> vm::Export where T: Copy + Into<EntityIndex>,609078bc37bSAlex Crichton pub(crate) fn lookup_vmexport<T>(
610078bc37bSAlex Crichton     store: &mut StoreOpaque,
611078bc37bSAlex Crichton     id: ComponentInstanceId,
612078bc37bSAlex Crichton     item: &CoreExport<T>,
613078bc37bSAlex Crichton ) -> vm::Export
614078bc37bSAlex Crichton where
615078bc37bSAlex Crichton     T: Copy + Into<EntityIndex>,
616078bc37bSAlex Crichton {
6172b832281SAlex Crichton     let store_id = store.id();
618078bc37bSAlex Crichton     let id = store
619078bc37bSAlex Crichton         .store_data_mut()
620078bc37bSAlex Crichton         .component_instance_mut(id)
621078bc37bSAlex Crichton         .instance(item.instance);
62299ecf728SChris Fallin     let (instance, registry) = store.instance_and_module_registry_mut(id);
623078bc37bSAlex Crichton     let idx = match &item.item {
624078bc37bSAlex Crichton         ExportItem::Index(idx) => (*idx).into(),
625078bc37bSAlex Crichton 
626078bc37bSAlex Crichton         // FIXME: ideally at runtime we don't actually do any name lookups
627078bc37bSAlex Crichton         // here. This will only happen when the host supplies an imported
628078bc37bSAlex Crichton         // module so while the structure can't be known at compile time we
629078bc37bSAlex Crichton         // do know at `InstancePre` time, for example, what all the host
630078bc37bSAlex Crichton         // imports are. In theory we should be able to, as part of
631078bc37bSAlex Crichton         // `InstancePre` construction, perform all name=>index mappings
632078bc37bSAlex Crichton         // during that phase so the actual instantiation of an `InstancePre`
633078bc37bSAlex Crichton         // skips all string lookups. This should probably only be
634078bc37bSAlex Crichton         // investigated if this becomes a performance issue though.
6351f16b28fSNick Fitzgerald         ExportItem::Name(name) => {
6361f16b28fSNick Fitzgerald             let module = instance.env_module();
6371f16b28fSNick Fitzgerald             let name = module.strings.get_atom(name).unwrap();
6381f16b28fSNick Fitzgerald             module.exports[&name]
6391f16b28fSNick Fitzgerald         }
640078bc37bSAlex Crichton     };
6412b832281SAlex Crichton     // SAFETY: the `store_id` owns this instance and all exports contained
6422b832281SAlex Crichton     // within.
64399ecf728SChris Fallin     unsafe { instance.get_export_by_index_mut(registry, store_id, idx) }
6444233014bSAlex Crichton }
6454233014bSAlex Crichton 
6463171ef6dSAlex Crichton /// Trait used to lookup the export of a component instance.
6473171ef6dSAlex Crichton ///
6483171ef6dSAlex Crichton /// This trait is used as an implementation detail of [`Instance::get_func`]
6493171ef6dSAlex Crichton /// and related `get_*` methods. Notable implementors of this trait are:
6503171ef6dSAlex Crichton ///
6513171ef6dSAlex Crichton /// * `str`
6523171ef6dSAlex Crichton /// * `String`
6533171ef6dSAlex Crichton /// * [`ComponentExportIndex`]
6543171ef6dSAlex Crichton ///
6553171ef6dSAlex Crichton /// Note that this is intended to be a `wasmtime`-sealed trait so it shouldn't
6563171ef6dSAlex Crichton /// need to be implemented externally.
6573171ef6dSAlex Crichton pub trait InstanceExportLookup {
6583171ef6dSAlex Crichton     #[doc(hidden)]
lookup(&self, component: &Component) -> Option<ExportIndex>6593171ef6dSAlex Crichton     fn lookup(&self, component: &Component) -> Option<ExportIndex>;
6603171ef6dSAlex Crichton }
6613171ef6dSAlex Crichton 
6623171ef6dSAlex Crichton impl<T> InstanceExportLookup for &T
6633171ef6dSAlex Crichton where
6643171ef6dSAlex Crichton     T: InstanceExportLookup + ?Sized,
6653171ef6dSAlex Crichton {
lookup(&self, component: &Component) -> Option<ExportIndex>6663171ef6dSAlex Crichton     fn lookup(&self, component: &Component) -> Option<ExportIndex> {
6673171ef6dSAlex Crichton         T::lookup(self, component)
6683171ef6dSAlex Crichton     }
6693171ef6dSAlex Crichton }
6703171ef6dSAlex Crichton 
6713171ef6dSAlex Crichton impl InstanceExportLookup for str {
lookup(&self, component: &Component) -> Option<ExportIndex>6723171ef6dSAlex Crichton     fn lookup(&self, component: &Component) -> Option<ExportIndex> {
6739bdb731aSAlex Crichton         component
6749bdb731aSAlex Crichton             .env_component()
6759bdb731aSAlex Crichton             .exports
6769bdb731aSAlex Crichton             .get(self, &NameMapNoIntern)
6779bdb731aSAlex Crichton             .copied()
6783171ef6dSAlex Crichton     }
6793171ef6dSAlex Crichton }
6803171ef6dSAlex Crichton 
6813171ef6dSAlex Crichton impl InstanceExportLookup for String {
lookup(&self, component: &Component) -> Option<ExportIndex>6823171ef6dSAlex Crichton     fn lookup(&self, component: &Component) -> Option<ExportIndex> {
6833171ef6dSAlex Crichton         str::lookup(self, component)
684d4242001SAdam Bratschi-Kaye     }
685d4242001SAdam Bratschi-Kaye }
686d4242001SAdam Bratschi-Kaye 
687d4242001SAdam Bratschi-Kaye struct Instantiator<'a> {
688d4242001SAdam Bratschi-Kaye     component: &'a Component,
68947e90882SAlex Crichton     id: ComponentInstanceId,
690d4242001SAdam Bratschi-Kaye     core_imports: OwnedImports,
691d4242001SAdam Bratschi-Kaye     imports: &'a PrimaryMap<RuntimeImportIndex, RuntimeImport>,
692d4242001SAdam Bratschi-Kaye }
693d4242001SAdam Bratschi-Kaye 
694d4242001SAdam Bratschi-Kaye pub(crate) enum RuntimeImport {
695d4242001SAdam Bratschi-Kaye     Func(Arc<HostFunc>),
696d4242001SAdam Bratschi-Kaye     Module(Module),
697d4242001SAdam Bratschi-Kaye     Resource {
698d4242001SAdam Bratschi-Kaye         ty: ResourceType,
699d4242001SAdam Bratschi-Kaye 
700d4242001SAdam Bratschi-Kaye         // A strong reference to the host function that represents the
701d4242001SAdam Bratschi-Kaye         // destructor for this resource. At this time all resources here are
702d4242001SAdam Bratschi-Kaye         // host-defined resources. Note that this is itself never read because
703d4242001SAdam Bratschi-Kaye         // the funcref below points to it.
704d4242001SAdam Bratschi-Kaye         //
705d4242001SAdam Bratschi-Kaye         // Also note that the `Arc` here is used to support the same host
706d4242001SAdam Bratschi-Kaye         // function being used across multiple instances simultaneously. Or
707d4242001SAdam Bratschi-Kaye         // otherwise this makes `InstancePre::instantiate` possible to create
708d4242001SAdam Bratschi-Kaye         // separate instances all sharing the same host function.
709cc8d04f4SAlex Crichton         dtor: Arc<crate::func::HostFunc>,
710d4242001SAdam Bratschi-Kaye 
711d4242001SAdam Bratschi-Kaye         // A raw function which is filled out (including `wasm_call`) which
712d4242001SAdam Bratschi-Kaye         // points to the internals of the `_dtor` field. This is read and
713d4242001SAdam Bratschi-Kaye         // possibly executed by wasm.
714d4242001SAdam Bratschi-Kaye         dtor_funcref: VMFuncRef,
715d4242001SAdam Bratschi-Kaye     },
716d4242001SAdam Bratschi-Kaye }
717d4242001SAdam Bratschi-Kaye 
718d4242001SAdam Bratschi-Kaye pub type ImportedResources = PrimaryMap<ResourceIndex, ResourceType>;
719d4242001SAdam Bratschi-Kaye 
720d4242001SAdam Bratschi-Kaye impl<'a> Instantiator<'a> {
new( component: &'a Component, store: &mut StoreOpaque, imports: &'a Arc<PrimaryMap<RuntimeImportIndex, RuntimeImport>>, ) -> Result<Instantiator<'a>>721d4242001SAdam Bratschi-Kaye     fn new(
722d4242001SAdam Bratschi-Kaye         component: &'a Component,
723d4242001SAdam Bratschi-Kaye         store: &mut StoreOpaque,
724d4242001SAdam Bratschi-Kaye         imports: &'a Arc<PrimaryMap<RuntimeImportIndex, RuntimeImport>>,
72599ecf728SChris Fallin     ) -> Result<Instantiator<'a>> {
726d4242001SAdam Bratschi-Kaye         let env_component = component.env_component();
727b90b8965SChris Fallin         let (modules, engine, breakpoints) = store.modules_and_engine_and_breakpoints_mut();
728b90b8965SChris Fallin         modules.register_component(component, engine, breakpoints)?;
729d4242001SAdam Bratschi-Kaye         let imported_resources: ImportedResources =
730d4242001SAdam Bratschi-Kaye             PrimaryMap::with_capacity(env_component.imported_resources.len());
73147e90882SAlex Crichton 
7327e28c254SAlex Crichton         let instance = ComponentInstance::new(
73300eb216aSAlex Crichton             store.store_data().components.next_component_instance_id(),
7348fb9d189SAlex Crichton             component,
735d4242001SAdam Bratschi-Kaye             Arc::new(imported_resources),
7368fb9d189SAlex Crichton             imports,
737d4242001SAdam Bratschi-Kaye             store.traitobj(),
738a465eabfSNick Fitzgerald         )?;
73947e90882SAlex Crichton         let id = store.store_data_mut().push_component_instance(instance);
74047e90882SAlex Crichton 
74199ecf728SChris Fallin         Ok(Instantiator {
74247e90882SAlex Crichton             component,
74347e90882SAlex Crichton             imports,
74447e90882SAlex Crichton             core_imports: OwnedImports::empty(),
74547e90882SAlex Crichton             id,
74699ecf728SChris Fallin         })
747d4242001SAdam Bratschi-Kaye     }
748d4242001SAdam Bratschi-Kaye 
run<T>( &mut self, store: &mut StoreContextMut<'_, T>, asyncness: Asyncness, ) -> Result<()>749cc8d04f4SAlex Crichton     async fn run<T>(
750cc8d04f4SAlex Crichton         &mut self,
751cc8d04f4SAlex Crichton         store: &mut StoreContextMut<'_, T>,
752cc8d04f4SAlex Crichton         asyncness: Asyncness,
753cc8d04f4SAlex Crichton     ) -> Result<()> {
754d4242001SAdam Bratschi-Kaye         let env_component = self.component.env_component();
755d4242001SAdam Bratschi-Kaye 
756d4242001SAdam Bratschi-Kaye         // Before all initializers are processed configure all destructors for
757d4242001SAdam Bratschi-Kaye         // host-defined resources. No initializer will correspond to these and
758d4242001SAdam Bratschi-Kaye         // it's required to happen before they're needed, so execute this first.
759d4242001SAdam Bratschi-Kaye         for (idx, import) in env_component.imported_resources.iter() {
760d4242001SAdam Bratschi-Kaye             let (ty, func_ref) = match &self.imports[*import] {
761d4242001SAdam Bratschi-Kaye                 RuntimeImport::Resource {
762d4242001SAdam Bratschi-Kaye                     ty, dtor_funcref, ..
763d4242001SAdam Bratschi-Kaye                 } => (*ty, NonNull::from(dtor_funcref)),
764d4242001SAdam Bratschi-Kaye                 _ => unreachable!(),
765d4242001SAdam Bratschi-Kaye             };
76647e90882SAlex Crichton             let i = self.instance_resource_types_mut(store.0).push(ty);
767d4242001SAdam Bratschi-Kaye             assert_eq!(i, idx);
76847e90882SAlex Crichton             self.instance_mut(store.0)
76947e90882SAlex Crichton                 .set_resource_destructor(idx, Some(func_ref));
770d4242001SAdam Bratschi-Kaye         }
771d4242001SAdam Bratschi-Kaye 
772d4242001SAdam Bratschi-Kaye         // Next configure all `VMFuncRef`s for trampolines that this component
773d4242001SAdam Bratschi-Kaye         // will require. These functions won't actually get used until their
774d4242001SAdam Bratschi-Kaye         // associated state has been initialized through the global initializers
775d4242001SAdam Bratschi-Kaye         // below, but the funcrefs can all be configured here.
776d4242001SAdam Bratschi-Kaye         for (idx, sig) in env_component.trampolines.iter() {
777d4242001SAdam Bratschi-Kaye             let ptrs = self.component.trampoline_ptrs(idx);
7781c013e30SNick Fitzgerald             let signature = match self.component.signatures().shared_type(*sig) {
7791c013e30SNick Fitzgerald                 Some(s) => s,
7801c013e30SNick Fitzgerald                 None => panic!("found unregistered signature: {sig:?}"),
7811c013e30SNick Fitzgerald             };
7821c013e30SNick Fitzgerald 
78347e90882SAlex Crichton             self.instance_mut(store.0).set_trampoline(
78447e90882SAlex Crichton                 idx,
78547e90882SAlex Crichton                 ptrs.wasm_call,
78647e90882SAlex Crichton                 ptrs.array_call,
78747e90882SAlex Crichton                 signature,
78847e90882SAlex Crichton             );
789d4242001SAdam Bratschi-Kaye         }
790d4242001SAdam Bratschi-Kaye 
791ad56ff98SNick Fitzgerald         // Initialize the unsafe intrinsics used by this component, if any.
792ad56ff98SNick Fitzgerald         for (i, module_ty) in env_component
793ad56ff98SNick Fitzgerald             .unsafe_intrinsics
794ad56ff98SNick Fitzgerald             .iter()
795ad56ff98SNick Fitzgerald             .enumerate()
796ad56ff98SNick Fitzgerald             .filter_map(|(i, ty)| ty.expand().map(|ty| (i, ty)))
797ad56ff98SNick Fitzgerald         {
798ad56ff98SNick Fitzgerald             let i = u32::try_from(i).unwrap();
799ad56ff98SNick Fitzgerald             let intrinsic = UnsafeIntrinsic::from_u32(i);
800ad56ff98SNick Fitzgerald             let ptrs = self.component.unsafe_intrinsic_ptrs(intrinsic).expect(
801ad56ff98SNick Fitzgerald                 "should have intrinsic pointers given that we assigned the intrinsic a type",
802ad56ff98SNick Fitzgerald             );
803ad56ff98SNick Fitzgerald             let shared_ty = self
804ad56ff98SNick Fitzgerald                 .component
805ad56ff98SNick Fitzgerald                 .signatures()
806ad56ff98SNick Fitzgerald                 .shared_type(module_ty)
807ad56ff98SNick Fitzgerald                 .expect("should have a shared type");
808ad56ff98SNick Fitzgerald             self.instance_mut(store.0).set_intrinsic(
809ad56ff98SNick Fitzgerald                 intrinsic,
810ad56ff98SNick Fitzgerald                 ptrs.wasm_call,
811ad56ff98SNick Fitzgerald                 ptrs.array_call,
812ad56ff98SNick Fitzgerald                 shared_ty,
813ad56ff98SNick Fitzgerald             );
814ad56ff98SNick Fitzgerald         }
815ad56ff98SNick Fitzgerald 
816d4242001SAdam Bratschi-Kaye         for initializer in env_component.initializers.iter() {
817d4242001SAdam Bratschi-Kaye             match initializer {
818b271e452SJoel Dice                 GlobalInitializer::InstantiateModule(m, component_instance) => {
819b271e452SJoel Dice                     let instance = self.id;
820d4242001SAdam Bratschi-Kaye                     let module;
821d4242001SAdam Bratschi-Kaye                     let imports = match m {
822d4242001SAdam Bratschi-Kaye                         // Since upvars are statically know we know that the
823d4242001SAdam Bratschi-Kaye                         // `args` list is already in the right order.
824d4242001SAdam Bratschi-Kaye                         InstantiateModule::Static(idx, args) => {
825d4242001SAdam Bratschi-Kaye                             module = self.component.static_module(*idx);
826282a1814SNick Fitzgerald                             self.build_imports(store.0, module, args.iter())?
827d4242001SAdam Bratschi-Kaye                         }
828d4242001SAdam Bratschi-Kaye 
829d4242001SAdam Bratschi-Kaye                         // With imports, unlike upvars, we need to do runtime
830d4242001SAdam Bratschi-Kaye                         // lookups with strings to determine the order of the
831d4242001SAdam Bratschi-Kaye                         // imports since it's whatever the actual module
832d4242001SAdam Bratschi-Kaye                         // requires.
833d4242001SAdam Bratschi-Kaye                         //
834d4242001SAdam Bratschi-Kaye                         // FIXME: see the note in `ExportItem::Name` handling
835d4242001SAdam Bratschi-Kaye                         // above for how we ideally shouldn't do string lookup
836d4242001SAdam Bratschi-Kaye                         // here.
837d4242001SAdam Bratschi-Kaye                         InstantiateModule::Import(idx, args) => {
838d4242001SAdam Bratschi-Kaye                             module = match &self.imports[*idx] {
839d4242001SAdam Bratschi-Kaye                                 RuntimeImport::Module(m) => m,
840d4242001SAdam Bratschi-Kaye                                 _ => unreachable!(),
841d4242001SAdam Bratschi-Kaye                             };
842d4242001SAdam Bratschi-Kaye                             let args = module
843d4242001SAdam Bratschi-Kaye                                 .imports()
844d4242001SAdam Bratschi-Kaye                                 .map(|import| &args[import.module()][import.name()]);
845282a1814SNick Fitzgerald                             self.build_imports(store.0, module, args)?
846d4242001SAdam Bratschi-Kaye                         }
847d4242001SAdam Bratschi-Kaye                     };
848d4242001SAdam Bratschi-Kaye 
8493764e757SAlex Crichton                     let exit = if let Some(component_instance) = *component_instance {
8503764e757SAlex Crichton                         store.0.enter_guest_sync_call(
851b271e452SJoel Dice                             None,
852b271e452SJoel Dice                             false,
853b271e452SJoel Dice                             RuntimeInstance {
854b271e452SJoel Dice                                 instance,
855b271e452SJoel Dice                                 index: component_instance,
856b271e452SJoel Dice                             },
857b271e452SJoel Dice                         )?;
858b271e452SJoel Dice                         true
859b271e452SJoel Dice                     } else {
860b271e452SJoel Dice                         false
861b271e452SJoel Dice                     };
862b271e452SJoel Dice 
863d4242001SAdam Bratschi-Kaye                     // Note that the unsafety here should be ok because the
864d4242001SAdam Bratschi-Kaye                     // validity of the component means that type-checks have
865d4242001SAdam Bratschi-Kaye                     // already been performed. This means that the unsafety due
866d4242001SAdam Bratschi-Kaye                     // to imports having the wrong type should not happen here.
867d4242001SAdam Bratschi-Kaye                     //
868d4242001SAdam Bratschi-Kaye                     // Also note we are calling new_started_impl because we have
869d4242001SAdam Bratschi-Kaye                     // already checked for asyncness and are running on a fiber
870d4242001SAdam Bratschi-Kaye                     // if required.
871d4242001SAdam Bratschi-Kaye 
872d4242001SAdam Bratschi-Kaye                     let i = unsafe {
873cc8d04f4SAlex Crichton                         crate::Instance::new_started(store, module, imports.as_ref(), asyncness)
874cc8d04f4SAlex Crichton                             .await?
875d4242001SAdam Bratschi-Kaye                     };
876b271e452SJoel Dice 
877b271e452SJoel Dice                     if exit {
878da093747SAlex Crichton                         store.0.exit_guest_sync_call()?;
879b271e452SJoel Dice                     }
880b271e452SJoel Dice 
88147e90882SAlex Crichton                     self.instance_mut(store.0).push_instance_id(i.id());
882d4242001SAdam Bratschi-Kaye                 }
883d4242001SAdam Bratschi-Kaye 
884d4242001SAdam Bratschi-Kaye                 GlobalInitializer::LowerImport { import, index } => {
885d4242001SAdam Bratschi-Kaye                     let func = match &self.imports[*import] {
886d4242001SAdam Bratschi-Kaye                         RuntimeImport::Func(func) => func,
887d4242001SAdam Bratschi-Kaye                         _ => unreachable!(),
888d4242001SAdam Bratschi-Kaye                     };
88947e90882SAlex Crichton                     self.instance_mut(store.0)
89047e90882SAlex Crichton                         .set_lowering(*index, func.lowering());
891d4242001SAdam Bratschi-Kaye                 }
892d4242001SAdam Bratschi-Kaye 
893d8360be4SAndrew Brown                 GlobalInitializer::ExtractTable(table) => self.extract_table(store.0, table),
894d8360be4SAndrew Brown 
895d4242001SAdam Bratschi-Kaye                 GlobalInitializer::ExtractMemory(mem) => self.extract_memory(store.0, mem),
896d4242001SAdam Bratschi-Kaye 
897d4242001SAdam Bratschi-Kaye                 GlobalInitializer::ExtractRealloc(realloc) => {
898d4242001SAdam Bratschi-Kaye                     self.extract_realloc(store.0, realloc)
899d4242001SAdam Bratschi-Kaye                 }
900d4242001SAdam Bratschi-Kaye 
901442003adSJoel Dice                 GlobalInitializer::ExtractCallback(callback) => {
9023ba13d1bSJoel Dice                     self.extract_callback(store.0, callback)
903442003adSJoel Dice                 }
904442003adSJoel Dice 
905d4242001SAdam Bratschi-Kaye                 GlobalInitializer::ExtractPostReturn(post_return) => {
906d4242001SAdam Bratschi-Kaye                     self.extract_post_return(store.0, post_return)
907d4242001SAdam Bratschi-Kaye                 }
908d4242001SAdam Bratschi-Kaye 
909d4242001SAdam Bratschi-Kaye                 GlobalInitializer::Resource(r) => self.resource(store.0, r),
910d4242001SAdam Bratschi-Kaye             }
911d4242001SAdam Bratschi-Kaye         }
912d4242001SAdam Bratschi-Kaye         Ok(())
913d4242001SAdam Bratschi-Kaye     }
914d4242001SAdam Bratschi-Kaye 
resource(&mut self, store: &mut StoreOpaque, resource: &Resource)91547e90882SAlex Crichton     fn resource(&mut self, store: &mut StoreOpaque, resource: &Resource) {
916d4242001SAdam Bratschi-Kaye         let dtor = resource
917d4242001SAdam Bratschi-Kaye             .dtor
918d4242001SAdam Bratschi-Kaye             .as_ref()
919078bc37bSAlex Crichton             .map(|dtor| lookup_vmdef(store, self.id, dtor));
920d4242001SAdam Bratschi-Kaye         let dtor = dtor.map(|export| match export {
9212b832281SAlex Crichton             crate::runtime::vm::Export::Function(f) => f.vm_func_ref(store),
922d4242001SAdam Bratschi-Kaye             _ => unreachable!(),
923d4242001SAdam Bratschi-Kaye         });
924d4242001SAdam Bratschi-Kaye         let index = self
925d4242001SAdam Bratschi-Kaye             .component
926d4242001SAdam Bratschi-Kaye             .env_component()
927d4242001SAdam Bratschi-Kaye             .resource_index(resource.index);
928078bc37bSAlex Crichton         let instance = self.instance(store);
92947e90882SAlex Crichton         let ty = ResourceType::guest(store.id(), instance, resource.index);
93047e90882SAlex Crichton         self.instance_mut(store)
93147e90882SAlex Crichton             .set_resource_destructor(index, dtor);
93247e90882SAlex Crichton         let i = self.instance_resource_types_mut(store).push(ty);
933d4242001SAdam Bratschi-Kaye         debug_assert_eq!(i, index);
934d4242001SAdam Bratschi-Kaye     }
935d4242001SAdam Bratschi-Kaye 
extract_memory(&mut self, store: &mut StoreOpaque, memory: &ExtractMemory)93647e90882SAlex Crichton     fn extract_memory(&mut self, store: &mut StoreOpaque, memory: &ExtractMemory) {
9371fcd0933SAlex Crichton         let import = match lookup_vmexport(store, self.id, &memory.export) {
9381fcd0933SAlex Crichton             crate::runtime::vm::Export::Memory(memory) => memory.vmimport(store),
9391fcd0933SAlex Crichton             crate::runtime::vm::Export::SharedMemory(_, import) => import,
940d4242001SAdam Bratschi-Kaye             _ => unreachable!(),
941d4242001SAdam Bratschi-Kaye         };
94247e90882SAlex Crichton         self.instance_mut(store)
9432b832281SAlex Crichton             .set_runtime_memory(memory.index, import.from.as_non_null());
944d4242001SAdam Bratschi-Kaye     }
945d4242001SAdam Bratschi-Kaye 
extract_realloc(&mut self, store: &mut StoreOpaque, realloc: &ExtractRealloc)94647e90882SAlex Crichton     fn extract_realloc(&mut self, store: &mut StoreOpaque, realloc: &ExtractRealloc) {
947078bc37bSAlex Crichton         let func_ref = match lookup_vmdef(store, self.id, &realloc.def) {
9482b832281SAlex Crichton             crate::runtime::vm::Export::Function(f) => f.vm_func_ref(store),
949d4242001SAdam Bratschi-Kaye             _ => unreachable!(),
950d4242001SAdam Bratschi-Kaye         };
95147e90882SAlex Crichton         self.instance_mut(store)
95247e90882SAlex Crichton             .set_runtime_realloc(realloc.index, func_ref);
953d4242001SAdam Bratschi-Kaye     }
954d4242001SAdam Bratschi-Kaye 
extract_callback(&mut self, store: &mut StoreOpaque, callback: &ExtractCallback)95547e90882SAlex Crichton     fn extract_callback(&mut self, store: &mut StoreOpaque, callback: &ExtractCallback) {
956078bc37bSAlex Crichton         let func_ref = match lookup_vmdef(store, self.id, &callback.def) {
9572b832281SAlex Crichton             crate::runtime::vm::Export::Function(f) => f.vm_func_ref(store),
9583ba13d1bSJoel Dice             _ => unreachable!(),
9593ba13d1bSJoel Dice         };
96047e90882SAlex Crichton         self.instance_mut(store)
96147e90882SAlex Crichton             .set_runtime_callback(callback.index, func_ref);
9623ba13d1bSJoel Dice     }
9633ba13d1bSJoel Dice 
extract_post_return(&mut self, store: &mut StoreOpaque, post_return: &ExtractPostReturn)96447e90882SAlex Crichton     fn extract_post_return(&mut self, store: &mut StoreOpaque, post_return: &ExtractPostReturn) {
965078bc37bSAlex Crichton         let func_ref = match lookup_vmdef(store, self.id, &post_return.def) {
9662b832281SAlex Crichton             crate::runtime::vm::Export::Function(f) => f.vm_func_ref(store),
967d4242001SAdam Bratschi-Kaye             _ => unreachable!(),
968d4242001SAdam Bratschi-Kaye         };
96947e90882SAlex Crichton         self.instance_mut(store)
970d4242001SAdam Bratschi-Kaye             .set_runtime_post_return(post_return.index, func_ref);
971d4242001SAdam Bratschi-Kaye     }
972d4242001SAdam Bratschi-Kaye 
extract_table(&mut self, store: &mut StoreOpaque, table: &ExtractTable)97347e90882SAlex Crichton     fn extract_table(&mut self, store: &mut StoreOpaque, table: &ExtractTable) {
974078bc37bSAlex Crichton         let export = match lookup_vmexport(store, self.id, &table.export) {
975d8360be4SAndrew Brown             crate::runtime::vm::Export::Table(t) => t,
976d8360be4SAndrew Brown             _ => unreachable!(),
977d8360be4SAndrew Brown         };
9782b832281SAlex Crichton         let import = export.vmimport(store);
9792b832281SAlex Crichton         self.instance_mut(store)
9802b832281SAlex Crichton             .set_runtime_table(table.index, import);
981d8360be4SAndrew Brown     }
982d8360be4SAndrew Brown 
build_imports<'b>( &mut self, store: &mut StoreOpaque, module: &Module, args: impl Iterator<Item = &'b CoreDef>, ) -> Result<&OwnedImports, OutOfMemory>983d4242001SAdam Bratschi-Kaye     fn build_imports<'b>(
984d4242001SAdam Bratschi-Kaye         &mut self,
985078bc37bSAlex Crichton         store: &mut StoreOpaque,
986d4242001SAdam Bratschi-Kaye         module: &Module,
987d4242001SAdam Bratschi-Kaye         args: impl Iterator<Item = &'b CoreDef>,
988282a1814SNick Fitzgerald     ) -> Result<&OwnedImports, OutOfMemory> {
989d4242001SAdam Bratschi-Kaye         self.core_imports.clear();
990282a1814SNick Fitzgerald         self.core_imports.reserve(module)?;
991d4242001SAdam Bratschi-Kaye         let mut imports = module.compiled_module().module().imports();
992d4242001SAdam Bratschi-Kaye 
993d4242001SAdam Bratschi-Kaye         for arg in args {
994d4242001SAdam Bratschi-Kaye             // The general idea of Wasmtime is that at runtime type-checks for
995d4242001SAdam Bratschi-Kaye             // core wasm instantiations internally within a component are
996d4242001SAdam Bratschi-Kaye             // unnecessary and superfluous. Naturally though mistakes may be
997d4242001SAdam Bratschi-Kaye             // made, so double-check this property of wasmtime in debug mode.
998d4242001SAdam Bratschi-Kaye 
999d4242001SAdam Bratschi-Kaye             if cfg!(debug_assertions) {
10001c013e30SNick Fitzgerald                 let (imp_module, imp_name, expected) = imports.next().unwrap();
10011c013e30SNick Fitzgerald                 self.assert_type_matches(store, module, arg, imp_module, imp_name, expected);
1002d4242001SAdam Bratschi-Kaye             }
1003d4242001SAdam Bratschi-Kaye 
1004d4242001SAdam Bratschi-Kaye             // The unsafety here should be ok since the `export` is loaded
1005d4242001SAdam Bratschi-Kaye             // directly from an instance which should only give us valid export
1006d4242001SAdam Bratschi-Kaye             // items.
1007078bc37bSAlex Crichton             let export = lookup_vmdef(store, self.id, arg);
1008282a1814SNick Fitzgerald             self.core_imports.push_export(store, &export)?;
1009d4242001SAdam Bratschi-Kaye         }
1010d4242001SAdam Bratschi-Kaye         debug_assert!(imports.next().is_none());
1011d4242001SAdam Bratschi-Kaye 
1012282a1814SNick Fitzgerald         Ok(&self.core_imports)
1013d4242001SAdam Bratschi-Kaye     }
1014d4242001SAdam Bratschi-Kaye 
assert_type_matches( &self, store: &mut StoreOpaque, module: &Module, arg: &CoreDef, imp_module: &str, imp_name: &str, expected: EntityType, )1015d4242001SAdam Bratschi-Kaye     fn assert_type_matches(
1016d4242001SAdam Bratschi-Kaye         &self,
1017078bc37bSAlex Crichton         store: &mut StoreOpaque,
1018d4242001SAdam Bratschi-Kaye         module: &Module,
1019d4242001SAdam Bratschi-Kaye         arg: &CoreDef,
10201c013e30SNick Fitzgerald         imp_module: &str,
10211c013e30SNick Fitzgerald         imp_name: &str,
1022d4242001SAdam Bratschi-Kaye         expected: EntityType,
1023d4242001SAdam Bratschi-Kaye     ) {
1024078bc37bSAlex Crichton         let export = lookup_vmdef(store, self.id, arg);
1025d4242001SAdam Bratschi-Kaye 
1026d4242001SAdam Bratschi-Kaye         // If this value is a core wasm function then the type check is inlined
1027d4242001SAdam Bratschi-Kaye         // here. This can otherwise fail `Extern::from_wasmtime_export` because
1028d4242001SAdam Bratschi-Kaye         // there's no guarantee that there exists a trampoline for `f` so this
1029d4242001SAdam Bratschi-Kaye         // can't fall through to the case below
103072004aadSNick Fitzgerald         if let crate::runtime::vm::Export::Function(f) = &export {
10310fa13013SNick Fitzgerald             let expected = match expected.unwrap_func() {
103297631126SNick Fitzgerald                 EngineOrModuleTypeIndex::Engine(e) => Some(e),
10330fa13013SNick Fitzgerald                 EngineOrModuleTypeIndex::Module(m) => module.signatures().shared_type(m),
10341c013e30SNick Fitzgerald                 EngineOrModuleTypeIndex::RecGroup(_) => unreachable!(),
10350fa13013SNick Fitzgerald             };
10362b832281SAlex Crichton             let actual = unsafe { f.vm_func_ref(store).as_ref().type_index };
10371c013e30SNick Fitzgerald             assert_eq!(
10381c013e30SNick Fitzgerald                 expected,
10391c013e30SNick Fitzgerald                 Some(actual),
10401c013e30SNick Fitzgerald                 "type mismatch for import {imp_module:?} {imp_name:?}!!!\n\n\
10411c013e30SNick Fitzgerald                  expected {:#?}\n\n\
10421c013e30SNick Fitzgerald                  found {:#?}",
10431c013e30SNick Fitzgerald                 expected.and_then(|e| store.engine().signatures().borrow(e)),
10441c013e30SNick Fitzgerald                 store.engine().signatures().borrow(actual)
10451c013e30SNick Fitzgerald             );
1046d4242001SAdam Bratschi-Kaye             return;
1047d4242001SAdam Bratschi-Kaye         }
1048d4242001SAdam Bratschi-Kaye 
1049*439de7fbSNick Fitzgerald         let val = crate::Extern::from_wasmtime_export(export, store.engine());
1050d4242001SAdam Bratschi-Kaye         let ty = DefinitionType::from(store, &val);
10510fa13013SNick Fitzgerald         crate::types::matching::MatchCx::new(module.engine())
1052d4242001SAdam Bratschi-Kaye             .definition(&expected, &ty)
1053d4242001SAdam Bratschi-Kaye             .expect("unexpected typecheck failure");
1054d4242001SAdam Bratschi-Kaye     }
10558fb9d189SAlex Crichton 
105647e90882SAlex Crichton     /// Convenience helper to return the `&ComponentInstance` that's being
105747e90882SAlex Crichton     /// instantiated.
instance<'b>(&self, store: &'b StoreOpaque) -> &'b ComponentInstance105847e90882SAlex Crichton     fn instance<'b>(&self, store: &'b StoreOpaque) -> &'b ComponentInstance {
105947e90882SAlex Crichton         store.store_data().component_instance(self.id)
106047e90882SAlex Crichton     }
106147e90882SAlex Crichton 
106247e90882SAlex Crichton     /// Same as [`Self::instance`], but for mutability.
instance_mut<'b>(&self, store: &'b mut StoreOpaque) -> Pin<&'b mut ComponentInstance>10637e28c254SAlex Crichton     fn instance_mut<'b>(&self, store: &'b mut StoreOpaque) -> Pin<&'b mut ComponentInstance> {
106447e90882SAlex Crichton         store.store_data_mut().component_instance_mut(self.id)
106547e90882SAlex Crichton     }
106647e90882SAlex Crichton 
10678fb9d189SAlex Crichton     // NB: This method is only intended to be called during the instantiation
10688fb9d189SAlex Crichton     // process because the `Arc::get_mut` here is fallible and won't generally
10698fb9d189SAlex Crichton     // succeed once the instance has been handed to the embedder. Before that
10708fb9d189SAlex Crichton     // though it should be guaranteed that the single owning reference currently
10718fb9d189SAlex Crichton     // lives within the `ComponentInstance` that's being built.
instance_resource_types_mut<'b>( &self, store: &'b mut StoreOpaque, ) -> &'b mut ImportedResources107247e90882SAlex Crichton     fn instance_resource_types_mut<'b>(
107347e90882SAlex Crichton         &self,
107447e90882SAlex Crichton         store: &'b mut StoreOpaque,
107547e90882SAlex Crichton     ) -> &'b mut ImportedResources {
107647e90882SAlex Crichton         Arc::get_mut(self.instance_mut(store).resource_types_mut()).unwrap()
10778fb9d189SAlex Crichton     }
1078d4242001SAdam Bratschi-Kaye }
1079d4242001SAdam Bratschi-Kaye 
1080d4242001SAdam Bratschi-Kaye /// A "pre-instantiated" [`Instance`] which has all of its arguments already
1081d4242001SAdam Bratschi-Kaye /// supplied and is ready to instantiate.
1082d4242001SAdam Bratschi-Kaye ///
1083d4242001SAdam Bratschi-Kaye /// This structure represents an efficient form of instantiation where import
1084d4242001SAdam Bratschi-Kaye /// type-checking and import lookup has all been resolved by the time that this
1085d4242001SAdam Bratschi-Kaye /// type is created. This type is primarily created through the
1086d4242001SAdam Bratschi-Kaye /// [`Linker::instantiate_pre`](crate::component::Linker::instantiate_pre)
1087d4242001SAdam Bratschi-Kaye /// method.
1088f81c0dc0SAlex Crichton pub struct InstancePre<T: 'static> {
1089d4242001SAdam Bratschi-Kaye     component: Component,
1090d4242001SAdam Bratschi-Kaye     imports: Arc<PrimaryMap<RuntimeImportIndex, RuntimeImport>>,
10911a9e6235SPat Hickey     resource_types: Arc<PrimaryMap<ResourceIndex, ResourceType>>,
1092cc8d04f4SAlex Crichton     asyncness: Asyncness,
1093d4242001SAdam Bratschi-Kaye     _marker: marker::PhantomData<fn() -> T>,
1094d4242001SAdam Bratschi-Kaye }
1095d4242001SAdam Bratschi-Kaye 
1096d4242001SAdam Bratschi-Kaye // `InstancePre`'s clone does not require `T: Clone`
1097f81c0dc0SAlex Crichton impl<T: 'static> Clone for InstancePre<T> {
clone(&self) -> Self1098d4242001SAdam Bratschi-Kaye     fn clone(&self) -> Self {
1099d4242001SAdam Bratschi-Kaye         Self {
1100d4242001SAdam Bratschi-Kaye             component: self.component.clone(),
1101d4242001SAdam Bratschi-Kaye             imports: self.imports.clone(),
11021a9e6235SPat Hickey             resource_types: self.resource_types.clone(),
1103cc8d04f4SAlex Crichton             asyncness: self.asyncness,
1104d4242001SAdam Bratschi-Kaye             _marker: self._marker,
1105d4242001SAdam Bratschi-Kaye         }
1106d4242001SAdam Bratschi-Kaye     }
1107d4242001SAdam Bratschi-Kaye }
1108d4242001SAdam Bratschi-Kaye 
1109f81c0dc0SAlex Crichton impl<T: 'static> InstancePre<T> {
1110d4242001SAdam Bratschi-Kaye     /// This function is `unsafe` since there's no guarantee that the
1111d4242001SAdam Bratschi-Kaye     /// `RuntimeImport` items provided are guaranteed to work with the `T` of
1112d4242001SAdam Bratschi-Kaye     /// the store.
1113d4242001SAdam Bratschi-Kaye     ///
1114d4242001SAdam Bratschi-Kaye     /// Additionally there is no static guarantee that the `imports` provided
1115d4242001SAdam Bratschi-Kaye     /// satisfy the imports of the `component` provided.
new_unchecked( component: Component, imports: Arc<PrimaryMap<RuntimeImportIndex, RuntimeImport>>, resource_types: Arc<PrimaryMap<ResourceIndex, ResourceType>>, ) -> InstancePre<T>1116d4242001SAdam Bratschi-Kaye     pub(crate) unsafe fn new_unchecked(
1117d4242001SAdam Bratschi-Kaye         component: Component,
11181a9e6235SPat Hickey         imports: Arc<PrimaryMap<RuntimeImportIndex, RuntimeImport>>,
11191a9e6235SPat Hickey         resource_types: Arc<PrimaryMap<ResourceIndex, ResourceType>>,
1120d4242001SAdam Bratschi-Kaye     ) -> InstancePre<T> {
1121cc8d04f4SAlex Crichton         let mut asyncness = Asyncness::No;
1122cc8d04f4SAlex Crichton         for (_, import) in imports.iter() {
1123cc8d04f4SAlex Crichton             asyncness = asyncness
1124cc8d04f4SAlex Crichton                 | match import {
1125cc8d04f4SAlex Crichton                     RuntimeImport::Func(f) => f.asyncness(),
1126cc8d04f4SAlex Crichton                     RuntimeImport::Module(_) => Asyncness::No,
1127cc8d04f4SAlex Crichton                     RuntimeImport::Resource { dtor, .. } => dtor.asyncness(),
1128cc8d04f4SAlex Crichton                 };
1129cc8d04f4SAlex Crichton         }
1130d4242001SAdam Bratschi-Kaye         InstancePre {
1131d4242001SAdam Bratschi-Kaye             component,
11321a9e6235SPat Hickey             imports,
11331a9e6235SPat Hickey             resource_types,
1134cc8d04f4SAlex Crichton             asyncness,
1135d4242001SAdam Bratschi-Kaye             _marker: marker::PhantomData,
1136d4242001SAdam Bratschi-Kaye         }
1137d4242001SAdam Bratschi-Kaye     }
1138d4242001SAdam Bratschi-Kaye 
1139d4242001SAdam Bratschi-Kaye     /// Returns the underlying component that will be instantiated.
component(&self) -> &Component1140d4242001SAdam Bratschi-Kaye     pub fn component(&self) -> &Component {
1141d4242001SAdam Bratschi-Kaye         &self.component
1142d4242001SAdam Bratschi-Kaye     }
1143d4242001SAdam Bratschi-Kaye 
11441a9e6235SPat Hickey     #[doc(hidden)]
11451a9e6235SPat Hickey     /// Returns the type at which the underlying component will be
11461a9e6235SPat Hickey     /// instantiated. This contains the instantiated type information which
11471a9e6235SPat Hickey     /// was determined by the Linker.
instance_type(&self) -> InstanceType<'_>11481a9e6235SPat Hickey     pub fn instance_type(&self) -> InstanceType<'_> {
11491a9e6235SPat Hickey         InstanceType {
11501a9e6235SPat Hickey             types: &self.component.types(),
11511a9e6235SPat Hickey             resources: &self.resource_types,
11521a9e6235SPat Hickey         }
11531a9e6235SPat Hickey     }
11541a9e6235SPat Hickey 
1155f471b4dcSAlex Crichton     /// Returns the underlying engine.
engine(&self) -> &Engine1156f471b4dcSAlex Crichton     pub fn engine(&self) -> &Engine {
1157f471b4dcSAlex Crichton         self.component.engine()
1158f471b4dcSAlex Crichton     }
1159f471b4dcSAlex Crichton 
1160d4242001SAdam Bratschi-Kaye     /// Performs the instantiation process into the store specified.
1161d4242001SAdam Bratschi-Kaye     //
1162d4242001SAdam Bratschi-Kaye     // TODO: needs more docs
instantiate(&self, mut store: impl AsContextMut<Data = T>) -> Result<Instance>1163cc8d04f4SAlex Crichton     pub fn instantiate(&self, mut store: impl AsContextMut<Data = T>) -> Result<Instance> {
1164cc8d04f4SAlex Crichton         let store = store.as_context_mut();
1165cc8d04f4SAlex Crichton 
1166cc8d04f4SAlex Crichton         // If this instance requires an async host, set that flag in the store,
1167cc8d04f4SAlex Crichton         // and then afterwards assert nothing else in the store, nor this
1168cc8d04f4SAlex Crichton         // instance, required async.
1169cc8d04f4SAlex Crichton         store.0.set_async_required(self.asyncness);
1170cc8d04f4SAlex Crichton         store.0.validate_sync_call()?;
1171cc8d04f4SAlex Crichton 
1172cc8d04f4SAlex Crichton         vm::assert_ready(self._instantiate(store, Asyncness::No))
1173d4242001SAdam Bratschi-Kaye     }
1174d4242001SAdam Bratschi-Kaye     /// Performs the instantiation process into the store specified.
1175d4242001SAdam Bratschi-Kaye     ///
1176d4242001SAdam Bratschi-Kaye     /// Exactly like [`Self::instantiate`] except for use on async stores.
1177d4242001SAdam Bratschi-Kaye     //
1178d4242001SAdam Bratschi-Kaye     // TODO: needs more docs
1179d4242001SAdam Bratschi-Kaye     #[cfg(feature = "async")]
instantiate_async(&self, store: impl AsContextMut<Data = T>) -> Result<Instance>1180e1f50aadSAlex Crichton     pub async fn instantiate_async(&self, store: impl AsContextMut<Data = T>) -> Result<Instance> {
1181cc8d04f4SAlex Crichton         self._instantiate(store, Asyncness::Yes).await
1182d4242001SAdam Bratschi-Kaye     }
1183d4242001SAdam Bratschi-Kaye 
_instantiate( &self, mut store: impl AsContextMut<Data = T>, asyncness: Asyncness, ) -> Result<Instance>1184cc8d04f4SAlex Crichton     async fn _instantiate(
1185cc8d04f4SAlex Crichton         &self,
1186cc8d04f4SAlex Crichton         mut store: impl AsContextMut<Data = T>,
1187cc8d04f4SAlex Crichton         asyncness: Asyncness,
1188cc8d04f4SAlex Crichton     ) -> Result<Instance> {
1189d4242001SAdam Bratschi-Kaye         let mut store = store.as_context_mut();
1190cc8d04f4SAlex Crichton         store.0.set_async_required(self.asyncness);
1191d4242001SAdam Bratschi-Kaye         store
1192d4242001SAdam Bratschi-Kaye             .engine()
1193d4242001SAdam Bratschi-Kaye             .allocator()
1194d4242001SAdam Bratschi-Kaye             .increment_component_instance_count()?;
119599ecf728SChris Fallin         let mut instantiator = Instantiator::new(&self.component, store.0, &self.imports)?;
1196cc8d04f4SAlex Crichton         instantiator.run(&mut store, asyncness).await.map_err(|e| {
1197d4242001SAdam Bratschi-Kaye             store
1198d4242001SAdam Bratschi-Kaye                 .engine()
1199d4242001SAdam Bratschi-Kaye                 .allocator()
1200d4242001SAdam Bratschi-Kaye                 .decrement_component_instance_count();
1201d4242001SAdam Bratschi-Kaye             e
1202d4242001SAdam Bratschi-Kaye         })?;
1203b271e452SJoel Dice 
12047aea45abSAlex Crichton         let instance = Instance::from_wasmtime(store.0, instantiator.id);
1205d4242001SAdam Bratschi-Kaye         store.0.push_component_instance(instance);
1206d4242001SAdam Bratschi-Kaye         Ok(instance)
1207d4242001SAdam Bratschi-Kaye     }
1208d4242001SAdam Bratschi-Kaye }
1209