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