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