190ac295eSAlex Crichton use crate::component::InstanceExportLookup;
245a8da69SAlex Crichton use crate::component::matching::InstanceType;
345a8da69SAlex Crichton use crate::component::types;
481a89169SAlex Crichton use crate::prelude::*;
515b464b6SAdam Bratschi-Kaye #[cfg(feature = "std")]
615b464b6SAdam Bratschi-Kaye use crate::runtime::vm::open_file_for_mmap;
7a252f37eSAlex Crichton use crate::runtime::vm::{CompiledModuleId, VMArrayCallFunction, VMFuncRef, VMWasmCallFunction};
8d4242001SAdam Bratschi-Kaye use crate::{
999ecf728SChris Fallin     Engine, Module, ResourcesRequired, code::EngineCode, code_memory::CodeMemory,
1090ac295eSAlex Crichton     type_registry::TypeCollection,
11d4242001SAdam Bratschi-Kaye };
12d961fc07SNick Fitzgerald use crate::{FuncType, ValType};
1381a89169SAlex Crichton use alloc::sync::Arc;
1481a89169SAlex Crichton use core::ops::Range;
1581a89169SAlex Crichton use core::ptr::NonNull;
1681a89169SAlex Crichton #[cfg(feature = "std")]
17d4242001SAdam Bratschi-Kaye use std::path::Path;
18d4242001SAdam Bratschi-Kaye use wasmtime_environ::component::{
195245e1f8SNick Fitzgerald     CompiledComponentInfo, ComponentArtifacts, ComponentTypes, CoreDef, Export, ExportIndex,
205245e1f8SNick Fitzgerald     GlobalInitializer, InstantiateModule, NameMapNoIntern, OptionsIndex, StaticModuleIndex,
21ad56ff98SNick Fitzgerald     TrampolineIndex, TypeComponentIndex, TypeFuncIndex, UnsafeIntrinsic, VMComponentOffsets,
22d4242001SAdam Bratschi-Kaye };
23b298f375SArjun Ramesh use wasmtime_environ::{Abi, CompiledFunctionsTable, FuncKey, TypeTrace, WasmChecksum};
24d4242001SAdam Bratschi-Kaye use wasmtime_environ::{FunctionLoc, HostPtr, ObjectKind, PrimaryMap};
25d4242001SAdam Bratschi-Kaye 
26d4242001SAdam Bratschi-Kaye /// A compiled WebAssembly Component.
276d105f4dSAlex Crichton ///
286d105f4dSAlex Crichton /// This structure represents a compiled component that is ready to be
296d105f4dSAlex Crichton /// instantiated. This owns a region of virtual memory which contains executable
306d105f4dSAlex Crichton /// code compiled from a WebAssembly binary originally. This is the analog of
316d105f4dSAlex Crichton /// [`Module`](crate::Module) in the component embedding API.
326d105f4dSAlex Crichton ///
336d105f4dSAlex Crichton /// A [`Component`] can be turned into an
346d105f4dSAlex Crichton /// [`Instance`](crate::component::Instance) through a
356d105f4dSAlex Crichton /// [`Linker`](crate::component::Linker). [`Component`]s are safe to share
366d105f4dSAlex Crichton /// across threads. The compilation model of a component is the same as that of
376d105f4dSAlex Crichton /// [a module](crate::Module) which is to say:
386d105f4dSAlex Crichton ///
396d105f4dSAlex Crichton /// * Compilation happens synchronously during [`Component::new`].
406d105f4dSAlex Crichton /// * The result of compilation can be saved into storage with
416d105f4dSAlex Crichton ///   [`Component::serialize`].
426d105f4dSAlex Crichton /// * A previously compiled artifact can be parsed with
436d105f4dSAlex Crichton ///   [`Component::deserialize`].
446d105f4dSAlex Crichton /// * No compilation happens at runtime for a component — everything is done
456d105f4dSAlex Crichton ///   by the time [`Component::new`] returns.
466d105f4dSAlex Crichton ///
476d105f4dSAlex Crichton /// ## Components and `Clone`
486d105f4dSAlex Crichton ///
496d105f4dSAlex Crichton /// Using `clone` on a `Component` is a cheap operation. It will not create an
506d105f4dSAlex Crichton /// entirely new component, but rather just a new reference to the existing
516d105f4dSAlex Crichton /// component. In other words it's a shallow copy, not a deep copy.
526d105f4dSAlex Crichton ///
536d105f4dSAlex Crichton /// ## Examples
546d105f4dSAlex Crichton ///
556d105f4dSAlex Crichton /// For example usage see the documentation of [`Module`](crate::Module) as
566d105f4dSAlex Crichton /// [`Component`] has the same high-level API.
57d4242001SAdam Bratschi-Kaye #[derive(Clone)]
58d4242001SAdam Bratschi-Kaye pub struct Component {
59d4242001SAdam Bratschi-Kaye     inner: Arc<ComponentInner>,
60d4242001SAdam Bratschi-Kaye }
61d4242001SAdam Bratschi-Kaye 
62d4242001SAdam Bratschi-Kaye struct ComponentInner {
633171ef6dSAlex Crichton     /// Unique id for this component within this process.
643171ef6dSAlex Crichton     ///
653171ef6dSAlex Crichton     /// Note that this is repurposing ids for modules intentionally as there
663171ef6dSAlex Crichton     /// shouldn't be an issue overlapping them.
673171ef6dSAlex Crichton     id: CompiledModuleId,
683171ef6dSAlex Crichton 
693171ef6dSAlex Crichton     /// The engine that this component belongs to.
703171ef6dSAlex Crichton     engine: Engine,
713171ef6dSAlex Crichton 
72d4242001SAdam Bratschi-Kaye     /// Component type index
73d4242001SAdam Bratschi-Kaye     ty: TypeComponentIndex,
74d4242001SAdam Bratschi-Kaye 
75d4242001SAdam Bratschi-Kaye     /// Core wasm modules that the component defined internally, indexed by the
76d4242001SAdam Bratschi-Kaye     /// compile-time-assigned `ModuleUpvarIndex`.
77d4242001SAdam Bratschi-Kaye     static_modules: PrimaryMap<StaticModuleIndex, Module>,
78d4242001SAdam Bratschi-Kaye 
79d4242001SAdam Bratschi-Kaye     /// Code-related information such as the compiled artifact, type
80d4242001SAdam Bratschi-Kaye     /// information, etc.
81d4242001SAdam Bratschi-Kaye     ///
82d4242001SAdam Bratschi-Kaye     /// Note that the `Arc` here is used to share this allocation with internal
83d4242001SAdam Bratschi-Kaye     /// modules.
8499ecf728SChris Fallin     code: Arc<EngineCode>,
85d4242001SAdam Bratschi-Kaye 
86d4242001SAdam Bratschi-Kaye     /// Metadata produced during compilation.
87d4242001SAdam Bratschi-Kaye     info: CompiledComponentInfo,
88d961fc07SNick Fitzgerald 
891806c265SNick Fitzgerald     /// The index of compiled functions and their locations in the text section
901806c265SNick Fitzgerald     /// for this component.
911806c265SNick Fitzgerald     index: Arc<CompiledFunctionsTable>,
921806c265SNick Fitzgerald 
93d961fc07SNick Fitzgerald     /// A cached handle to the `wasmtime::FuncType` for the canonical ABI's
94d961fc07SNick Fitzgerald     /// `realloc`, to avoid the need to look up types in the registry and take
95d961fc07SNick Fitzgerald     /// locks when calling `realloc` via `TypedFunc::call_raw`.
968fb9d189SAlex Crichton     realloc_func_type: Arc<FuncType>,
97b298f375SArjun Ramesh 
98b298f375SArjun Ramesh     /// The checksum of the source binary from which the module was compiled.
99b298f375SArjun Ramesh     checksum: WasmChecksum,
100d4242001SAdam Bratschi-Kaye }
101d4242001SAdam Bratschi-Kaye 
102d4242001SAdam Bratschi-Kaye pub(crate) struct AllCallFuncPointers {
103d4242001SAdam Bratschi-Kaye     pub wasm_call: NonNull<VMWasmCallFunction>,
1042e6b18f0SAlex Crichton     pub array_call: NonNull<VMArrayCallFunction>,
105d4242001SAdam Bratschi-Kaye }
106d4242001SAdam Bratschi-Kaye 
107d4242001SAdam Bratschi-Kaye impl Component {
1086d105f4dSAlex Crichton     /// Compiles a new WebAssembly component from the in-memory list of bytes
109d4242001SAdam Bratschi-Kaye     /// provided.
1106d105f4dSAlex Crichton     ///
1116d105f4dSAlex Crichton     /// The `bytes` provided can either be the binary or text format of a
1126d105f4dSAlex Crichton     /// [WebAssembly component]. Note that the text format requires the `wat`
1136d105f4dSAlex Crichton     /// feature of this crate to be enabled. This API does not support
1146d105f4dSAlex Crichton     /// streaming compilation.
1156d105f4dSAlex Crichton     ///
1166d105f4dSAlex Crichton     /// This function will synchronously validate the entire component,
1176d105f4dSAlex Crichton     /// including all core modules, and then compile all components, modules,
1186d105f4dSAlex Crichton     /// etc., found within the provided bytes.
1196d105f4dSAlex Crichton     ///
1206d105f4dSAlex Crichton     /// [WebAssembly component]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Binary.md
1216d105f4dSAlex Crichton     ///
1226d105f4dSAlex Crichton     /// # Errors
1236d105f4dSAlex Crichton     ///
1246d105f4dSAlex Crichton     /// This function may fail and return an error. Errors may include
1256d105f4dSAlex Crichton     /// situations such as:
1266d105f4dSAlex Crichton     ///
1276d105f4dSAlex Crichton     /// * The binary provided could not be decoded because it's not a valid
1286d105f4dSAlex Crichton     ///   WebAssembly binary
1296d105f4dSAlex Crichton     /// * The WebAssembly binary may not validate (e.g. contains type errors)
1306d105f4dSAlex Crichton     /// * Implementation-specific limits were exceeded with a valid binary (for
1316d105f4dSAlex Crichton     ///   example too many locals)
1326d105f4dSAlex Crichton     /// * The wasm binary may use features that are not enabled in the
1336d105f4dSAlex Crichton     ///   configuration of `engine`
1346d105f4dSAlex Crichton     /// * If the `wat` feature is enabled and the input is text, then it may be
1356d105f4dSAlex Crichton     ///   rejected if it fails to parse.
1366d105f4dSAlex Crichton     ///
1376d105f4dSAlex Crichton     /// The error returned should contain full information about why compilation
1386d105f4dSAlex Crichton     /// failed.
1396d105f4dSAlex Crichton     ///
1406d105f4dSAlex Crichton     /// # Examples
1416d105f4dSAlex Crichton     ///
1426d105f4dSAlex Crichton     /// The `new` function can be invoked with a in-memory array of bytes:
1436d105f4dSAlex Crichton     ///
1446d105f4dSAlex Crichton     /// ```no_run
1456d105f4dSAlex Crichton     /// # use wasmtime::*;
1466d105f4dSAlex Crichton     /// # use wasmtime::component::Component;
14796e19700SNick Fitzgerald     /// # fn main() -> Result<()> {
1486d105f4dSAlex Crichton     /// # let engine = Engine::default();
1496d105f4dSAlex Crichton     /// # let wasm_bytes: Vec<u8> = Vec::new();
1506d105f4dSAlex Crichton     /// let component = Component::new(&engine, &wasm_bytes)?;
1516d105f4dSAlex Crichton     /// # Ok(())
1526d105f4dSAlex Crichton     /// # }
1536d105f4dSAlex Crichton     /// ```
1546d105f4dSAlex Crichton     ///
1556d105f4dSAlex Crichton     /// Or you can also pass in a string to be parsed as the wasm text
1566d105f4dSAlex Crichton     /// format:
1576d105f4dSAlex Crichton     ///
1586d105f4dSAlex Crichton     /// ```
1596d105f4dSAlex Crichton     /// # use wasmtime::*;
1606d105f4dSAlex Crichton     /// # use wasmtime::component::Component;
16196e19700SNick Fitzgerald     /// # fn main() -> Result<()> {
1626d105f4dSAlex Crichton     /// # let engine = Engine::default();
1636d105f4dSAlex Crichton     /// let component = Component::new(&engine, "(component (core module))")?;
1646d105f4dSAlex Crichton     /// # Ok(())
1656d105f4dSAlex Crichton     /// # }
166d4242001SAdam Bratschi-Kaye     #[cfg(any(feature = "cranelift", feature = "winch"))]
new(engine: &Engine, bytes: impl AsRef<[u8]>) -> Result<Component>167d4242001SAdam Bratschi-Kaye     pub fn new(engine: &Engine, bytes: impl AsRef<[u8]>) -> Result<Component> {
16855664f5aSAlex Crichton         crate::CodeBuilder::new(engine)
169f673cde3SAlex Crichton             .wasm_binary_or_text(bytes.as_ref(), None)?
17055664f5aSAlex Crichton             .compile_component()
171d4242001SAdam Bratschi-Kaye     }
172d4242001SAdam Bratschi-Kaye 
1736d105f4dSAlex Crichton     /// Compiles a new WebAssembly component from a wasm file on disk pointed
1746d105f4dSAlex Crichton     /// to by `file`.
1756d105f4dSAlex Crichton     ///
1766d105f4dSAlex Crichton     /// This is a convenience function for reading the contents of `file` on
1776d105f4dSAlex Crichton     /// disk and then calling [`Component::new`].
17881a89169SAlex Crichton     #[cfg(all(feature = "std", any(feature = "cranelift", feature = "winch")))]
from_file(engine: &Engine, file: impl AsRef<Path>) -> Result<Component>179d4242001SAdam Bratschi-Kaye     pub fn from_file(engine: &Engine, file: impl AsRef<Path>) -> Result<Component> {
18055664f5aSAlex Crichton         crate::CodeBuilder::new(engine)
181f673cde3SAlex Crichton             .wasm_binary_or_text_file(file.as_ref())?
18255664f5aSAlex Crichton             .compile_component()
183d4242001SAdam Bratschi-Kaye     }
184d4242001SAdam Bratschi-Kaye 
185d4242001SAdam Bratschi-Kaye     /// Compiles a new WebAssembly component from the in-memory wasm image
186d4242001SAdam Bratschi-Kaye     /// provided.
1876d105f4dSAlex Crichton     ///
1886d105f4dSAlex Crichton     /// This function is the same as [`Component::new`] except that it does not
1896d105f4dSAlex Crichton     /// accept the text format of WebAssembly. Even if the `wat` feature
1906d105f4dSAlex Crichton     /// is enabled an error will be returned here if `binary` is the text
1916d105f4dSAlex Crichton     /// format.
1926d105f4dSAlex Crichton     ///
1936d105f4dSAlex Crichton     /// For more information on semantics and errors see [`Component::new`].
194d4242001SAdam Bratschi-Kaye     #[cfg(any(feature = "cranelift", feature = "winch"))]
from_binary(engine: &Engine, binary: &[u8]) -> Result<Component>195d4242001SAdam Bratschi-Kaye     pub fn from_binary(engine: &Engine, binary: &[u8]) -> Result<Component> {
19655664f5aSAlex Crichton         crate::CodeBuilder::new(engine)
197f673cde3SAlex Crichton             .wasm_binary(binary, None)?
19855664f5aSAlex Crichton             .compile_component()
199d4242001SAdam Bratschi-Kaye     }
200d4242001SAdam Bratschi-Kaye 
201d4242001SAdam Bratschi-Kaye     /// Same as [`Module::deserialize`], but for components.
202d4242001SAdam Bratschi-Kaye     ///
2036d105f4dSAlex Crichton     /// Note that the bytes referenced here must contain contents previously
204d4242001SAdam Bratschi-Kaye     /// produced by [`Engine::precompile_component`] or
205d4242001SAdam Bratschi-Kaye     /// [`Component::serialize`].
206d4242001SAdam Bratschi-Kaye     ///
207d4242001SAdam Bratschi-Kaye     /// For more information see the [`Module::deserialize`] method.
208d4242001SAdam Bratschi-Kaye     ///
2096d105f4dSAlex Crichton     /// # Unsafety
2106d105f4dSAlex Crichton     ///
2116d105f4dSAlex Crichton     /// The unsafety of this method is the same as that of the
2126d105f4dSAlex Crichton     /// [`Module::deserialize`] method.
2136d105f4dSAlex Crichton     ///
214d4242001SAdam Bratschi-Kaye     /// [`Module::deserialize`]: crate::Module::deserialize
deserialize(engine: &Engine, bytes: impl AsRef<[u8]>) -> Result<Component>215d4242001SAdam Bratschi-Kaye     pub unsafe fn deserialize(engine: &Engine, bytes: impl AsRef<[u8]>) -> Result<Component> {
216d4242001SAdam Bratschi-Kaye         let code = engine.load_code_bytes(bytes.as_ref(), ObjectKind::Component)?;
217d4242001SAdam Bratschi-Kaye         Component::from_parts(engine, code, None)
218d4242001SAdam Bratschi-Kaye     }
219d4242001SAdam Bratschi-Kaye 
22099efc20bSPaul Osborne     /// Same as [`Module::deserialize_raw`], but for components.
22199efc20bSPaul Osborne     ///
22299efc20bSPaul Osborne     /// See [`Component::deserialize`] for additional information; this method
22399efc20bSPaul Osborne     /// works identically except that it will not create a copy of the provided
22499efc20bSPaul Osborne     /// memory but will use it directly.
22599efc20bSPaul Osborne     ///
22699efc20bSPaul Osborne     /// # Unsafety
22799efc20bSPaul Osborne     ///
22899efc20bSPaul Osborne     /// All of the safety notes from [`Component::deserialize`] apply here as well
22999efc20bSPaul Osborne     /// with the additional constraint that the code memory provide by `memory`
23099efc20bSPaul Osborne     /// lives for as long as the module and is nevery externally modified for
23199efc20bSPaul Osborne     /// the lifetime of the deserialized module.
deserialize_raw(engine: &Engine, memory: NonNull<[u8]>) -> Result<Component>23299efc20bSPaul Osborne     pub unsafe fn deserialize_raw(engine: &Engine, memory: NonNull<[u8]>) -> Result<Component> {
2330f457fadSAlex Crichton         // SAFETY: the contract required by `load_code_raw` is the same as this
2340f457fadSAlex Crichton         // function.
2350f457fadSAlex Crichton         let code = unsafe { engine.load_code_raw(memory, ObjectKind::Component)? };
23699efc20bSPaul Osborne         Component::from_parts(engine, code, None)
23799efc20bSPaul Osborne     }
23899efc20bSPaul Osborne 
239d4242001SAdam Bratschi-Kaye     /// Same as [`Module::deserialize_file`], but for components.
240d4242001SAdam Bratschi-Kaye     ///
2416d105f4dSAlex Crichton     /// Note that the file referenced here must contain contents previously
2426d105f4dSAlex Crichton     /// produced by [`Engine::precompile_component`] or
2436d105f4dSAlex Crichton     /// [`Component::serialize`].
2446d105f4dSAlex Crichton     ///
2456d105f4dSAlex Crichton     /// For more information see the [`Module::deserialize_file`] method.
2466d105f4dSAlex Crichton     ///
2476d105f4dSAlex Crichton     /// # Unsafety
2486d105f4dSAlex Crichton     ///
2496d105f4dSAlex Crichton     /// The unsafety of this method is the same as that of the
2506d105f4dSAlex Crichton     /// [`Module::deserialize_file`] method.
251d4242001SAdam Bratschi-Kaye     ///
252d4242001SAdam Bratschi-Kaye     /// [`Module::deserialize_file`]: crate::Module::deserialize_file
25381a89169SAlex Crichton     #[cfg(feature = "std")]
deserialize_file(engine: &Engine, path: impl AsRef<Path>) -> Result<Component>254d4242001SAdam Bratschi-Kaye     pub unsafe fn deserialize_file(engine: &Engine, path: impl AsRef<Path>) -> Result<Component> {
25515b464b6SAdam Bratschi-Kaye         let file = open_file_for_mmap(path.as_ref())?;
25615b464b6SAdam Bratschi-Kaye         let code = engine
25715b464b6SAdam Bratschi-Kaye             .load_code_file(file, ObjectKind::Component)
25815b464b6SAdam Bratschi-Kaye             .with_context(|| format!("failed to load code for: {}", path.as_ref().display()))?;
259d4242001SAdam Bratschi-Kaye         Component::from_parts(engine, code, None)
260d4242001SAdam Bratschi-Kaye     }
261d4242001SAdam Bratschi-Kaye 
26245a8da69SAlex Crichton     /// Returns the type of this component as a [`types::Component`].
26345a8da69SAlex Crichton     ///
26445a8da69SAlex Crichton     /// This method enables runtime introspection of the type of a component
26545a8da69SAlex Crichton     /// before instantiation, if necessary.
26645a8da69SAlex Crichton     ///
26745a8da69SAlex Crichton     /// ## Component types and Resources
26845a8da69SAlex Crichton     ///
26945a8da69SAlex Crichton     /// An important point to note here is that the precise type of imports and
27045a8da69SAlex Crichton     /// exports of a component change when it is instantiated with respect to
27145a8da69SAlex Crichton     /// resources. For example a [`Component`] represents an un-instantiated
2725393c2bfSBruce Mitchener     /// component meaning that its imported resources are represented as abstract
27345a8da69SAlex Crichton     /// resource types. These abstract types are not equal to any other
27445a8da69SAlex Crichton     /// component's types.
27545a8da69SAlex Crichton     ///
27645a8da69SAlex Crichton     /// For example:
27745a8da69SAlex Crichton     ///
27845a8da69SAlex Crichton     /// ```
27945a8da69SAlex Crichton     /// # use wasmtime::Engine;
28045a8da69SAlex Crichton     /// # use wasmtime::component::Component;
28145a8da69SAlex Crichton     /// # use wasmtime::component::types::ComponentItem;
28245a8da69SAlex Crichton     /// # fn main() -> wasmtime::Result<()> {
28345a8da69SAlex Crichton     /// # let engine = Engine::default();
28445a8da69SAlex Crichton     /// let a = Component::new(&engine, r#"
28545a8da69SAlex Crichton     ///     (component (import "x" (type (sub resource))))
28645a8da69SAlex Crichton     /// "#)?;
28745a8da69SAlex Crichton     /// let b = Component::new(&engine, r#"
28845a8da69SAlex Crichton     ///     (component (import "x" (type (sub resource))))
28945a8da69SAlex Crichton     /// "#)?;
29045a8da69SAlex Crichton     ///
29145a8da69SAlex Crichton     /// let (_, a_ty) = a.component_type().imports(&engine).next().unwrap();
29245a8da69SAlex Crichton     /// let (_, b_ty) = b.component_type().imports(&engine).next().unwrap();
29345a8da69SAlex Crichton     ///
29445a8da69SAlex Crichton     /// let a_ty = match a_ty {
29545a8da69SAlex Crichton     ///     ComponentItem::Resource(ty) => ty,
29645a8da69SAlex Crichton     ///     _ => unreachable!(),
29745a8da69SAlex Crichton     /// };
29845a8da69SAlex Crichton     /// let b_ty = match b_ty {
29945a8da69SAlex Crichton     ///     ComponentItem::Resource(ty) => ty,
30045a8da69SAlex Crichton     ///     _ => unreachable!(),
30145a8da69SAlex Crichton     /// };
30245a8da69SAlex Crichton     /// assert!(a_ty != b_ty);
30345a8da69SAlex Crichton     /// # Ok(())
30445a8da69SAlex Crichton     /// # }
30545a8da69SAlex Crichton     /// ```
30645a8da69SAlex Crichton     ///
30745a8da69SAlex Crichton     /// Additionally, however, these abstract types are "substituted" during
30845a8da69SAlex Crichton     /// instantiation meaning that a component type will appear to have changed
30945a8da69SAlex Crichton     /// once it is instantiated.
31045a8da69SAlex Crichton     ///
31145a8da69SAlex Crichton     /// ```
31245a8da69SAlex Crichton     /// # use wasmtime::{Engine, Store};
31345a8da69SAlex Crichton     /// # use wasmtime::component::{Component, Linker, ResourceType};
31445a8da69SAlex Crichton     /// # use wasmtime::component::types::ComponentItem;
31545a8da69SAlex Crichton     /// # fn main() -> wasmtime::Result<()> {
31645a8da69SAlex Crichton     /// # let engine = Engine::default();
31745a8da69SAlex Crichton     /// // Here this component imports a resource and then exports it as-is
31845a8da69SAlex Crichton     /// // which means that the export is equal to the import.
31945a8da69SAlex Crichton     /// let a = Component::new(&engine, r#"
32045a8da69SAlex Crichton     ///     (component
32145a8da69SAlex Crichton     ///         (import "x" (type $x (sub resource)))
32245a8da69SAlex Crichton     ///         (export "x" (type $x))
32345a8da69SAlex Crichton     ///     )
32445a8da69SAlex Crichton     /// "#)?;
32545a8da69SAlex Crichton     ///
32645a8da69SAlex Crichton     /// let (_, import) = a.component_type().imports(&engine).next().unwrap();
32745a8da69SAlex Crichton     /// let (_, export) = a.component_type().exports(&engine).next().unwrap();
32845a8da69SAlex Crichton     ///
32945a8da69SAlex Crichton     /// let import = match import {
33045a8da69SAlex Crichton     ///     ComponentItem::Resource(ty) => ty,
33145a8da69SAlex Crichton     ///     _ => unreachable!(),
33245a8da69SAlex Crichton     /// };
33345a8da69SAlex Crichton     /// let export = match export {
33445a8da69SAlex Crichton     ///     ComponentItem::Resource(ty) => ty,
33545a8da69SAlex Crichton     ///     _ => unreachable!(),
33645a8da69SAlex Crichton     /// };
33745a8da69SAlex Crichton     /// assert_eq!(import, export);
33845a8da69SAlex Crichton     ///
33945a8da69SAlex Crichton     /// // However after instantiation the resource type "changes"
34045a8da69SAlex Crichton     /// let mut store = Store::new(&engine, ());
34145a8da69SAlex Crichton     /// let mut linker = Linker::new(&engine);
34245a8da69SAlex Crichton     /// linker.root().resource("x", ResourceType::host::<()>(), |_, _| Ok(()))?;
34345a8da69SAlex Crichton     /// let instance = linker.instantiate(&mut store, &a)?;
3443171ef6dSAlex Crichton     /// let instance_ty = instance.get_resource(&mut store, "x").unwrap();
34545a8da69SAlex Crichton     ///
34645a8da69SAlex Crichton     /// // Here `instance_ty` is not the same as either `import` or `export`,
34745a8da69SAlex Crichton     /// // but it is equal to what we provided as an import.
34845a8da69SAlex Crichton     /// assert!(instance_ty != import);
34945a8da69SAlex Crichton     /// assert!(instance_ty != export);
35045a8da69SAlex Crichton     /// assert!(instance_ty == ResourceType::host::<()>());
35145a8da69SAlex Crichton     /// # Ok(())
35245a8da69SAlex Crichton     /// # }
35345a8da69SAlex Crichton     /// ```
35445a8da69SAlex Crichton     ///
35545a8da69SAlex Crichton     /// Finally, each instantiation of an exported resource from a component is
35645a8da69SAlex Crichton     /// considered "fresh" for all instantiations meaning that different
35745a8da69SAlex Crichton     /// instantiations will have different exported resource types:
35845a8da69SAlex Crichton     ///
35945a8da69SAlex Crichton     /// ```
36045a8da69SAlex Crichton     /// # use wasmtime::{Engine, Store};
36145a8da69SAlex Crichton     /// # use wasmtime::component::{Component, Linker};
36245a8da69SAlex Crichton     /// # fn main() -> wasmtime::Result<()> {
36345a8da69SAlex Crichton     /// # let engine = Engine::default();
36445a8da69SAlex Crichton     /// let a = Component::new(&engine, r#"
36545a8da69SAlex Crichton     ///     (component
36645a8da69SAlex Crichton     ///         (type $x (resource (rep i32)))
36745a8da69SAlex Crichton     ///         (export "x" (type $x))
36845a8da69SAlex Crichton     ///     )
36945a8da69SAlex Crichton     /// "#)?;
37045a8da69SAlex Crichton     ///
37145a8da69SAlex Crichton     /// let mut store = Store::new(&engine, ());
37245a8da69SAlex Crichton     /// let linker = Linker::new(&engine);
37345a8da69SAlex Crichton     /// let instance1 = linker.instantiate(&mut store, &a)?;
37445a8da69SAlex Crichton     /// let instance2 = linker.instantiate(&mut store, &a)?;
37545a8da69SAlex Crichton     ///
3763171ef6dSAlex Crichton     /// let x1 = instance1.get_resource(&mut store, "x").unwrap();
3773171ef6dSAlex Crichton     /// let x2 = instance2.get_resource(&mut store, "x").unwrap();
37845a8da69SAlex Crichton     ///
37945a8da69SAlex Crichton     /// // Despite these two resources being the same export of the same
38045a8da69SAlex Crichton     /// // component they come from two different instances meaning that their
38145a8da69SAlex Crichton     /// // types will be unique.
38245a8da69SAlex Crichton     /// assert!(x1 != x2);
38345a8da69SAlex Crichton     /// # Ok(())
38445a8da69SAlex Crichton     /// # }
38545a8da69SAlex Crichton     /// ```
component_type(&self) -> types::Component38645a8da69SAlex Crichton     pub fn component_type(&self) -> types::Component {
3873171ef6dSAlex Crichton         self.with_uninstantiated_instance_type(|ty| types::Component::from(self.inner.ty, ty))
3883171ef6dSAlex Crichton     }
3893171ef6dSAlex Crichton 
with_uninstantiated_instance_type<R>(&self, f: impl FnOnce(&InstanceType<'_>) -> R) -> R3903171ef6dSAlex Crichton     fn with_uninstantiated_instance_type<R>(&self, f: impl FnOnce(&InstanceType<'_>) -> R) -> R {
39145a8da69SAlex Crichton         let resources = Arc::new(PrimaryMap::new());
3923171ef6dSAlex Crichton         f(&InstanceType {
39345a8da69SAlex Crichton             types: self.types(),
39445a8da69SAlex Crichton             resources: &resources,
3953171ef6dSAlex Crichton         })
39645a8da69SAlex Crichton     }
39745a8da69SAlex Crichton 
398d4242001SAdam Bratschi-Kaye     /// Final assembly step for a component from its in-memory representation.
399d4242001SAdam Bratschi-Kaye     ///
400d4242001SAdam Bratschi-Kaye     /// If the `artifacts` are specified as `None` here then they will be
401d4242001SAdam Bratschi-Kaye     /// deserialized from `code_memory`.
from_parts( engine: &Engine, code_memory: Arc<CodeMemory>, artifacts: Option<ComponentArtifacts>, ) -> Result<Component>40255664f5aSAlex Crichton     pub(crate) fn from_parts(
403d4242001SAdam Bratschi-Kaye         engine: &Engine,
404d4242001SAdam Bratschi-Kaye         code_memory: Arc<CodeMemory>,
405d4242001SAdam Bratschi-Kaye         artifacts: Option<ComponentArtifacts>,
406d4242001SAdam Bratschi-Kaye     ) -> Result<Component> {
407d4242001SAdam Bratschi-Kaye         let ComponentArtifacts {
408d4242001SAdam Bratschi-Kaye             ty,
409d4242001SAdam Bratschi-Kaye             info,
4101806c265SNick Fitzgerald             table: index,
411cb235ecfSNick Fitzgerald             mut types,
412cb235ecfSNick Fitzgerald             mut static_modules,
413b298f375SArjun Ramesh             checksum,
414d4242001SAdam Bratschi-Kaye         } = match artifacts {
415d4242001SAdam Bratschi-Kaye             Some(artifacts) => artifacts,
4169034e101SAlex Crichton             None => postcard::from_bytes(code_memory.wasmtime_info())?,
417d4242001SAdam Bratschi-Kaye         };
4181806c265SNick Fitzgerald         let index = Arc::new(index);
419d4242001SAdam Bratschi-Kaye 
420d4242001SAdam Bratschi-Kaye         // Validate that the component can be used with the current instance
421d4242001SAdam Bratschi-Kaye         // allocator.
422d4242001SAdam Bratschi-Kaye         engine.allocator().validate_component(
423d4242001SAdam Bratschi-Kaye             &info.component,
424d4242001SAdam Bratschi-Kaye             &VMComponentOffsets::new(HostPtr, &info.component),
425d4242001SAdam Bratschi-Kaye             &|module_index| &static_modules[module_index].module,
426d4242001SAdam Bratschi-Kaye         )?;
427d4242001SAdam Bratschi-Kaye 
428d4242001SAdam Bratschi-Kaye         // Create a signature registration with the `Engine` for all trampolines
429d4242001SAdam Bratschi-Kaye         // and core wasm types found within this component, both for the
430d4242001SAdam Bratschi-Kaye         // component and for all included core wasm modules.
431cb235ecfSNick Fitzgerald         let signatures = engine.register_and_canonicalize_types(
432cb235ecfSNick Fitzgerald             types.module_types_mut(),
433cb235ecfSNick Fitzgerald             static_modules.iter_mut().map(|(_, m)| &mut m.module),
4349e3b5ee5SNick Fitzgerald         )?;
435cb235ecfSNick Fitzgerald         types.canonicalize_for_runtime_usage(&mut |idx| signatures.shared_type(idx).unwrap());
436d4242001SAdam Bratschi-Kaye 
43799ecf728SChris Fallin         // Assemble the `EngineCode` artifact which is shared by all core wasm
438d4242001SAdam Bratschi-Kaye         // modules as well as the final component.
439d4242001SAdam Bratschi-Kaye         let types = Arc::new(types);
4406e0ded7cSNick Fitzgerald         let code = Arc::new(EngineCode::new(code_memory, signatures, types.into())?);
441d4242001SAdam Bratschi-Kaye 
442d4242001SAdam Bratschi-Kaye         // Convert all information about static core wasm modules into actual
443d4242001SAdam Bratschi-Kaye         // `Module` instances by converting each `CompiledModuleInfo`, the
444d4242001SAdam Bratschi-Kaye         // `types` type information, and the code memory to a runtime object.
445d4242001SAdam Bratschi-Kaye         let static_modules = static_modules
446d4242001SAdam Bratschi-Kaye             .into_iter()
4471806c265SNick Fitzgerald             .map(|(_, info)| {
4481806c265SNick Fitzgerald                 Module::from_parts_raw(engine, code.clone(), info, index.clone(), false)
4491806c265SNick Fitzgerald             })
450d4242001SAdam Bratschi-Kaye             .collect::<Result<_>>()?;
451d4242001SAdam Bratschi-Kaye 
452d961fc07SNick Fitzgerald         let realloc_func_type = Arc::new(FuncType::new(
453d961fc07SNick Fitzgerald             engine,
454d961fc07SNick Fitzgerald             [ValType::I32, ValType::I32, ValType::I32, ValType::I32],
455d961fc07SNick Fitzgerald             [ValType::I32],
4568fb9d189SAlex Crichton         ));
457d961fc07SNick Fitzgerald 
458d4242001SAdam Bratschi-Kaye         Ok(Component {
459d4242001SAdam Bratschi-Kaye             inner: Arc::new(ComponentInner {
4603171ef6dSAlex Crichton                 id: CompiledModuleId::new(),
4613171ef6dSAlex Crichton                 engine: engine.clone(),
462d4242001SAdam Bratschi-Kaye                 ty,
463d4242001SAdam Bratschi-Kaye                 static_modules,
464d4242001SAdam Bratschi-Kaye                 code,
465d4242001SAdam Bratschi-Kaye                 info,
4661806c265SNick Fitzgerald                 index,
467d961fc07SNick Fitzgerald                 realloc_func_type,
468b298f375SArjun Ramesh                 checksum,
469d4242001SAdam Bratschi-Kaye             }),
470d4242001SAdam Bratschi-Kaye         })
471d4242001SAdam Bratschi-Kaye     }
472d4242001SAdam Bratschi-Kaye 
ty(&self) -> TypeComponentIndex473d4242001SAdam Bratschi-Kaye     pub(crate) fn ty(&self) -> TypeComponentIndex {
474d4242001SAdam Bratschi-Kaye         self.inner.ty
475d4242001SAdam Bratschi-Kaye     }
476d4242001SAdam Bratschi-Kaye 
env_component(&self) -> &wasmtime_environ::component::Component477d4242001SAdam Bratschi-Kaye     pub(crate) fn env_component(&self) -> &wasmtime_environ::component::Component {
478d4242001SAdam Bratschi-Kaye         &self.inner.info.component
479d4242001SAdam Bratschi-Kaye     }
480d4242001SAdam Bratschi-Kaye 
static_module(&self, idx: StaticModuleIndex) -> &Module481d4242001SAdam Bratschi-Kaye     pub(crate) fn static_module(&self, idx: StaticModuleIndex) -> &Module {
482d4242001SAdam Bratschi-Kaye         &self.inner.static_modules[idx]
483d4242001SAdam Bratschi-Kaye     }
484d4242001SAdam Bratschi-Kaye 
485*856fb272SChris Fallin     #[cfg(any(feature = "profiling", feature = "debug"))]
static_modules(&self) -> impl Iterator<Item = &Module>486c3177fc4SPaul Osborne     pub(crate) fn static_modules(&self) -> impl Iterator<Item = &Module> {
487c3177fc4SPaul Osborne         self.inner.static_modules.values()
488c3177fc4SPaul Osborne     }
489c3177fc4SPaul Osborne 
490d4242001SAdam Bratschi-Kaye     #[inline]
types(&self) -> &Arc<ComponentTypes>491d4242001SAdam Bratschi-Kaye     pub(crate) fn types(&self) -> &Arc<ComponentTypes> {
4928fb9d189SAlex Crichton         match self.inner.code.types() {
4938fb9d189SAlex Crichton             crate::code::Types::Component(types) => types,
4948fb9d189SAlex Crichton             // The only creator of a `Component` is itself which uses the other
4958fb9d189SAlex Crichton             // variant, so this shouldn't be possible.
4968fb9d189SAlex Crichton             crate::code::Types::Module(_) => unreachable!(),
4978fb9d189SAlex Crichton         }
498d4242001SAdam Bratschi-Kaye     }
499d4242001SAdam Bratschi-Kaye 
signatures(&self) -> &TypeCollection500d4242001SAdam Bratschi-Kaye     pub(crate) fn signatures(&self) -> &TypeCollection {
501d4242001SAdam Bratschi-Kaye         self.inner.code.signatures()
502d4242001SAdam Bratschi-Kaye     }
503d4242001SAdam Bratschi-Kaye 
trampoline_ptrs(&self, index: TrampolineIndex) -> AllCallFuncPointers504d4242001SAdam Bratschi-Kaye     pub(crate) fn trampoline_ptrs(&self, index: TrampolineIndex) -> AllCallFuncPointers {
5051806c265SNick Fitzgerald         let wasm_call = self
50699ecf728SChris Fallin             .store_invariant_func(FuncKey::ComponentTrampoline(Abi::Wasm, index))
507ad56ff98SNick Fitzgerald             .unwrap()
508ad56ff98SNick Fitzgerald             .cast();
5091806c265SNick Fitzgerald         let array_call = self
51099ecf728SChris Fallin             .store_invariant_func(FuncKey::ComponentTrampoline(Abi::Array, index))
511ad56ff98SNick Fitzgerald             .unwrap()
512ad56ff98SNick Fitzgerald             .cast();
513d4242001SAdam Bratschi-Kaye         AllCallFuncPointers {
514ad56ff98SNick Fitzgerald             wasm_call,
515ad56ff98SNick Fitzgerald             array_call,
516d4242001SAdam Bratschi-Kaye         }
517d4242001SAdam Bratschi-Kaye     }
518d4242001SAdam Bratschi-Kaye 
unsafe_intrinsic_ptrs( &self, intrinsic: UnsafeIntrinsic, ) -> Option<AllCallFuncPointers>519ad56ff98SNick Fitzgerald     pub(crate) fn unsafe_intrinsic_ptrs(
520ad56ff98SNick Fitzgerald         &self,
521ad56ff98SNick Fitzgerald         intrinsic: UnsafeIntrinsic,
522ad56ff98SNick Fitzgerald     ) -> Option<AllCallFuncPointers> {
523ad56ff98SNick Fitzgerald         let wasm_call = self
52499ecf728SChris Fallin             .store_invariant_func(FuncKey::UnsafeIntrinsic(Abi::Wasm, intrinsic))?
525ad56ff98SNick Fitzgerald             .cast();
526ad56ff98SNick Fitzgerald         let array_call = self
52799ecf728SChris Fallin             .store_invariant_func(FuncKey::UnsafeIntrinsic(Abi::Array, intrinsic))?
528ad56ff98SNick Fitzgerald             .cast();
529ad56ff98SNick Fitzgerald         Some(AllCallFuncPointers {
530ad56ff98SNick Fitzgerald             wasm_call,
531ad56ff98SNick Fitzgerald             array_call,
532ad56ff98SNick Fitzgerald         })
533ad56ff98SNick Fitzgerald     }
534ad56ff98SNick Fitzgerald 
535ad56ff98SNick Fitzgerald     /// Look up a function in this component's text section by `FuncKey`.
53699ecf728SChris Fallin     ///
53799ecf728SChris Fallin     /// This supports only `FuncKey`s that do not invoke Wasm code,
53899ecf728SChris Fallin     /// i.e., code that is potentially Store-specific.
store_invariant_func(&self, key: FuncKey) -> Option<NonNull<u8>>53999ecf728SChris Fallin     fn store_invariant_func(&self, key: FuncKey) -> Option<NonNull<u8>> {
54099ecf728SChris Fallin         assert!(key.is_store_invariant());
541ad56ff98SNick Fitzgerald         let loc = self.inner.index.func_loc(key)?;
542ad56ff98SNick Fitzgerald         Some(self.func_loc_to_pointer(loc))
543ad56ff98SNick Fitzgerald     }
544ad56ff98SNick Fitzgerald 
545ad56ff98SNick Fitzgerald     /// Given a function location within this component's text section, get a
546ad56ff98SNick Fitzgerald     /// pointer to the function.
547ad56ff98SNick Fitzgerald     ///
54899ecf728SChris Fallin     /// This works only for Store-invariant functions.
54999ecf728SChris Fallin     ///
550ad56ff98SNick Fitzgerald     /// Panics on out-of-bounds function locations.
func_loc_to_pointer(&self, loc: &FunctionLoc) -> NonNull<u8>551ad56ff98SNick Fitzgerald     fn func_loc_to_pointer(&self, loc: &FunctionLoc) -> NonNull<u8> {
55299ecf728SChris Fallin         let text = self.engine_code().text();
553d4242001SAdam Bratschi-Kaye         let trampoline = &text[loc.start as usize..][..loc.length as usize];
554a252f37eSAlex Crichton         NonNull::from(trampoline).cast()
555d4242001SAdam Bratschi-Kaye     }
556d4242001SAdam Bratschi-Kaye 
engine_code(&self) -> &Arc<EngineCode>55799ecf728SChris Fallin     pub(crate) fn engine_code(&self) -> &Arc<EngineCode> {
558d4242001SAdam Bratschi-Kaye         &self.inner.code
559d4242001SAdam Bratschi-Kaye     }
560d4242001SAdam Bratschi-Kaye 
561d4242001SAdam Bratschi-Kaye     /// Same as [`Module::serialize`], except for a component.
562d4242001SAdam Bratschi-Kaye     ///
563d4242001SAdam Bratschi-Kaye     /// Note that the artifact produced here must be passed to
564d4242001SAdam Bratschi-Kaye     /// [`Component::deserialize`] and is not compatible for use with
565d4242001SAdam Bratschi-Kaye     /// [`Module`].
566d4242001SAdam Bratschi-Kaye     ///
567d4242001SAdam Bratschi-Kaye     /// [`Module::serialize`]: crate::Module::serialize
568d4242001SAdam Bratschi-Kaye     /// [`Module`]: crate::Module
serialize(&self) -> Result<Vec<u8>>569d4242001SAdam Bratschi-Kaye     pub fn serialize(&self) -> Result<Vec<u8>> {
57099ecf728SChris Fallin         Ok(self.engine_code().image().to_vec())
571d4242001SAdam Bratschi-Kaye     }
572d4242001SAdam Bratschi-Kaye 
573d4242001SAdam Bratschi-Kaye     /// Creates a new `VMFuncRef` with all fields filled out for the destructor
574d4242001SAdam Bratschi-Kaye     /// specified.
575d4242001SAdam Bratschi-Kaye     ///
576d4242001SAdam Bratschi-Kaye     /// The `dtor`'s own `VMFuncRef` won't have `wasm_call` filled out but this
577d4242001SAdam Bratschi-Kaye     /// component may have `resource_drop_wasm_to_native_trampoline` filled out
578d4242001SAdam Bratschi-Kaye     /// if necessary in which case it's filled in here.
resource_drop_func_ref(&self, dtor: &crate::func::HostFunc) -> VMFuncRef579d4242001SAdam Bratschi-Kaye     pub(crate) fn resource_drop_func_ref(&self, dtor: &crate::func::HostFunc) -> VMFuncRef {
580d4242001SAdam Bratschi-Kaye         // Host functions never have their `wasm_call` filled in at this time.
581d4242001SAdam Bratschi-Kaye         assert!(dtor.func_ref().wasm_call.is_none());
582d4242001SAdam Bratschi-Kaye 
583d4242001SAdam Bratschi-Kaye         // Note that if `resource_drop_wasm_to_native_trampoline` is not present
584d4242001SAdam Bratschi-Kaye         // then this can't be called by the component, so it's ok to leave it
585d4242001SAdam Bratschi-Kaye         // blank.
586d4242001SAdam Bratschi-Kaye         let wasm_call = self
58799ecf728SChris Fallin             .store_invariant_func(FuncKey::ResourceDropTrampoline)
588ad56ff98SNick Fitzgerald             .map(|f| f.cast().into());
5891806c265SNick Fitzgerald 
590d4242001SAdam Bratschi-Kaye         VMFuncRef {
591d4242001SAdam Bratschi-Kaye             wasm_call,
592d4242001SAdam Bratschi-Kaye             ..*dtor.func_ref()
593d4242001SAdam Bratschi-Kaye         }
594d4242001SAdam Bratschi-Kaye     }
595d4242001SAdam Bratschi-Kaye 
596d4242001SAdam Bratschi-Kaye     /// Returns a summary of the resources required to instantiate this
597d4242001SAdam Bratschi-Kaye     /// [`Component`][crate::component::Component].
598d4242001SAdam Bratschi-Kaye     ///
599d4242001SAdam Bratschi-Kaye     /// Note that when a component imports and instantiates another component or
600d4242001SAdam Bratschi-Kaye     /// core module, we cannot determine ahead of time how many resources
601d4242001SAdam Bratschi-Kaye     /// instantiating this component will require, and therefore this method
602d4242001SAdam Bratschi-Kaye     /// will return `None` in these scenarios.
603d4242001SAdam Bratschi-Kaye     ///
604d4242001SAdam Bratschi-Kaye     /// Potential uses of the returned information:
605d4242001SAdam Bratschi-Kaye     ///
606d4242001SAdam Bratschi-Kaye     /// * Determining whether your pooling allocator configuration supports
607d4242001SAdam Bratschi-Kaye     ///   instantiating this component.
608d4242001SAdam Bratschi-Kaye     ///
609d4242001SAdam Bratschi-Kaye     /// * Deciding how many of which `Component` you want to instantiate within
610d4242001SAdam Bratschi-Kaye     ///   a fixed amount of resources, e.g. determining whether to create 5
611d4242001SAdam Bratschi-Kaye     ///   instances of component X or 10 instances of component Y.
612d4242001SAdam Bratschi-Kaye     ///
613d4242001SAdam Bratschi-Kaye     /// # Example
614d4242001SAdam Bratschi-Kaye     ///
615d4242001SAdam Bratschi-Kaye     /// ```
616d4242001SAdam Bratschi-Kaye     /// # fn main() -> wasmtime::Result<()> {
617d4242001SAdam Bratschi-Kaye     /// use wasmtime::{Config, Engine, component::Component};
618d4242001SAdam Bratschi-Kaye     ///
619d4242001SAdam Bratschi-Kaye     /// let mut config = Config::new();
620d4242001SAdam Bratschi-Kaye     /// config.wasm_multi_memory(true);
621d4242001SAdam Bratschi-Kaye     /// config.wasm_component_model(true);
622d4242001SAdam Bratschi-Kaye     /// let engine = Engine::new(&config)?;
623d4242001SAdam Bratschi-Kaye     ///
624d4242001SAdam Bratschi-Kaye     /// let component = Component::new(&engine, &r#"
625d4242001SAdam Bratschi-Kaye     ///     (component
626d4242001SAdam Bratschi-Kaye     ///         ;; Define a core module that uses two memories.
627d4242001SAdam Bratschi-Kaye     ///         (core module $m
628d4242001SAdam Bratschi-Kaye     ///             (memory 1)
629d4242001SAdam Bratschi-Kaye     ///             (memory 6)
630d4242001SAdam Bratschi-Kaye     ///         )
631d4242001SAdam Bratschi-Kaye     ///
632d4242001SAdam Bratschi-Kaye     ///         ;; Instantiate that core module three times.
633d4242001SAdam Bratschi-Kaye     ///         (core instance $i1 (instantiate (module $m)))
634d4242001SAdam Bratschi-Kaye     ///         (core instance $i2 (instantiate (module $m)))
635d4242001SAdam Bratschi-Kaye     ///         (core instance $i3 (instantiate (module $m)))
636d4242001SAdam Bratschi-Kaye     ///     )
637d4242001SAdam Bratschi-Kaye     /// "#)?;
638d4242001SAdam Bratschi-Kaye     ///
639d4242001SAdam Bratschi-Kaye     /// let resources = component.resources_required()
640d4242001SAdam Bratschi-Kaye     ///     .expect("this component does not import any core modules or instances");
641d4242001SAdam Bratschi-Kaye     ///
642d4242001SAdam Bratschi-Kaye     /// // Instantiating the component will require allocating two memories per
643d4242001SAdam Bratschi-Kaye     /// // core instance, and there are three instances, so six total memories.
644d4242001SAdam Bratschi-Kaye     /// assert_eq!(resources.num_memories, 6);
645d4242001SAdam Bratschi-Kaye     /// assert_eq!(resources.max_initial_memory_size, Some(6));
646d4242001SAdam Bratschi-Kaye     ///
647d4242001SAdam Bratschi-Kaye     /// // The component doesn't need any tables.
648d4242001SAdam Bratschi-Kaye     /// assert_eq!(resources.num_tables, 0);
649d4242001SAdam Bratschi-Kaye     /// assert_eq!(resources.max_initial_table_size, None);
650d4242001SAdam Bratschi-Kaye     /// # Ok(()) }
651d4242001SAdam Bratschi-Kaye     /// ```
resources_required(&self) -> Option<ResourcesRequired>652d4242001SAdam Bratschi-Kaye     pub fn resources_required(&self) -> Option<ResourcesRequired> {
653d4242001SAdam Bratschi-Kaye         let mut resources = ResourcesRequired {
654d4242001SAdam Bratschi-Kaye             num_memories: 0,
655d4242001SAdam Bratschi-Kaye             max_initial_memory_size: None,
656d4242001SAdam Bratschi-Kaye             num_tables: 0,
657d4242001SAdam Bratschi-Kaye             max_initial_table_size: None,
658d4242001SAdam Bratschi-Kaye         };
659d4242001SAdam Bratschi-Kaye         for init in &self.env_component().initializers {
660d4242001SAdam Bratschi-Kaye             match init {
661b271e452SJoel Dice                 GlobalInitializer::InstantiateModule(inst, _) => match inst {
662d4242001SAdam Bratschi-Kaye                     InstantiateModule::Static(index, _) => {
663d4242001SAdam Bratschi-Kaye                         let module = self.static_module(*index);
664d4242001SAdam Bratschi-Kaye                         resources.add(&module.resources_required());
665d4242001SAdam Bratschi-Kaye                     }
666d4242001SAdam Bratschi-Kaye                     InstantiateModule::Import(_, _) => {
667d4242001SAdam Bratschi-Kaye                         // We can't statically determine the resources required
668d4242001SAdam Bratschi-Kaye                         // to instantiate this component.
669d4242001SAdam Bratschi-Kaye                         return None;
670d4242001SAdam Bratschi-Kaye                     }
671d4242001SAdam Bratschi-Kaye                 },
672d4242001SAdam Bratschi-Kaye                 GlobalInitializer::LowerImport { .. }
673d4242001SAdam Bratschi-Kaye                 | GlobalInitializer::ExtractMemory(_)
674d8360be4SAndrew Brown                 | GlobalInitializer::ExtractTable(_)
675d4242001SAdam Bratschi-Kaye                 | GlobalInitializer::ExtractRealloc(_)
676442003adSJoel Dice                 | GlobalInitializer::ExtractCallback(_)
677d4242001SAdam Bratschi-Kaye                 | GlobalInitializer::ExtractPostReturn(_)
678d4242001SAdam Bratschi-Kaye                 | GlobalInitializer::Resource(_) => {}
679d4242001SAdam Bratschi-Kaye             }
680d4242001SAdam Bratschi-Kaye         }
681d4242001SAdam Bratschi-Kaye         Some(resources)
682d4242001SAdam Bratschi-Kaye     }
683120e6b23SAlex Crichton 
684120e6b23SAlex Crichton     /// Returns the range, in the host's address space, that this module's
685120e6b23SAlex Crichton     /// compiled code resides at.
686120e6b23SAlex Crichton     ///
687120e6b23SAlex Crichton     /// For more information see
68866266fa9Siximeow     /// [`Module::image_range`](crate::Module::image_range).
image_range(&self) -> Range<*const u8>689120e6b23SAlex Crichton     pub fn image_range(&self) -> Range<*const u8> {
6905566d520SChris Fallin         self.inner.code.image().as_ptr_range()
691120e6b23SAlex Crichton     }
6923171ef6dSAlex Crichton 
6935378d8e3SDan Gohman     /// Force initialization of copy-on-write images to happen here-and-now
6945378d8e3SDan Gohman     /// instead of when they're requested during first instantiation.
6955378d8e3SDan Gohman     ///
6965378d8e3SDan Gohman     /// When [copy-on-write memory
6975378d8e3SDan Gohman     /// initialization](crate::Config::memory_init_cow) is enabled then Wasmtime
6985378d8e3SDan Gohman     /// will lazily create the initialization image for a component. This method
6995378d8e3SDan Gohman     /// can be used to explicitly dictate when this initialization happens.
7005378d8e3SDan Gohman     ///
7015378d8e3SDan Gohman     /// Note that this largely only matters on Linux when memfd is used.
7025378d8e3SDan Gohman     /// Otherwise the copy-on-write image typically comes from disk and in that
7035378d8e3SDan Gohman     /// situation the creation of the image is trivial as the image is always
7045378d8e3SDan Gohman     /// sourced from disk. On Linux, though, when memfd is used a memfd is
7055378d8e3SDan Gohman     /// created and the initialization image is written to it.
7065378d8e3SDan Gohman     ///
7075378d8e3SDan Gohman     /// Also note that this method is not required to be called, it's available
7085378d8e3SDan Gohman     /// as a performance optimization if required but is otherwise handled
7095378d8e3SDan Gohman     /// automatically.
initialize_copy_on_write_image(&self) -> Result<()>7105378d8e3SDan Gohman     pub fn initialize_copy_on_write_image(&self) -> Result<()> {
7115378d8e3SDan Gohman         for (_, module) in self.inner.static_modules.iter() {
7125378d8e3SDan Gohman             module.initialize_copy_on_write_image()?;
7135378d8e3SDan Gohman         }
7145378d8e3SDan Gohman         Ok(())
7155378d8e3SDan Gohman     }
7165378d8e3SDan Gohman 
7173171ef6dSAlex Crichton     /// Looks up a specific export of this component by `name` optionally nested
7183171ef6dSAlex Crichton     /// within the `instance` provided.
7193171ef6dSAlex Crichton     ///
72095cc0297SPat Hickey     /// See related method [`Self::get_export`] for additional docs and
72195cc0297SPat Hickey     /// examples.
72295cc0297SPat Hickey     ///
72395cc0297SPat Hickey     /// This method is primarily used to acquire a [`ComponentExportIndex`]
72495cc0297SPat Hickey     /// which can be used with [`Instance`](crate::component::Instance) when
72595cc0297SPat Hickey     /// looking up exports. Export lookup with [`ComponentExportIndex`] can
72695cc0297SPat Hickey     /// skip string lookups at runtime and instead use a more efficient
72795cc0297SPat Hickey     /// index-based lookup.
72895cc0297SPat Hickey     ///
72995cc0297SPat Hickey     /// This method only returns the [`ComponentExportIndex`]. If you need the
73095cc0297SPat Hickey     /// corresponding [`types::ComponentItem`], use the related function
73195cc0297SPat Hickey     /// [`Self::get_export`].
73295cc0297SPat Hickey     ///
73395cc0297SPat Hickey     ///
73495cc0297SPat Hickey     /// [`Instance`](crate::component::Instance) has a corresponding method
73595cc0297SPat Hickey     /// [`Instance::get_export_index`](crate::component::Instance::get_export_index).
get_export_index( &self, instance: Option<&ComponentExportIndex>, name: &str, ) -> Option<ComponentExportIndex>73695cc0297SPat Hickey     pub fn get_export_index(
73795cc0297SPat Hickey         &self,
73895cc0297SPat Hickey         instance: Option<&ComponentExportIndex>,
73995cc0297SPat Hickey         name: &str,
74095cc0297SPat Hickey     ) -> Option<ComponentExportIndex> {
74195cc0297SPat Hickey         let index = self.lookup_export_index(instance, name)?;
74295cc0297SPat Hickey         Some(ComponentExportIndex {
74395cc0297SPat Hickey             id: self.inner.id,
74495cc0297SPat Hickey             index,
74595cc0297SPat Hickey         })
74695cc0297SPat Hickey     }
74795cc0297SPat Hickey 
74895cc0297SPat Hickey     /// Looks up a specific export of this component by `name` optionally nested
74995cc0297SPat Hickey     /// within the `instance` provided.
75095cc0297SPat Hickey     ///
7513171ef6dSAlex Crichton     /// This method is primarily used to acquire a [`ComponentExportIndex`]
7523171ef6dSAlex Crichton     /// which can be used with [`Instance`](crate::component::Instance) when
7533171ef6dSAlex Crichton     /// looking up exports. Export lookup with [`ComponentExportIndex`] can
7543171ef6dSAlex Crichton     /// skip string lookups at runtime and instead use a more efficient
7553171ef6dSAlex Crichton     /// index-based lookup.
7563171ef6dSAlex Crichton     ///
7573171ef6dSAlex Crichton     /// This method takes a few arguments:
7583171ef6dSAlex Crichton     ///
7593171ef6dSAlex Crichton     /// * `engine` - the engine that was used to compile this component.
7603171ef6dSAlex Crichton     /// * `instance` - an optional "parent instance" for the export being looked
7613171ef6dSAlex Crichton     ///   up. If this is `None` then the export is looked up on the root of the
7623171ef6dSAlex Crichton     ///   component itself, and otherwise the export is looked up on the
7633171ef6dSAlex Crichton     ///   `instance` specified. Note that `instance` must have come from a
7643171ef6dSAlex Crichton     ///   previous invocation of this method.
7653171ef6dSAlex Crichton     /// * `name` - the name of the export that's being looked up.
7663171ef6dSAlex Crichton     ///
7673171ef6dSAlex Crichton     /// If the export is located then two values are returned: a
7683171ef6dSAlex Crichton     /// [`types::ComponentItem`] which enables introspection about the type of
7693171ef6dSAlex Crichton     /// the export and a [`ComponentExportIndex`]. The index returned notably
7703171ef6dSAlex Crichton     /// implements the [`InstanceExportLookup`] trait which enables using it
7713171ef6dSAlex Crichton     /// with [`Instance::get_func`](crate::component::Instance::get_func) for
7723171ef6dSAlex Crichton     /// example.
7733171ef6dSAlex Crichton     ///
77495cc0297SPat Hickey     /// The returned [`types::ComponentItem`] is more expensive to calculate
77595cc0297SPat Hickey     /// than the [`ComponentExportIndex`]. If you only consume the
77695cc0297SPat Hickey     /// [`ComponentExportIndex`], use the related method
77795cc0297SPat Hickey     /// [`Self::get_export_index`] instead.
77895cc0297SPat Hickey     ///
77995cc0297SPat Hickey     /// [`Instance`](crate::component::Instance) has a corresponding method
78095cc0297SPat Hickey     /// [`Instance::get_export`](crate::component::Instance::get_export).
78195cc0297SPat Hickey     ///
7823171ef6dSAlex Crichton     /// # Examples
7833171ef6dSAlex Crichton     ///
7843171ef6dSAlex Crichton     /// ```
7853171ef6dSAlex Crichton     /// use wasmtime::{Engine, Store};
7863171ef6dSAlex Crichton     /// use wasmtime::component::{Component, Linker};
7873171ef6dSAlex Crichton     /// use wasmtime::component::types::ComponentItem;
7883171ef6dSAlex Crichton     ///
7893171ef6dSAlex Crichton     /// # fn main() -> wasmtime::Result<()> {
7903171ef6dSAlex Crichton     /// let engine = Engine::default();
7913171ef6dSAlex Crichton     /// let component = Component::new(
7923171ef6dSAlex Crichton     ///     &engine,
7933171ef6dSAlex Crichton     ///     r#"
7943171ef6dSAlex Crichton     ///         (component
7953171ef6dSAlex Crichton     ///             (core module $m
7963171ef6dSAlex Crichton     ///                 (func (export "f"))
7973171ef6dSAlex Crichton     ///             )
7983171ef6dSAlex Crichton     ///             (core instance $i (instantiate $m))
7993171ef6dSAlex Crichton     ///             (func (export "f")
8003171ef6dSAlex Crichton     ///                 (canon lift (core func $i "f")))
8013171ef6dSAlex Crichton     ///         )
8023171ef6dSAlex Crichton     ///     "#,
8033171ef6dSAlex Crichton     /// )?;
8043171ef6dSAlex Crichton     ///
8053171ef6dSAlex Crichton     /// // Perform a lookup of the function "f" before instantiaton.
80695cc0297SPat Hickey     /// let (ty, export) = component.get_export(None, "f").unwrap();
8073171ef6dSAlex Crichton     /// assert!(matches!(ty, ComponentItem::ComponentFunc(_)));
8083171ef6dSAlex Crichton     ///
8093171ef6dSAlex Crichton     /// // After instantiation use `export` to lookup the function in question
8103171ef6dSAlex Crichton     /// // which notably does not do a string lookup at runtime.
8113171ef6dSAlex Crichton     /// let mut store = Store::new(&engine, ());
8123171ef6dSAlex Crichton     /// let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
8133171ef6dSAlex Crichton     /// let func = instance.get_typed_func::<(), ()>(&mut store, &export)?;
8143171ef6dSAlex Crichton     /// // ...
8153171ef6dSAlex Crichton     /// # Ok(())
8163171ef6dSAlex Crichton     /// # }
8173171ef6dSAlex Crichton     /// ```
get_export( &self, instance: Option<&ComponentExportIndex>, name: &str, ) -> Option<(types::ComponentItem, ComponentExportIndex)>81895cc0297SPat Hickey     pub fn get_export(
8193171ef6dSAlex Crichton         &self,
8203171ef6dSAlex Crichton         instance: Option<&ComponentExportIndex>,
8213171ef6dSAlex Crichton         name: &str,
8223171ef6dSAlex Crichton     ) -> Option<(types::ComponentItem, ComponentExportIndex)> {
8233171ef6dSAlex Crichton         let info = self.env_component();
8243171ef6dSAlex Crichton         let index = self.lookup_export_index(instance, name)?;
8253171ef6dSAlex Crichton         let item = self.with_uninstantiated_instance_type(|instance| {
82695cc0297SPat Hickey             types::ComponentItem::from_export(
82795cc0297SPat Hickey                 &self.inner.engine,
82895cc0297SPat Hickey                 &info.export_items[index],
82995cc0297SPat Hickey                 instance,
83095cc0297SPat Hickey             )
8313171ef6dSAlex Crichton         });
8323171ef6dSAlex Crichton         Some((
8333171ef6dSAlex Crichton             item,
8343171ef6dSAlex Crichton             ComponentExportIndex {
8353171ef6dSAlex Crichton                 id: self.inner.id,
8363171ef6dSAlex Crichton                 index,
8373171ef6dSAlex Crichton             },
8383171ef6dSAlex Crichton         ))
8393171ef6dSAlex Crichton     }
8403171ef6dSAlex Crichton 
lookup_export_index( &self, instance: Option<&ComponentExportIndex>, name: &str, ) -> Option<ExportIndex>8413171ef6dSAlex Crichton     pub(crate) fn lookup_export_index(
8423171ef6dSAlex Crichton         &self,
8433171ef6dSAlex Crichton         instance: Option<&ComponentExportIndex>,
8443171ef6dSAlex Crichton         name: &str,
8453171ef6dSAlex Crichton     ) -> Option<ExportIndex> {
8463171ef6dSAlex Crichton         let info = self.env_component();
8473171ef6dSAlex Crichton         let exports = match instance {
8483171ef6dSAlex Crichton             Some(idx) => {
8493171ef6dSAlex Crichton                 if idx.id != self.inner.id {
8503171ef6dSAlex Crichton                     return None;
8513171ef6dSAlex Crichton                 }
8523171ef6dSAlex Crichton                 match &info.export_items[idx.index] {
8533171ef6dSAlex Crichton                     Export::Instance { exports, .. } => exports,
8543171ef6dSAlex Crichton                     _ => return None,
8553171ef6dSAlex Crichton                 }
8563171ef6dSAlex Crichton             }
8573171ef6dSAlex Crichton             None => &info.exports,
8583171ef6dSAlex Crichton         };
8599bdb731aSAlex Crichton         exports.get(name, &NameMapNoIntern).copied()
8603171ef6dSAlex Crichton     }
8613171ef6dSAlex Crichton 
id(&self) -> CompiledModuleId8623171ef6dSAlex Crichton     pub(crate) fn id(&self) -> CompiledModuleId {
8633171ef6dSAlex Crichton         self.inner.id
8643171ef6dSAlex Crichton     }
8653171ef6dSAlex Crichton 
8663171ef6dSAlex Crichton     /// Returns the [`Engine`] that this [`Component`] was compiled by.
engine(&self) -> &Engine8673171ef6dSAlex Crichton     pub fn engine(&self) -> &Engine {
8683171ef6dSAlex Crichton         &self.inner.engine
8693171ef6dSAlex Crichton     }
8708fb9d189SAlex Crichton 
realloc_func_ty(&self) -> &Arc<FuncType>8718fb9d189SAlex Crichton     pub(crate) fn realloc_func_ty(&self) -> &Arc<FuncType> {
8728fb9d189SAlex Crichton         &self.inner.realloc_func_type
8738fb9d189SAlex Crichton     }
874e33836c0SAlex Crichton 
875b298f375SArjun Ramesh     #[allow(
876b298f375SArjun Ramesh         unused,
877b298f375SArjun Ramesh         reason = "used only for verification with wasmtime `rr` feature \
878b298f375SArjun Ramesh         and requires a lot of unnecessary gating across crates"
879b298f375SArjun Ramesh     )]
checksum(&self) -> &WasmChecksum880b298f375SArjun Ramesh     pub(crate) fn checksum(&self) -> &WasmChecksum {
881b298f375SArjun Ramesh         &self.inner.checksum
882b298f375SArjun Ramesh     }
883b298f375SArjun Ramesh 
884e33836c0SAlex Crichton     /// Returns the `Export::LiftedFunction` metadata associated with `export`.
885e33836c0SAlex Crichton     ///
886e33836c0SAlex Crichton     /// # Panics
887e33836c0SAlex Crichton     ///
888e33836c0SAlex Crichton     /// Panics if `export` is out of bounds or if it isn't a `LiftedFunction`.
export_lifted_function( &self, export: ExportIndex, ) -> (TypeFuncIndex, &CoreDef, OptionsIndex)889e33836c0SAlex Crichton     pub(crate) fn export_lifted_function(
890e33836c0SAlex Crichton         &self,
891e33836c0SAlex Crichton         export: ExportIndex,
892815c10deSAlex Crichton     ) -> (TypeFuncIndex, &CoreDef, OptionsIndex) {
893815c10deSAlex Crichton         let component = self.env_component();
894815c10deSAlex Crichton         match &component.export_items[export] {
895815c10deSAlex Crichton             Export::LiftedFunction { ty, func, options } => (*ty, func, *options),
896e33836c0SAlex Crichton             _ => unreachable!(),
897e33836c0SAlex Crichton         }
898e33836c0SAlex Crichton     }
8993171ef6dSAlex Crichton }
9003171ef6dSAlex Crichton 
9013171ef6dSAlex Crichton /// A value which represents a known export of a component.
9023171ef6dSAlex Crichton ///
90395cc0297SPat Hickey /// This is the return value of [`Component::get_export`] and implements the
9043171ef6dSAlex Crichton /// [`InstanceExportLookup`] trait to work with lookups like
9053171ef6dSAlex Crichton /// [`Instance::get_func`](crate::component::Instance::get_func).
9063171ef6dSAlex Crichton #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
9073171ef6dSAlex Crichton pub struct ComponentExportIndex {
9083171ef6dSAlex Crichton     pub(crate) id: CompiledModuleId,
9093171ef6dSAlex Crichton     pub(crate) index: ExportIndex,
9103171ef6dSAlex Crichton }
9113171ef6dSAlex Crichton 
9123171ef6dSAlex Crichton impl InstanceExportLookup for ComponentExportIndex {
lookup(&self, component: &Component) -> Option<ExportIndex>9133171ef6dSAlex Crichton     fn lookup(&self, component: &Component) -> Option<ExportIndex> {
9143171ef6dSAlex Crichton         if component.inner.id == self.id {
9153171ef6dSAlex Crichton             Some(self.index)
9163171ef6dSAlex Crichton         } else {
9173171ef6dSAlex Crichton             None
9183171ef6dSAlex Crichton         }
9193171ef6dSAlex Crichton     }
920d4242001SAdam Bratschi-Kaye }
921d4242001SAdam Bratschi-Kaye 
922d4242001SAdam Bratschi-Kaye #[cfg(test)]
923d4242001SAdam Bratschi-Kaye mod tests {
924d4242001SAdam Bratschi-Kaye     use crate::component::Component;
9255566d520SChris Fallin     use crate::{CodeBuilder, Config, Engine};
926d4242001SAdam Bratschi-Kaye     use wasmtime_environ::MemoryInitialization;
927d4242001SAdam Bratschi-Kaye 
928d4242001SAdam Bratschi-Kaye     #[test]
cow_on_by_default()929d4242001SAdam Bratschi-Kaye     fn cow_on_by_default() {
930d4242001SAdam Bratschi-Kaye         let mut config = Config::new();
931d4242001SAdam Bratschi-Kaye         config.wasm_component_model(true);
932d4242001SAdam Bratschi-Kaye         let engine = Engine::new(&config).unwrap();
933d4242001SAdam Bratschi-Kaye         let component = Component::new(
934d4242001SAdam Bratschi-Kaye             &engine,
935d4242001SAdam Bratschi-Kaye             r#"
936d4242001SAdam Bratschi-Kaye                 (component
937d4242001SAdam Bratschi-Kaye                     (core module
938d4242001SAdam Bratschi-Kaye                         (memory 1)
939d4242001SAdam Bratschi-Kaye                         (data (i32.const 100) "abcd")
940d4242001SAdam Bratschi-Kaye                     )
941d4242001SAdam Bratschi-Kaye                 )
942d4242001SAdam Bratschi-Kaye             "#,
943d4242001SAdam Bratschi-Kaye         )
944d4242001SAdam Bratschi-Kaye         .unwrap();
945d4242001SAdam Bratschi-Kaye 
946d4242001SAdam Bratschi-Kaye         for (_, module) in component.inner.static_modules.iter() {
947d4242001SAdam Bratschi-Kaye             let init = &module.env_module().memory_initialization;
948d4242001SAdam Bratschi-Kaye             assert!(matches!(init, MemoryInitialization::Static { .. }));
949d4242001SAdam Bratschi-Kaye         }
950d4242001SAdam Bratschi-Kaye     }
9515566d520SChris Fallin 
9525566d520SChris Fallin     #[test]
9535566d520SChris Fallin     #[cfg_attr(miri, ignore)]
image_range_is_whole_image()9545566d520SChris Fallin     fn image_range_is_whole_image() {
9555566d520SChris Fallin         let wat = r#"
9565566d520SChris Fallin                 (component
9575566d520SChris Fallin                     (core module
9585566d520SChris Fallin                         (memory 1)
9595566d520SChris Fallin                         (data (i32.const 0) "1234")
9605566d520SChris Fallin                         (func (export "f") (param i32) (result i32)
9615566d520SChris Fallin                             local.get 0)))
9625566d520SChris Fallin             "#;
9635566d520SChris Fallin         let engine = Engine::default();
9645566d520SChris Fallin         let mut builder = CodeBuilder::new(&engine);
9655566d520SChris Fallin         builder.wasm_binary_or_text(wat.as_bytes(), None).unwrap();
9665566d520SChris Fallin         let bytes = builder.compile_component_serialized().unwrap();
9675566d520SChris Fallin 
9685566d520SChris Fallin         let comp = unsafe { Component::deserialize(&engine, &bytes).unwrap() };
9695566d520SChris Fallin         let image_range = comp.image_range();
9705566d520SChris Fallin         let len = image_range.end.addr() - image_range.start.addr();
9715566d520SChris Fallin         // Length may be strictly greater if it becomes page-aligned.
9725566d520SChris Fallin         assert!(len >= bytes.len());
9735566d520SChris Fallin     }
974d4242001SAdam Bratschi-Kaye }
975