1 use crate::component::matching::InstanceType;
2 use crate::component::types;
3 use crate::component::InstanceExportLookup;
4 use crate::prelude::*;
5 use crate::runtime::vm::component::ComponentRuntimeInfo;
6 #[cfg(feature = "std")]
7 use crate::runtime::vm::open_file_for_mmap;
8 use crate::runtime::vm::{
9     CompiledModuleId, VMArrayCallFunction, VMFuncRef, VMFunctionBody, VMWasmCallFunction,
10 };
11 use crate::{
12     code::CodeObject, code_memory::CodeMemory, type_registry::TypeCollection, Engine, Module,
13     ResourcesRequired,
14 };
15 use crate::{FuncType, ValType};
16 use alloc::sync::Arc;
17 use core::any::Any;
18 use core::ops::Range;
19 use core::ptr::NonNull;
20 #[cfg(feature = "std")]
21 use std::path::Path;
22 use wasmtime_environ::component::{
23     AllCallFunc, CompiledComponentInfo, ComponentArtifacts, ComponentTypes, Export, ExportIndex,
24     GlobalInitializer, InstantiateModule, NameMapNoIntern, StaticModuleIndex, TrampolineIndex,
25     TypeComponentIndex, TypeDef, VMComponentOffsets,
26 };
27 use wasmtime_environ::TypeTrace;
28 use wasmtime_environ::{FunctionLoc, HostPtr, ObjectKind, PrimaryMap};
29 
30 /// A compiled WebAssembly Component.
31 ///
32 /// This structure represents a compiled component that is ready to be
33 /// instantiated. This owns a region of virtual memory which contains executable
34 /// code compiled from a WebAssembly binary originally. This is the analog of
35 /// [`Module`](crate::Module) in the component embedding API.
36 ///
37 /// A [`Component`] can be turned into an
38 /// [`Instance`](crate::component::Instance) through a
39 /// [`Linker`](crate::component::Linker). [`Component`]s are safe to share
40 /// across threads. The compilation model of a component is the same as that of
41 /// [a module](crate::Module) which is to say:
42 ///
43 /// * Compilation happens synchronously during [`Component::new`].
44 /// * The result of compilation can be saved into storage with
45 ///   [`Component::serialize`].
46 /// * A previously compiled artifact can be parsed with
47 ///   [`Component::deserialize`].
48 /// * No compilation happens at runtime for a component — everything is done
49 ///   by the time [`Component::new`] returns.
50 ///
51 /// ## Components and `Clone`
52 ///
53 /// Using `clone` on a `Component` is a cheap operation. It will not create an
54 /// entirely new component, but rather just a new reference to the existing
55 /// component. In other words it's a shallow copy, not a deep copy.
56 ///
57 /// ## Examples
58 ///
59 /// For example usage see the documentation of [`Module`](crate::Module) as
60 /// [`Component`] has the same high-level API.
61 #[derive(Clone)]
62 pub struct Component {
63     inner: Arc<ComponentInner>,
64 }
65 
66 struct ComponentInner {
67     /// Unique id for this component within this process.
68     ///
69     /// Note that this is repurposing ids for modules intentionally as there
70     /// shouldn't be an issue overlapping them.
71     id: CompiledModuleId,
72 
73     /// The engine that this component belongs to.
74     engine: Engine,
75 
76     /// Component type index
77     ty: TypeComponentIndex,
78 
79     /// Core wasm modules that the component defined internally, indexed by the
80     /// compile-time-assigned `ModuleUpvarIndex`.
81     static_modules: PrimaryMap<StaticModuleIndex, Module>,
82 
83     /// Code-related information such as the compiled artifact, type
84     /// information, etc.
85     ///
86     /// Note that the `Arc` here is used to share this allocation with internal
87     /// modules.
88     code: Arc<CodeObject>,
89 
90     /// Metadata produced during compilation.
91     info: CompiledComponentInfo,
92 
93     /// A cached handle to the `wasmtime::FuncType` for the canonical ABI's
94     /// `realloc`, to avoid the need to look up types in the registry and take
95     /// locks when calling `realloc` via `TypedFunc::call_raw`.
96     realloc_func_type: Arc<dyn Any + Send + Sync>,
97 }
98 
99 pub(crate) struct AllCallFuncPointers {
100     pub wasm_call: NonNull<VMWasmCallFunction>,
101     pub array_call: NonNull<VMArrayCallFunction>,
102 }
103 
104 impl Component {
105     /// Compiles a new WebAssembly component from the in-memory list of bytes
106     /// provided.
107     ///
108     /// The `bytes` provided can either be the binary or text format of a
109     /// [WebAssembly component]. Note that the text format requires the `wat`
110     /// feature of this crate to be enabled. This API does not support
111     /// streaming compilation.
112     ///
113     /// This function will synchronously validate the entire component,
114     /// including all core modules, and then compile all components, modules,
115     /// etc., found within the provided bytes.
116     ///
117     /// [WebAssembly component]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Binary.md
118     ///
119     /// # Errors
120     ///
121     /// This function may fail and return an error. Errors may include
122     /// situations such as:
123     ///
124     /// * The binary provided could not be decoded because it's not a valid
125     ///   WebAssembly binary
126     /// * The WebAssembly binary may not validate (e.g. contains type errors)
127     /// * Implementation-specific limits were exceeded with a valid binary (for
128     ///   example too many locals)
129     /// * The wasm binary may use features that are not enabled in the
130     ///   configuration of `engine`
131     /// * If the `wat` feature is enabled and the input is text, then it may be
132     ///   rejected if it fails to parse.
133     ///
134     /// The error returned should contain full information about why compilation
135     /// failed.
136     ///
137     /// # Examples
138     ///
139     /// The `new` function can be invoked with a in-memory array of bytes:
140     ///
141     /// ```no_run
142     /// # use wasmtime::*;
143     /// # use wasmtime::component::Component;
144     /// # fn main() -> anyhow::Result<()> {
145     /// # let engine = Engine::default();
146     /// # let wasm_bytes: Vec<u8> = Vec::new();
147     /// let component = Component::new(&engine, &wasm_bytes)?;
148     /// # Ok(())
149     /// # }
150     /// ```
151     ///
152     /// Or you can also pass in a string to be parsed as the wasm text
153     /// format:
154     ///
155     /// ```
156     /// # use wasmtime::*;
157     /// # use wasmtime::component::Component;
158     /// # fn main() -> anyhow::Result<()> {
159     /// # let engine = Engine::default();
160     /// let component = Component::new(&engine, "(component (core module))")?;
161     /// # Ok(())
162     /// # }
163     #[cfg(any(feature = "cranelift", feature = "winch"))]
164     pub fn new(engine: &Engine, bytes: impl AsRef<[u8]>) -> Result<Component> {
165         crate::CodeBuilder::new(engine)
166             .wasm_binary_or_text(bytes.as_ref(), None)?
167             .compile_component()
168     }
169 
170     /// Compiles a new WebAssembly component from a wasm file on disk pointed
171     /// to by `file`.
172     ///
173     /// This is a convenience function for reading the contents of `file` on
174     /// disk and then calling [`Component::new`].
175     #[cfg(all(feature = "std", any(feature = "cranelift", feature = "winch")))]
176     pub fn from_file(engine: &Engine, file: impl AsRef<Path>) -> Result<Component> {
177         crate::CodeBuilder::new(engine)
178             .wasm_binary_or_text_file(file.as_ref())?
179             .compile_component()
180     }
181 
182     /// Compiles a new WebAssembly component from the in-memory wasm image
183     /// provided.
184     ///
185     /// This function is the same as [`Component::new`] except that it does not
186     /// accept the text format of WebAssembly. Even if the `wat` feature
187     /// is enabled an error will be returned here if `binary` is the text
188     /// format.
189     ///
190     /// For more information on semantics and errors see [`Component::new`].
191     #[cfg(any(feature = "cranelift", feature = "winch"))]
192     pub fn from_binary(engine: &Engine, binary: &[u8]) -> Result<Component> {
193         crate::CodeBuilder::new(engine)
194             .wasm_binary(binary, None)?
195             .compile_component()
196     }
197 
198     /// Same as [`Module::deserialize`], but for components.
199     ///
200     /// Note that the bytes referenced here must contain contents previously
201     /// produced by [`Engine::precompile_component`] or
202     /// [`Component::serialize`].
203     ///
204     /// For more information see the [`Module::deserialize`] method.
205     ///
206     /// # Unsafety
207     ///
208     /// The unsafety of this method is the same as that of the
209     /// [`Module::deserialize`] method.
210     ///
211     /// [`Module::deserialize`]: crate::Module::deserialize
212     pub unsafe fn deserialize(engine: &Engine, bytes: impl AsRef<[u8]>) -> Result<Component> {
213         let code = engine.load_code_bytes(bytes.as_ref(), ObjectKind::Component)?;
214         Component::from_parts(engine, code, None)
215     }
216 
217     /// Same as [`Module::deserialize_file`], but for components.
218     ///
219     /// Note that the file referenced here must contain contents previously
220     /// produced by [`Engine::precompile_component`] or
221     /// [`Component::serialize`].
222     ///
223     /// For more information see the [`Module::deserialize_file`] method.
224     ///
225     /// # Unsafety
226     ///
227     /// The unsafety of this method is the same as that of the
228     /// [`Module::deserialize_file`] method.
229     ///
230     /// [`Module::deserialize_file`]: crate::Module::deserialize_file
231     #[cfg(feature = "std")]
232     pub unsafe fn deserialize_file(engine: &Engine, path: impl AsRef<Path>) -> Result<Component> {
233         let file = open_file_for_mmap(path.as_ref())?;
234         let code = engine
235             .load_code_file(file, ObjectKind::Component)
236             .with_context(|| format!("failed to load code for: {}", path.as_ref().display()))?;
237         Component::from_parts(engine, code, None)
238     }
239 
240     /// Returns the type of this component as a [`types::Component`].
241     ///
242     /// This method enables runtime introspection of the type of a component
243     /// before instantiation, if necessary.
244     ///
245     /// ## Component types and Resources
246     ///
247     /// An important point to note here is that the precise type of imports and
248     /// exports of a component change when it is instantiated with respect to
249     /// resources. For example a [`Component`] represents an un-instantiated
250     /// component meaning that its imported resources are represented as abstract
251     /// resource types. These abstract types are not equal to any other
252     /// component's types.
253     ///
254     /// For example:
255     ///
256     /// ```
257     /// # use wasmtime::Engine;
258     /// # use wasmtime::component::Component;
259     /// # use wasmtime::component::types::ComponentItem;
260     /// # fn main() -> wasmtime::Result<()> {
261     /// # let engine = Engine::default();
262     /// let a = Component::new(&engine, r#"
263     ///     (component (import "x" (type (sub resource))))
264     /// "#)?;
265     /// let b = Component::new(&engine, r#"
266     ///     (component (import "x" (type (sub resource))))
267     /// "#)?;
268     ///
269     /// let (_, a_ty) = a.component_type().imports(&engine).next().unwrap();
270     /// let (_, b_ty) = b.component_type().imports(&engine).next().unwrap();
271     ///
272     /// let a_ty = match a_ty {
273     ///     ComponentItem::Resource(ty) => ty,
274     ///     _ => unreachable!(),
275     /// };
276     /// let b_ty = match b_ty {
277     ///     ComponentItem::Resource(ty) => ty,
278     ///     _ => unreachable!(),
279     /// };
280     /// assert!(a_ty != b_ty);
281     /// # Ok(())
282     /// # }
283     /// ```
284     ///
285     /// Additionally, however, these abstract types are "substituted" during
286     /// instantiation meaning that a component type will appear to have changed
287     /// once it is instantiated.
288     ///
289     /// ```
290     /// # use wasmtime::{Engine, Store};
291     /// # use wasmtime::component::{Component, Linker, ResourceType};
292     /// # use wasmtime::component::types::ComponentItem;
293     /// # fn main() -> wasmtime::Result<()> {
294     /// # let engine = Engine::default();
295     /// // Here this component imports a resource and then exports it as-is
296     /// // which means that the export is equal to the import.
297     /// let a = Component::new(&engine, r#"
298     ///     (component
299     ///         (import "x" (type $x (sub resource)))
300     ///         (export "x" (type $x))
301     ///     )
302     /// "#)?;
303     ///
304     /// let (_, import) = a.component_type().imports(&engine).next().unwrap();
305     /// let (_, export) = a.component_type().exports(&engine).next().unwrap();
306     ///
307     /// let import = match import {
308     ///     ComponentItem::Resource(ty) => ty,
309     ///     _ => unreachable!(),
310     /// };
311     /// let export = match export {
312     ///     ComponentItem::Resource(ty) => ty,
313     ///     _ => unreachable!(),
314     /// };
315     /// assert_eq!(import, export);
316     ///
317     /// // However after instantiation the resource type "changes"
318     /// let mut store = Store::new(&engine, ());
319     /// let mut linker = Linker::new(&engine);
320     /// linker.root().resource("x", ResourceType::host::<()>(), |_, _| Ok(()))?;
321     /// let instance = linker.instantiate(&mut store, &a)?;
322     /// let instance_ty = instance.get_resource(&mut store, "x").unwrap();
323     ///
324     /// // Here `instance_ty` is not the same as either `import` or `export`,
325     /// // but it is equal to what we provided as an import.
326     /// assert!(instance_ty != import);
327     /// assert!(instance_ty != export);
328     /// assert!(instance_ty == ResourceType::host::<()>());
329     /// # Ok(())
330     /// # }
331     /// ```
332     ///
333     /// Finally, each instantiation of an exported resource from a component is
334     /// considered "fresh" for all instantiations meaning that different
335     /// instantiations will have different exported resource types:
336     ///
337     /// ```
338     /// # use wasmtime::{Engine, Store};
339     /// # use wasmtime::component::{Component, Linker};
340     /// # fn main() -> wasmtime::Result<()> {
341     /// # let engine = Engine::default();
342     /// let a = Component::new(&engine, r#"
343     ///     (component
344     ///         (type $x (resource (rep i32)))
345     ///         (export "x" (type $x))
346     ///     )
347     /// "#)?;
348     ///
349     /// let mut store = Store::new(&engine, ());
350     /// let linker = Linker::new(&engine);
351     /// let instance1 = linker.instantiate(&mut store, &a)?;
352     /// let instance2 = linker.instantiate(&mut store, &a)?;
353     ///
354     /// let x1 = instance1.get_resource(&mut store, "x").unwrap();
355     /// let x2 = instance2.get_resource(&mut store, "x").unwrap();
356     ///
357     /// // Despite these two resources being the same export of the same
358     /// // component they come from two different instances meaning that their
359     /// // types will be unique.
360     /// assert!(x1 != x2);
361     /// # Ok(())
362     /// # }
363     /// ```
364     pub fn component_type(&self) -> types::Component {
365         self.with_uninstantiated_instance_type(|ty| types::Component::from(self.inner.ty, ty))
366     }
367 
368     fn with_uninstantiated_instance_type<R>(&self, f: impl FnOnce(&InstanceType<'_>) -> R) -> R {
369         let resources = Arc::new(PrimaryMap::new());
370         f(&InstanceType {
371             types: self.types(),
372             resources: &resources,
373         })
374     }
375 
376     /// Final assembly step for a component from its in-memory representation.
377     ///
378     /// If the `artifacts` are specified as `None` here then they will be
379     /// deserialized from `code_memory`.
380     pub(crate) fn from_parts(
381         engine: &Engine,
382         code_memory: Arc<CodeMemory>,
383         artifacts: Option<ComponentArtifacts>,
384     ) -> Result<Component> {
385         let ComponentArtifacts {
386             ty,
387             info,
388             mut types,
389             mut static_modules,
390         } = match artifacts {
391             Some(artifacts) => artifacts,
392             None => postcard::from_bytes(code_memory.wasmtime_info())?,
393         };
394 
395         // Validate that the component can be used with the current instance
396         // allocator.
397         engine.allocator().validate_component(
398             &info.component,
399             &VMComponentOffsets::new(HostPtr, &info.component),
400             &|module_index| &static_modules[module_index].module,
401         )?;
402 
403         // Create a signature registration with the `Engine` for all trampolines
404         // and core wasm types found within this component, both for the
405         // component and for all included core wasm modules.
406         let signatures = engine.register_and_canonicalize_types(
407             types.module_types_mut(),
408             static_modules.iter_mut().map(|(_, m)| &mut m.module),
409         );
410         types.canonicalize_for_runtime_usage(&mut |idx| signatures.shared_type(idx).unwrap());
411 
412         // Assemble the `CodeObject` artifact which is shared by all core wasm
413         // modules as well as the final component.
414         let types = Arc::new(types);
415         let code = Arc::new(CodeObject::new(code_memory, signatures, types.into()));
416 
417         // Convert all information about static core wasm modules into actual
418         // `Module` instances by converting each `CompiledModuleInfo`, the
419         // `types` type information, and the code memory to a runtime object.
420         let static_modules = static_modules
421             .into_iter()
422             .map(|(_, info)| Module::from_parts_raw(engine, code.clone(), info, false))
423             .collect::<Result<_>>()?;
424 
425         let realloc_func_type = Arc::new(FuncType::new(
426             engine,
427             [ValType::I32, ValType::I32, ValType::I32, ValType::I32],
428             [ValType::I32],
429         )) as _;
430 
431         Ok(Component {
432             inner: Arc::new(ComponentInner {
433                 id: CompiledModuleId::new(),
434                 engine: engine.clone(),
435                 ty,
436                 static_modules,
437                 code,
438                 info,
439                 realloc_func_type,
440             }),
441         })
442     }
443 
444     pub(crate) fn ty(&self) -> TypeComponentIndex {
445         self.inner.ty
446     }
447 
448     pub(crate) fn env_component(&self) -> &wasmtime_environ::component::Component {
449         &self.inner.info.component
450     }
451 
452     pub(crate) fn static_module(&self, idx: StaticModuleIndex) -> &Module {
453         &self.inner.static_modules[idx]
454     }
455 
456     #[inline]
457     pub(crate) fn types(&self) -> &Arc<ComponentTypes> {
458         self.inner.component_types()
459     }
460 
461     pub(crate) fn signatures(&self) -> &TypeCollection {
462         self.inner.code.signatures()
463     }
464 
465     pub(crate) fn text(&self) -> &[u8] {
466         self.inner.code.code_memory().text()
467     }
468 
469     pub(crate) fn trampoline_ptrs(&self, index: TrampolineIndex) -> AllCallFuncPointers {
470         let AllCallFunc {
471             wasm_call,
472             array_call,
473         } = &self.inner.info.trampolines[index];
474         AllCallFuncPointers {
475             wasm_call: self.func(wasm_call).cast(),
476             array_call: self.func(array_call).cast(),
477         }
478     }
479 
480     fn func(&self, loc: &FunctionLoc) -> NonNull<VMFunctionBody> {
481         let text = self.text();
482         let trampoline = &text[loc.start as usize..][..loc.length as usize];
483         NonNull::new(trampoline.as_ptr() as *mut VMFunctionBody).unwrap()
484     }
485 
486     pub(crate) fn code_object(&self) -> &Arc<CodeObject> {
487         &self.inner.code
488     }
489 
490     /// Same as [`Module::serialize`], except for a component.
491     ///
492     /// Note that the artifact produced here must be passed to
493     /// [`Component::deserialize`] and is not compatible for use with
494     /// [`Module`].
495     ///
496     /// [`Module::serialize`]: crate::Module::serialize
497     /// [`Module`]: crate::Module
498     pub fn serialize(&self) -> Result<Vec<u8>> {
499         Ok(self.code_object().code_memory().mmap().to_vec())
500     }
501 
502     pub(crate) fn runtime_info(&self) -> Arc<dyn ComponentRuntimeInfo> {
503         self.inner.clone()
504     }
505 
506     /// Creates a new `VMFuncRef` with all fields filled out for the destructor
507     /// specified.
508     ///
509     /// The `dtor`'s own `VMFuncRef` won't have `wasm_call` filled out but this
510     /// component may have `resource_drop_wasm_to_native_trampoline` filled out
511     /// if necessary in which case it's filled in here.
512     pub(crate) fn resource_drop_func_ref(&self, dtor: &crate::func::HostFunc) -> VMFuncRef {
513         // Host functions never have their `wasm_call` filled in at this time.
514         assert!(dtor.func_ref().wasm_call.is_none());
515 
516         // Note that if `resource_drop_wasm_to_native_trampoline` is not present
517         // then this can't be called by the component, so it's ok to leave it
518         // blank.
519         let wasm_call = self
520             .inner
521             .info
522             .resource_drop_wasm_to_array_trampoline
523             .as_ref()
524             .map(|i| self.func(i).cast().into());
525         VMFuncRef {
526             wasm_call,
527             ..*dtor.func_ref()
528         }
529     }
530 
531     /// Returns a summary of the resources required to instantiate this
532     /// [`Component`][crate::component::Component].
533     ///
534     /// Note that when a component imports and instantiates another component or
535     /// core module, we cannot determine ahead of time how many resources
536     /// instantiating this component will require, and therefore this method
537     /// will return `None` in these scenarios.
538     ///
539     /// Potential uses of the returned information:
540     ///
541     /// * Determining whether your pooling allocator configuration supports
542     ///   instantiating this component.
543     ///
544     /// * Deciding how many of which `Component` you want to instantiate within
545     ///   a fixed amount of resources, e.g. determining whether to create 5
546     ///   instances of component X or 10 instances of component Y.
547     ///
548     /// # Example
549     ///
550     /// ```
551     /// # fn main() -> wasmtime::Result<()> {
552     /// use wasmtime::{Config, Engine, component::Component};
553     ///
554     /// let mut config = Config::new();
555     /// config.wasm_multi_memory(true);
556     /// config.wasm_component_model(true);
557     /// let engine = Engine::new(&config)?;
558     ///
559     /// let component = Component::new(&engine, &r#"
560     ///     (component
561     ///         ;; Define a core module that uses two memories.
562     ///         (core module $m
563     ///             (memory 1)
564     ///             (memory 6)
565     ///         )
566     ///
567     ///         ;; Instantiate that core module three times.
568     ///         (core instance $i1 (instantiate (module $m)))
569     ///         (core instance $i2 (instantiate (module $m)))
570     ///         (core instance $i3 (instantiate (module $m)))
571     ///     )
572     /// "#)?;
573     ///
574     /// let resources = component.resources_required()
575     ///     .expect("this component does not import any core modules or instances");
576     ///
577     /// // Instantiating the component will require allocating two memories per
578     /// // core instance, and there are three instances, so six total memories.
579     /// assert_eq!(resources.num_memories, 6);
580     /// assert_eq!(resources.max_initial_memory_size, Some(6));
581     ///
582     /// // The component doesn't need any tables.
583     /// assert_eq!(resources.num_tables, 0);
584     /// assert_eq!(resources.max_initial_table_size, None);
585     /// # Ok(()) }
586     /// ```
587     pub fn resources_required(&self) -> Option<ResourcesRequired> {
588         let mut resources = ResourcesRequired {
589             num_memories: 0,
590             max_initial_memory_size: None,
591             num_tables: 0,
592             max_initial_table_size: None,
593         };
594         for init in &self.env_component().initializers {
595             match init {
596                 GlobalInitializer::InstantiateModule(inst) => match inst {
597                     InstantiateModule::Static(index, _) => {
598                         let module = self.static_module(*index);
599                         resources.add(&module.resources_required());
600                     }
601                     InstantiateModule::Import(_, _) => {
602                         // We can't statically determine the resources required
603                         // to instantiate this component.
604                         return None;
605                     }
606                 },
607                 GlobalInitializer::LowerImport { .. }
608                 | GlobalInitializer::ExtractMemory(_)
609                 | GlobalInitializer::ExtractRealloc(_)
610                 | GlobalInitializer::ExtractCallback(_)
611                 | GlobalInitializer::ExtractPostReturn(_)
612                 | GlobalInitializer::Resource(_) => {}
613             }
614         }
615         Some(resources)
616     }
617 
618     /// Returns the range, in the host's address space, that this module's
619     /// compiled code resides at.
620     ///
621     /// For more information see
622     /// [`Module::image_range`](crate::Module::image_range).
623     pub fn image_range(&self) -> Range<*const u8> {
624         self.inner.code.code_memory().mmap().image_range()
625     }
626 
627     /// Force initialization of copy-on-write images to happen here-and-now
628     /// instead of when they're requested during first instantiation.
629     ///
630     /// When [copy-on-write memory
631     /// initialization](crate::Config::memory_init_cow) is enabled then Wasmtime
632     /// will lazily create the initialization image for a component. This method
633     /// can be used to explicitly dictate when this initialization happens.
634     ///
635     /// Note that this largely only matters on Linux when memfd is used.
636     /// Otherwise the copy-on-write image typically comes from disk and in that
637     /// situation the creation of the image is trivial as the image is always
638     /// sourced from disk. On Linux, though, when memfd is used a memfd is
639     /// created and the initialization image is written to it.
640     ///
641     /// Also note that this method is not required to be called, it's available
642     /// as a performance optimization if required but is otherwise handled
643     /// automatically.
644     pub fn initialize_copy_on_write_image(&self) -> Result<()> {
645         for (_, module) in self.inner.static_modules.iter() {
646             module.initialize_copy_on_write_image()?;
647         }
648         Ok(())
649     }
650 
651     /// Looks up a specific export of this component by `name` optionally nested
652     /// within the `instance` provided.
653     ///
654     /// This method is primarily used to acquire a [`ComponentExportIndex`]
655     /// which can be used with [`Instance`](crate::component::Instance) when
656     /// looking up exports. Export lookup with [`ComponentExportIndex`] can
657     /// skip string lookups at runtime and instead use a more efficient
658     /// index-based lookup.
659     ///
660     /// This method takes a few arguments:
661     ///
662     /// * `engine` - the engine that was used to compile this component.
663     /// * `instance` - an optional "parent instance" for the export being looked
664     ///   up. If this is `None` then the export is looked up on the root of the
665     ///   component itself, and otherwise the export is looked up on the
666     ///   `instance` specified. Note that `instance` must have come from a
667     ///   previous invocation of this method.
668     /// * `name` - the name of the export that's being looked up.
669     ///
670     /// If the export is located then two values are returned: a
671     /// [`types::ComponentItem`] which enables introspection about the type of
672     /// the export and a [`ComponentExportIndex`]. The index returned notably
673     /// implements the [`InstanceExportLookup`] trait which enables using it
674     /// with [`Instance::get_func`](crate::component::Instance::get_func) for
675     /// example.
676     ///
677     /// # Examples
678     ///
679     /// ```
680     /// use wasmtime::{Engine, Store};
681     /// use wasmtime::component::{Component, Linker};
682     /// use wasmtime::component::types::ComponentItem;
683     ///
684     /// # fn main() -> wasmtime::Result<()> {
685     /// let engine = Engine::default();
686     /// let component = Component::new(
687     ///     &engine,
688     ///     r#"
689     ///         (component
690     ///             (core module $m
691     ///                 (func (export "f"))
692     ///             )
693     ///             (core instance $i (instantiate $m))
694     ///             (func (export "f")
695     ///                 (canon lift (core func $i "f")))
696     ///         )
697     ///     "#,
698     /// )?;
699     ///
700     /// // Perform a lookup of the function "f" before instantiaton.
701     /// let (ty, export) = component.export_index(None, "f").unwrap();
702     /// assert!(matches!(ty, ComponentItem::ComponentFunc(_)));
703     ///
704     /// // After instantiation use `export` to lookup the function in question
705     /// // which notably does not do a string lookup at runtime.
706     /// let mut store = Store::new(&engine, ());
707     /// let instance = Linker::new(&engine).instantiate(&mut store, &component)?;
708     /// let func = instance.get_typed_func::<(), ()>(&mut store, &export)?;
709     /// // ...
710     /// # Ok(())
711     /// # }
712     /// ```
713     pub fn export_index(
714         &self,
715         instance: Option<&ComponentExportIndex>,
716         name: &str,
717     ) -> Option<(types::ComponentItem, ComponentExportIndex)> {
718         let info = self.env_component();
719         let index = self.lookup_export_index(instance, name)?;
720         let ty = match info.export_items[index] {
721             Export::Instance { ty, .. } => TypeDef::ComponentInstance(ty),
722             Export::LiftedFunction { ty, .. } => TypeDef::ComponentFunc(ty),
723             Export::ModuleStatic { ty, .. } | Export::ModuleImport { ty, .. } => {
724                 TypeDef::Module(ty)
725             }
726             Export::Type(ty) => ty,
727         };
728         let item = self.with_uninstantiated_instance_type(|instance| {
729             types::ComponentItem::from(&self.inner.engine, &ty, instance)
730         });
731         Some((
732             item,
733             ComponentExportIndex {
734                 id: self.inner.id,
735                 index,
736             },
737         ))
738     }
739 
740     pub(crate) fn lookup_export_index(
741         &self,
742         instance: Option<&ComponentExportIndex>,
743         name: &str,
744     ) -> Option<ExportIndex> {
745         let info = self.env_component();
746         let exports = match instance {
747             Some(idx) => {
748                 if idx.id != self.inner.id {
749                     return None;
750                 }
751                 match &info.export_items[idx.index] {
752                     Export::Instance { exports, .. } => exports,
753                     _ => return None,
754                 }
755             }
756             None => &info.exports,
757         };
758         exports.get(name, &NameMapNoIntern).copied()
759     }
760 
761     pub(crate) fn id(&self) -> CompiledModuleId {
762         self.inner.id
763     }
764 
765     /// Returns the [`Engine`] that this [`Component`] was compiled by.
766     pub fn engine(&self) -> &Engine {
767         &self.inner.engine
768     }
769 }
770 
771 /// A value which represents a known export of a component.
772 ///
773 /// This is the return value of [`Component::export_index`] and implements the
774 /// [`InstanceExportLookup`] trait to work with lookups like
775 /// [`Instance::get_func`](crate::component::Instance::get_func).
776 #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
777 pub struct ComponentExportIndex {
778     pub(crate) id: CompiledModuleId,
779     pub(crate) index: ExportIndex,
780 }
781 
782 impl InstanceExportLookup for ComponentExportIndex {
783     fn lookup(&self, component: &Component) -> Option<ExportIndex> {
784         if component.inner.id == self.id {
785             Some(self.index)
786         } else {
787             None
788         }
789     }
790 }
791 
792 impl ComponentRuntimeInfo for ComponentInner {
793     fn component(&self) -> &wasmtime_environ::component::Component {
794         &self.info.component
795     }
796 
797     fn component_types(&self) -> &Arc<ComponentTypes> {
798         match self.code.types() {
799             crate::code::Types::Component(types) => types,
800             // The only creator of a `Component` is itself which uses the other
801             // variant, so this shouldn't be possible.
802             crate::code::Types::Module(_) => unreachable!(),
803         }
804     }
805 
806     fn realloc_func_type(&self) -> &Arc<dyn Any + Send + Sync> {
807         &self.realloc_func_type
808     }
809 }
810 
811 #[cfg(test)]
812 mod tests {
813     use crate::component::Component;
814     use crate::{Config, Engine};
815     use wasmtime_environ::MemoryInitialization;
816 
817     #[test]
818     fn cow_on_by_default() {
819         let mut config = Config::new();
820         config.wasm_component_model(true);
821         let engine = Engine::new(&config).unwrap();
822         let component = Component::new(
823             &engine,
824             r#"
825                 (component
826                     (core module
827                         (memory 1)
828                         (data (i32.const 100) "abcd")
829                     )
830                 )
831             "#,
832         )
833         .unwrap();
834 
835         for (_, module) in component.inner.static_modules.iter() {
836             let init = &module.env_module().memory_initialization;
837             assert!(matches!(init, MemoryInitialization::Static { .. }));
838         }
839     }
840 }
841