1 use crate::linker::{Definition, DefinitionType};
2 use crate::prelude::*;
3 use crate::runtime::vm::{
4     self, Imports, ModuleRuntimeInfo, VMFuncRef, VMFunctionImport, VMGlobalImport, VMMemoryImport,
5     VMTableImport, VMTagImport,
6 };
7 use crate::store::{AllocateInstanceKind, InstanceId, StoreInstanceId, StoreOpaque};
8 use crate::types::matching;
9 use crate::{
10     AsContextMut, Engine, Export, Extern, Func, Global, Memory, Module, ModuleExport, SharedMemory,
11     StoreContext, StoreContextMut, Table, Tag, TypedFunc,
12 };
13 use alloc::sync::Arc;
14 use core::ptr::NonNull;
15 use wasmparser::WasmFeatures;
16 use wasmtime_environ::{
17     EntityIndex, EntityType, FuncIndex, GlobalIndex, MemoryIndex, PrimaryMap, TableIndex, TagIndex,
18     TypeTrace,
19 };
20 
21 /// An instantiated WebAssembly module.
22 ///
23 /// This type represents the instantiation of a [`Module`]. Once instantiated
24 /// you can access the [`exports`](Instance::exports) which are of type
25 /// [`Extern`] and provide the ability to call functions, set globals, read
26 /// memory, etc. When interacting with any wasm code you'll want to make an
27 /// [`Instance`] to call any code or execute anything.
28 ///
29 /// Instances are owned by a [`Store`](crate::Store) which is passed in at
30 /// creation time. It's recommended to create instances with
31 /// [`Linker::instantiate`](crate::Linker::instantiate) or similar
32 /// [`Linker`](crate::Linker) methods, but a more low-level constructor is also
33 /// available as [`Instance::new`].
34 #[derive(Copy, Clone, Debug)]
35 #[repr(C)]
36 pub struct Instance {
37     id: StoreInstanceId,
38 }
39 
40 // Double-check that the C representation in `instance.h` matches our in-Rust
41 // representation here in terms of size/alignment/etc.
42 const _: () = {
43     #[repr(C)]
44     struct C(u64, usize);
45     assert!(core::mem::size_of::<C>() == core::mem::size_of::<Instance>());
46     assert!(core::mem::align_of::<C>() == core::mem::align_of::<Instance>());
47     assert!(core::mem::offset_of!(Instance, id) == 0);
48 };
49 
50 impl Instance {
51     /// Creates a new [`Instance`] from the previously compiled [`Module`] and
52     /// list of `imports` specified.
53     ///
54     /// This method instantiates the `module` provided with the `imports`,
55     /// following the procedure in the [core specification][inst] to
56     /// instantiate. Instantiation can fail for a number of reasons (many
57     /// specified below), but if successful the `start` function will be
58     /// automatically run (if specified in the `module`) and then the
59     /// [`Instance`] will be returned.
60     ///
61     /// Per the WebAssembly spec, instantiation includes running the module's
62     /// start function, if it has one (not to be confused with the `_start`
63     /// function, which is not run).
64     ///
65     /// Note that this is a low-level function that just performs an
66     /// instantiation. See the [`Linker`](crate::Linker) struct for an API which
67     /// provides a convenient way to link imports and provides automatic Command
68     /// and Reactor behavior.
69     ///
70     /// ## Providing Imports
71     ///
72     /// The entries in the list of `imports` are intended to correspond 1:1
73     /// with the list of imports returned by [`Module::imports`]. Before
74     /// calling [`Instance::new`] you'll want to inspect the return value of
75     /// [`Module::imports`] and, for each import type, create an [`Extern`]
76     /// which corresponds to that type.  These [`Extern`] values are all then
77     /// collected into a list and passed to this function.
78     ///
79     /// Note that this function is intentionally relatively low level. For an
80     /// easier time passing imports by doing name-based resolution it's
81     /// recommended to instead use the [`Linker`](crate::Linker) type.
82     ///
83     /// ## Errors
84     ///
85     /// This function can fail for a number of reasons, including, but not
86     /// limited to:
87     ///
88     /// * The number of `imports` provided doesn't match the number of imports
89     ///   returned by the `module`'s [`Module::imports`] method.
90     /// * The type of any [`Extern`] doesn't match the corresponding
91     ///   [`ExternType`] entry that it maps to.
92     /// * The `start` function in the instance, if present, traps.
93     /// * Module/instance resource limits are exceeded.
94     ///
95     /// When instantiation fails it's recommended to inspect the return value to
96     /// see why it failed, or bubble it upwards. If you'd like to specifically
97     /// check for trap errors, you can use `error.downcast::<Trap>()`. For more
98     /// about error handling see the [`Trap`] documentation.
99     ///
100     /// [`Trap`]: crate::Trap
101     ///
102     /// # Panics
103     ///
104     /// This function will panic if called with a store associated with a
105     /// [`asynchronous config`](crate::Config::async_support). This function
106     /// will also panic if any [`Extern`] supplied is not owned by `store`.
107     ///
108     /// [inst]: https://webassembly.github.io/spec/core/exec/modules.html#exec-instantiation
109     /// [`ExternType`]: crate::ExternType
110     pub fn new(
111         mut store: impl AsContextMut,
112         module: &Module,
113         imports: &[Extern],
114     ) -> Result<Instance> {
115         let mut store = store.as_context_mut();
116         let imports = Instance::typecheck_externs(store.0, module, imports)?;
117         // Note that the unsafety here should be satisfied by the call to
118         // `typecheck_externs` above which satisfies the condition that all
119         // the imports are valid for this module.
120         unsafe { Instance::new_started(&mut store, module, imports.as_ref()) }
121     }
122 
123     /// Same as [`Instance::new`], except for usage in [asynchronous stores].
124     ///
125     /// For more details about this function see the documentation on
126     /// [`Instance::new`]. The only difference between these two methods is that
127     /// this one will asynchronously invoke the wasm start function in case it
128     /// calls any imported function which is an asynchronous host function (e.g.
129     /// created with [`Func::new_async`](crate::Func::new_async).
130     ///
131     /// # Panics
132     ///
133     /// This function will panic if called with a store associated with a
134     /// [`synchronous config`](crate::Config::new). This is only compatible with
135     /// stores associated with an [`asynchronous
136     /// config`](crate::Config::async_support).
137     ///
138     /// This function will also panic, like [`Instance::new`], if any [`Extern`]
139     /// specified does not belong to `store`.
140     #[cfg(feature = "async")]
141     pub async fn new_async(
142         mut store: impl AsContextMut<Data: Send>,
143         module: &Module,
144         imports: &[Extern],
145     ) -> Result<Instance> {
146         let mut store = store.as_context_mut();
147         let imports = Instance::typecheck_externs(store.0, module, imports)?;
148         // See `new` for notes on this unsafety
149         unsafe { Instance::new_started_async(&mut store, module, imports.as_ref()).await }
150     }
151 
152     fn typecheck_externs(
153         store: &mut StoreOpaque,
154         module: &Module,
155         imports: &[Extern],
156     ) -> Result<OwnedImports> {
157         for import in imports {
158             if !import.comes_from_same_store(store) {
159                 bail!("cross-`Store` instantiation is not currently supported");
160             }
161         }
162 
163         typecheck(module, imports, |cx, ty, item| {
164             let item = DefinitionType::from(store, item);
165             cx.definition(ty, &item)
166         })?;
167 
168         // When pushing functions into `OwnedImports` it's required that their
169         // `wasm_call` fields are all filled out. This `module` is guaranteed
170         // to have any trampolines necessary for functions so register the
171         // module with the store and then attempt to fill out any outstanding
172         // holes.
173         //
174         // Note that under normal operation this shouldn't do much as the list
175         // of funcs-with-holes should generally be empty. As a result the
176         // process of filling this out is not super optimized at this point.
177         store.modules_mut().register_module(module);
178         let (funcrefs, modules) = store.func_refs_and_modules();
179         funcrefs.fill(modules);
180 
181         let mut owned_imports = OwnedImports::new(module);
182         for import in imports {
183             owned_imports.push(import, store);
184         }
185         Ok(owned_imports)
186     }
187 
188     /// Internal function to create an instance and run the start function.
189     ///
190     /// This function's unsafety is the same as `Instance::new_raw`.
191     pub(crate) unsafe fn new_started<T>(
192         store: &mut StoreContextMut<'_, T>,
193         module: &Module,
194         imports: Imports<'_>,
195     ) -> Result<Instance> {
196         assert!(
197             !store.0.async_support(),
198             "must use async instantiation when async support is enabled",
199         );
200 
201         // SAFETY: the safety contract of `new_started_impl` is the same as this
202         // function.
203         unsafe { Self::new_started_impl(store, module, imports) }
204     }
205 
206     /// Internal function to create an instance and run the start function.
207     ///
208     /// ONLY CALL THIS IF YOU HAVE ALREADY CHECKED FOR ASYNCNESS AND HANDLED
209     /// THE FIBER NONSENSE
210     pub(crate) unsafe fn new_started_impl<T>(
211         store: &mut StoreContextMut<'_, T>,
212         module: &Module,
213         imports: Imports<'_>,
214     ) -> Result<Instance> {
215         // SAFETY: the safety contract of `new_raw` is the same as this
216         // function.
217         let (instance, start) = unsafe { Instance::new_raw(store.0, module, imports)? };
218         if let Some(start) = start {
219             instance.start_raw(store, start)?;
220         }
221         Ok(instance)
222     }
223 
224     /// Internal function to create an instance and run the start function.
225     ///
226     /// This function's unsafety is the same as `Instance::new_raw`.
227     #[cfg(feature = "async")]
228     async unsafe fn new_started_async<T>(
229         store: &mut StoreContextMut<'_, T>,
230         module: &Module,
231         imports: Imports<'_>,
232     ) -> Result<Instance>
233     where
234         T: Send + 'static,
235     {
236         assert!(
237             store.0.async_support(),
238             "must use sync instantiation when async support is disabled",
239         );
240 
241         store
242             .on_fiber(|store| {
243                 // SAFETY: the unsafe contract of `new_started_impl` is the same
244                 // as this function.
245                 unsafe { Self::new_started_impl(store, module, imports) }
246             })
247             .await?
248     }
249 
250     /// Internal function to create an instance which doesn't have its `start`
251     /// function run yet.
252     ///
253     /// This is not intended to be exposed from Wasmtime, it's intended to
254     /// refactor out common code from `new_started` and `new_started_async`.
255     ///
256     /// Note that this step needs to be run on a fiber in async mode even
257     /// though it doesn't do any blocking work because an async resource
258     /// limiter may need to yield.
259     ///
260     /// # Unsafety
261     ///
262     /// This method is unsafe because it does not type-check the `imports`
263     /// provided. The `imports` provided must be suitable for the module
264     /// provided as well.
265     unsafe fn new_raw(
266         store: &mut StoreOpaque,
267         module: &Module,
268         imports: Imports<'_>,
269     ) -> Result<(Instance, Option<FuncIndex>)> {
270         if !Engine::same(store.engine(), module.engine()) {
271             bail!("cross-`Engine` instantiation is not currently supported");
272         }
273         store.bump_resource_counts(module)?;
274 
275         // Allocate the GC heap, if necessary.
276         if module.env_module().needs_gc_heap {
277             let _ = store.gc_store_mut()?;
278         }
279 
280         let compiled_module = module.compiled_module();
281 
282         // Register the module just before instantiation to ensure we keep the module
283         // properly referenced while in use by the store.
284         let module_id = store.modules_mut().register_module(module);
285 
286         // The first thing we do is issue an instance allocation request
287         // to the instance allocator. This, on success, will give us an
288         // instance handle.
289         //
290         // SAFETY: this module, by construction, was already validated within
291         // the store.
292         let id = unsafe {
293             store.allocate_instance(
294                 AllocateInstanceKind::Module(module_id),
295                 &ModuleRuntimeInfo::Module(module.clone()),
296                 imports,
297             )?
298         };
299 
300         // Additionally, before we start doing fallible instantiation, we
301         // do one more step which is to insert an `InstanceData`
302         // corresponding to this instance. This `InstanceData` can be used
303         // via `Caller::get_export` if our instance's state "leaks" into
304         // other instances, even if we don't return successfully from this
305         // function.
306         //
307         // We don't actually load all exports from the instance at this
308         // time, instead preferring to lazily load them as they're demanded.
309         // For module/instance exports, though, those aren't actually
310         // stored in the instance handle so we need to immediately handle
311         // those here.
312         let instance = Instance::from_wasmtime(id, store);
313 
314         // Now that we've recorded all information we need to about this
315         // instance within a `Store` we can start performing fallible
316         // initialization. Note that we still defer the `start` function to
317         // later since that may need to run asynchronously.
318         //
319         // If this returns an error (or if the start function traps) then
320         // any other initialization which may have succeeded which placed
321         // items from this instance into other instances should be ok when
322         // those items are loaded and run we'll have all the metadata to
323         // look at them.
324         let bulk_memory = store
325             .engine()
326             .features()
327             .contains(WasmFeatures::BULK_MEMORY);
328 
329         vm::initialize_instance(store, id, compiled_module.module(), bulk_memory)?;
330 
331         Ok((instance, compiled_module.module().start_func))
332     }
333 
334     pub(crate) fn from_wasmtime(id: InstanceId, store: &mut StoreOpaque) -> Instance {
335         Instance {
336             id: StoreInstanceId::new(store.id(), id),
337         }
338     }
339 
340     fn start_raw<T>(&self, store: &mut StoreContextMut<'_, T>, start: FuncIndex) -> Result<()> {
341         // If a start function is present, invoke it. Make sure we use all the
342         // trap-handling configuration in `store` as well.
343         let store_id = store.0.id();
344         let mut instance = self.id.get_mut(store.0);
345         // SAFETY: the `store_id` is the id of the store that owns this
346         // instance and any function stored within the instance.
347         let f = unsafe { instance.as_mut().get_exported_func(store_id, start) };
348         let caller_vmctx = instance.vmctx();
349         unsafe {
350             let funcref = f.vm_func_ref(store.0);
351             super::func::invoke_wasm_and_catch_traps(store, |_default_caller, vm| {
352                 VMFuncRef::array_call(funcref, vm, caller_vmctx, NonNull::from(&mut []))
353             })?;
354         }
355         Ok(())
356     }
357 
358     /// Get this instance's module.
359     pub fn module<'a, T: 'static>(&self, store: impl Into<StoreContext<'a, T>>) -> &'a Module {
360         self._module(store.into().0)
361     }
362 
363     fn _module<'a>(&self, store: &'a StoreOpaque) -> &'a Module {
364         store.module_for_instance(self.id).unwrap()
365     }
366 
367     /// Returns the list of exported items from this [`Instance`].
368     ///
369     /// # Panics
370     ///
371     /// Panics if `store` does not own this instance.
372     pub fn exports<'a, T: 'static>(
373         &'a self,
374         store: impl Into<StoreContextMut<'a, T>>,
375     ) -> impl ExactSizeIterator<Item = Export<'a>> + 'a {
376         self._exports(store.into().0)
377     }
378 
379     fn _exports<'a>(
380         &'a self,
381         store: &'a mut StoreOpaque,
382     ) -> impl ExactSizeIterator<Item = Export<'a>> + 'a {
383         let module = store[self.id].env_module().clone();
384         let mut items = Vec::new();
385         for (_name, entity) in module.exports.iter() {
386             items.push(self._get_export(store, *entity));
387         }
388         store[self.id]
389             .env_module()
390             .exports
391             .iter()
392             .zip(items)
393             .map(|((name, _), item)| Export::new(name, item))
394     }
395 
396     /// Looks up an exported [`Extern`] value by name.
397     ///
398     /// This method will search the module for an export named `name` and return
399     /// the value, if found.
400     ///
401     /// Returns `None` if there was no export named `name`.
402     ///
403     /// # Panics
404     ///
405     /// Panics if `store` does not own this instance.
406     ///
407     /// # Why does `get_export` take a mutable context?
408     ///
409     /// This method requires a mutable context because an instance's exports are
410     /// lazily populated, and we cache them as they are accessed. This makes
411     /// instantiating a module faster, but also means this method requires a
412     /// mutable context.
413     pub fn get_export(&self, mut store: impl AsContextMut, name: &str) -> Option<Extern> {
414         let store = store.as_context_mut().0;
415         let entity = *store[self.id].env_module().exports.get(name)?;
416         Some(self._get_export(store, entity))
417     }
418 
419     /// Looks up an exported [`Extern`] value by a [`ModuleExport`] value.
420     ///
421     /// This is similar to [`Instance::get_export`] but uses a [`ModuleExport`] value to avoid
422     /// string lookups where possible. [`ModuleExport`]s can be obtained by calling
423     /// [`Module::get_export_index`] on the [`Module`] that this instance was instantiated with.
424     ///
425     /// This method will search the module for an export with a matching entity index and return
426     /// the value, if found.
427     ///
428     /// Returns `None` if there was no export with a matching entity index.
429     ///
430     /// # Panics
431     ///
432     /// Panics if `store` does not own this instance.
433     pub fn get_module_export(
434         &self,
435         mut store: impl AsContextMut,
436         export: &ModuleExport,
437     ) -> Option<Extern> {
438         let store = store.as_context_mut().0;
439 
440         // Verify the `ModuleExport` matches the module used in this instance.
441         if self._module(store).id() != export.module {
442             return None;
443         }
444 
445         Some(self._get_export(store, export.entity))
446     }
447 
448     fn _get_export(&self, store: &mut StoreOpaque, entity: EntityIndex) -> Extern {
449         let id = store.id();
450         // SAFETY: the store `id` owns this instance and all exports contained
451         // within.
452         let export = unsafe { self.id.get_mut(store).get_export_by_index_mut(id, entity) };
453         unsafe { Extern::from_wasmtime_export(export, store) }
454     }
455 
456     /// Looks up an exported [`Func`] value by name.
457     ///
458     /// Returns `None` if there was no export named `name`, or if there was but
459     /// it wasn't a function.
460     ///
461     /// # Panics
462     ///
463     /// Panics if `store` does not own this instance.
464     pub fn get_func(&self, store: impl AsContextMut, name: &str) -> Option<Func> {
465         self.get_export(store, name)?.into_func()
466     }
467 
468     /// Looks up an exported [`Func`] value by name and with its type.
469     ///
470     /// This function is a convenience wrapper over [`Instance::get_func`] and
471     /// [`Func::typed`]. For more information see the linked documentation.
472     ///
473     /// Returns an error if `name` isn't a function export or if the export's
474     /// type did not match `Params` or `Results`
475     ///
476     /// # Panics
477     ///
478     /// Panics if `store` does not own this instance.
479     pub fn get_typed_func<Params, Results>(
480         &self,
481         mut store: impl AsContextMut,
482         name: &str,
483     ) -> Result<TypedFunc<Params, Results>>
484     where
485         Params: crate::WasmParams,
486         Results: crate::WasmResults,
487     {
488         let f = self
489             .get_export(store.as_context_mut(), name)
490             .and_then(|f| f.into_func())
491             .ok_or_else(|| anyhow!("failed to find function export `{}`", name))?;
492         Ok(f.typed::<Params, Results>(store)
493             .with_context(|| format!("failed to convert function `{name}` to given type"))?)
494     }
495 
496     /// Looks up an exported [`Table`] value by name.
497     ///
498     /// Returns `None` if there was no export named `name`, or if there was but
499     /// it wasn't a table.
500     ///
501     /// # Panics
502     ///
503     /// Panics if `store` does not own this instance.
504     pub fn get_table(&self, store: impl AsContextMut, name: &str) -> Option<Table> {
505         self.get_export(store, name)?.into_table()
506     }
507 
508     /// Looks up an exported [`Memory`] value by name.
509     ///
510     /// Returns `None` if there was no export named `name`, or if there was but
511     /// it wasn't a memory.
512     ///
513     /// # Panics
514     ///
515     /// Panics if `store` does not own this instance.
516     pub fn get_memory(&self, store: impl AsContextMut, name: &str) -> Option<Memory> {
517         self.get_export(store, name)?.into_memory()
518     }
519 
520     /// Looks up an exported [`SharedMemory`] value by name.
521     ///
522     /// Returns `None` if there was no export named `name`, or if there was but
523     /// it wasn't a shared memory.
524     ///
525     /// # Panics
526     ///
527     /// Panics if `store` does not own this instance.
528     pub fn get_shared_memory(
529         &self,
530         mut store: impl AsContextMut,
531         name: &str,
532     ) -> Option<SharedMemory> {
533         let mut store = store.as_context_mut();
534         self.get_export(&mut store, name)?.into_shared_memory()
535     }
536 
537     /// Looks up an exported [`Global`] value by name.
538     ///
539     /// Returns `None` if there was no export named `name`, or if there was but
540     /// it wasn't a global.
541     ///
542     /// # Panics
543     ///
544     /// Panics if `store` does not own this instance.
545     pub fn get_global(&self, store: impl AsContextMut, name: &str) -> Option<Global> {
546         self.get_export(store, name)?.into_global()
547     }
548 
549     /// Looks up a tag [`Tag`] by name.
550     ///
551     /// Returns `None` if there was no export named `name`, or if there was but
552     /// it wasn't a tag.
553     ///
554     /// # Panics
555     ///
556     /// Panics if `store` does not own this instance.
557     pub fn get_tag(&self, store: impl AsContextMut, name: &str) -> Option<Tag> {
558         self.get_export(store, name)?.into_tag()
559     }
560 
561     #[allow(
562         dead_code,
563         reason = "c-api crate does not yet support exnrefs and causes this method to be dead."
564     )]
565     pub(crate) fn id(&self) -> InstanceId {
566         self.id.instance()
567     }
568 
569     /// Get all globals within this instance.
570     ///
571     /// Returns both import and defined globals.
572     ///
573     /// Returns both exported and non-exported globals.
574     ///
575     /// Gives access to the full globals space.
576     #[cfg(feature = "coredump")]
577     pub(crate) fn all_globals<'a>(
578         &'a self,
579         store: &'a mut StoreOpaque,
580     ) -> impl ExactSizeIterator<Item = (GlobalIndex, Global)> + 'a {
581         let store_id = store.id();
582         store[self.id].all_globals(store_id)
583     }
584 
585     /// Get all memories within this instance.
586     ///
587     /// Returns both import and defined memories.
588     ///
589     /// Returns both exported and non-exported memories.
590     ///
591     /// Gives access to the full memories space.
592     #[cfg(feature = "coredump")]
593     pub(crate) fn all_memories<'a>(
594         &'a self,
595         store: &'a StoreOpaque,
596     ) -> impl ExactSizeIterator<Item = (MemoryIndex, Memory)> + 'a {
597         let store_id = store.id();
598         store[self.id].all_memories(store_id)
599     }
600 }
601 
602 pub(crate) struct OwnedImports {
603     functions: PrimaryMap<FuncIndex, VMFunctionImport>,
604     tables: PrimaryMap<TableIndex, VMTableImport>,
605     memories: PrimaryMap<MemoryIndex, VMMemoryImport>,
606     globals: PrimaryMap<GlobalIndex, VMGlobalImport>,
607     tags: PrimaryMap<TagIndex, VMTagImport>,
608 }
609 
610 impl OwnedImports {
611     fn new(module: &Module) -> OwnedImports {
612         let mut ret = OwnedImports::empty();
613         ret.reserve(module);
614         return ret;
615     }
616 
617     pub(crate) fn empty() -> OwnedImports {
618         OwnedImports {
619             functions: PrimaryMap::new(),
620             tables: PrimaryMap::new(),
621             memories: PrimaryMap::new(),
622             globals: PrimaryMap::new(),
623             tags: PrimaryMap::new(),
624         }
625     }
626 
627     pub(crate) fn reserve(&mut self, module: &Module) {
628         let raw = module.compiled_module().module();
629         self.functions.reserve(raw.num_imported_funcs);
630         self.tables.reserve(raw.num_imported_tables);
631         self.memories.reserve(raw.num_imported_memories);
632         self.globals.reserve(raw.num_imported_globals);
633         self.tags.reserve(raw.num_imported_tags);
634     }
635 
636     #[cfg(feature = "component-model")]
637     pub(crate) fn clear(&mut self) {
638         self.functions.clear();
639         self.tables.clear();
640         self.memories.clear();
641         self.globals.clear();
642         self.tags.clear();
643     }
644 
645     fn push(&mut self, item: &Extern, store: &mut StoreOpaque) {
646         match item {
647             Extern::Func(i) => {
648                 self.functions.push(i.vmimport(store));
649             }
650             Extern::Global(i) => {
651                 self.globals.push(i.vmimport(store));
652             }
653             Extern::Table(i) => {
654                 self.tables.push(i.vmimport(store));
655             }
656             Extern::Memory(i) => {
657                 self.memories.push(i.vmimport(store));
658             }
659             Extern::SharedMemory(i) => {
660                 self.memories.push(i.vmimport(store));
661             }
662             Extern::Tag(i) => {
663                 self.tags.push(i.vmimport(store));
664             }
665         }
666     }
667 
668     /// Note that this is unsafe as the validity of `item` is not verified and
669     /// it contains a bunch of raw pointers.
670     #[cfg(feature = "component-model")]
671     pub(crate) fn push_export(&mut self, store: &StoreOpaque, item: &crate::runtime::vm::Export) {
672         match item {
673             crate::runtime::vm::Export::Function(f) => {
674                 // SAFETY: the funcref associated with a `Func` is valid to use
675                 // under the `store` that owns the function.
676                 let f = unsafe { f.vm_func_ref(store).as_ref() };
677                 self.functions.push(VMFunctionImport {
678                     wasm_call: f.wasm_call.unwrap(),
679                     array_call: f.array_call,
680                     vmctx: f.vmctx,
681                 });
682             }
683             crate::runtime::vm::Export::Global(g) => {
684                 self.globals.push(g.vmimport(store));
685             }
686             crate::runtime::vm::Export::Table(t) => {
687                 self.tables.push(t.vmimport(store));
688             }
689             crate::runtime::vm::Export::Memory { memory, .. } => {
690                 self.memories.push(memory.vmimport(store));
691             }
692             crate::runtime::vm::Export::Tag(t) => {
693                 self.tags.push(t.vmimport(store));
694             }
695         }
696     }
697 
698     pub(crate) fn as_ref(&self) -> Imports<'_> {
699         Imports {
700             tables: self.tables.values().as_slice(),
701             globals: self.globals.values().as_slice(),
702             memories: self.memories.values().as_slice(),
703             functions: self.functions.values().as_slice(),
704             tags: self.tags.values().as_slice(),
705         }
706     }
707 }
708 
709 /// An instance, pre-instantiation, that is ready to be instantiated.
710 ///
711 /// This structure represents an instance *just before* it was instantiated,
712 /// after all type-checking and imports have been resolved. The only thing left
713 /// to do for this instance is to actually run the process of instantiation.
714 ///
715 /// Note that an `InstancePre` may not be tied to any particular [`Store`] if
716 /// none of the imports it closed over are tied to any particular [`Store`].
717 ///
718 /// This structure is created through the [`Linker::instantiate_pre`] method,
719 /// which also has some more information and examples.
720 ///
721 /// [`Store`]: crate::Store
722 /// [`Linker::instantiate_pre`]: crate::Linker::instantiate_pre
723 pub struct InstancePre<T> {
724     module: Module,
725 
726     /// The items which this `InstancePre` use to instantiate the `module`
727     /// provided, passed to `Instance::new_started` after inserting them into a
728     /// `Store`.
729     ///
730     /// Note that this is stored as an `Arc<[T]>` to quickly move a strong
731     /// reference to everything internally into a `Store<T>` without having to
732     /// clone each individual item.
733     items: Arc<[Definition]>,
734 
735     /// A count of `Definition::HostFunc` entries in `items` above to
736     /// preallocate space in a `Store` up front for all entries to be inserted.
737     host_funcs: usize,
738 
739     /// The `VMFuncRef`s for the functions in `items` that do not
740     /// have a `wasm_call` trampoline. We pre-allocate and pre-patch these
741     /// `VMFuncRef`s so that we don't have to do it at
742     /// instantiation time.
743     ///
744     /// This is an `Arc<[T]>` for the same reason as `items`.
745     func_refs: Arc<[VMFuncRef]>,
746 
747     _marker: core::marker::PhantomData<fn() -> T>,
748 }
749 
750 /// InstancePre's clone does not require T: Clone
751 impl<T> Clone for InstancePre<T> {
752     fn clone(&self) -> Self {
753         Self {
754             module: self.module.clone(),
755             items: self.items.clone(),
756             host_funcs: self.host_funcs,
757             func_refs: self.func_refs.clone(),
758             _marker: self._marker,
759         }
760     }
761 }
762 
763 impl<T: 'static> InstancePre<T> {
764     /// Creates a new `InstancePre` which type-checks the `items` provided and
765     /// on success is ready to instantiate a new instance.
766     ///
767     /// # Unsafety
768     ///
769     /// This method is unsafe as the `T` of the `InstancePre<T>` is not
770     /// guaranteed to be the same as the `T` within the `Store`, the caller must
771     /// verify that.
772     pub(crate) unsafe fn new(module: &Module, items: Vec<Definition>) -> Result<InstancePre<T>> {
773         typecheck(module, &items, |cx, ty, item| cx.definition(ty, &item.ty()))?;
774 
775         let mut func_refs = vec![];
776         let mut host_funcs = 0;
777         for item in &items {
778             match item {
779                 Definition::Extern(_, _) => {}
780                 Definition::HostFunc(f) => {
781                     host_funcs += 1;
782                     if f.func_ref().wasm_call.is_none() {
783                         // `f` needs its `VMFuncRef::wasm_call` patched with a
784                         // Wasm-to-native trampoline.
785                         debug_assert!(matches!(f.host_ctx(), crate::HostContext::Array(_)));
786                         func_refs.push(VMFuncRef {
787                             wasm_call: module
788                                 .wasm_to_array_trampoline(f.sig_index())
789                                 .map(|f| f.into()),
790                             ..*f.func_ref()
791                         });
792                     }
793                 }
794             }
795         }
796 
797         Ok(InstancePre {
798             module: module.clone(),
799             items: items.into(),
800             host_funcs,
801             func_refs: func_refs.into(),
802             _marker: core::marker::PhantomData,
803         })
804     }
805 
806     /// Returns a reference to the module that this [`InstancePre`] will be
807     /// instantiating.
808     pub fn module(&self) -> &Module {
809         &self.module
810     }
811 
812     /// Instantiates this instance, creating a new instance within the provided
813     /// `store`.
814     ///
815     /// This function will run the actual process of instantiation to
816     /// completion. This will use all of the previously-closed-over items as
817     /// imports to instantiate the module that this was originally created with.
818     ///
819     /// For more information about instantiation see [`Instance::new`].
820     ///
821     /// # Panics
822     ///
823     /// Panics if any import closed over by this [`InstancePre`] isn't owned by
824     /// `store`, or if `store` has async support enabled. Additionally this
825     /// function will panic if the `store` provided comes from a different
826     /// [`Engine`] than the [`InstancePre`] originally came from.
827     pub fn instantiate(&self, mut store: impl AsContextMut<Data = T>) -> Result<Instance> {
828         let mut store = store.as_context_mut();
829         let imports = pre_instantiate_raw(
830             &mut store.0,
831             &self.module,
832             &self.items,
833             self.host_funcs,
834             &self.func_refs,
835         )?;
836 
837         // This unsafety should be handled by the type-checking performed by the
838         // constructor of `InstancePre` to assert that all the imports we're passing
839         // in match the module we're instantiating.
840         unsafe { Instance::new_started(&mut store, &self.module, imports.as_ref()) }
841     }
842 
843     /// Creates a new instance, running the start function asynchronously
844     /// instead of inline.
845     ///
846     /// For more information about asynchronous instantiation see the
847     /// documentation on [`Instance::new_async`].
848     ///
849     /// # Panics
850     ///
851     /// Panics if any import closed over by this [`InstancePre`] isn't owned by
852     /// `store`, or if `store` does not have async support enabled.
853     #[cfg(feature = "async")]
854     pub async fn instantiate_async(
855         &self,
856         mut store: impl AsContextMut<Data: Send>,
857     ) -> Result<Instance> {
858         let mut store = store.as_context_mut();
859         let imports = pre_instantiate_raw(
860             &mut store.0,
861             &self.module,
862             &self.items,
863             self.host_funcs,
864             &self.func_refs,
865         )?;
866 
867         // This unsafety should be handled by the type-checking performed by the
868         // constructor of `InstancePre` to assert that all the imports we're passing
869         // in match the module we're instantiating.
870         unsafe { Instance::new_started_async(&mut store, &self.module, imports.as_ref()).await }
871     }
872 }
873 
874 /// Helper function shared between
875 /// `InstancePre::{instantiate,instantiate_async}`
876 ///
877 /// This is an out-of-line function to avoid the generic on `InstancePre` and
878 /// get this compiled into the `wasmtime` crate to avoid having it monomorphized
879 /// elsewhere.
880 fn pre_instantiate_raw(
881     store: &mut StoreOpaque,
882     module: &Module,
883     items: &Arc<[Definition]>,
884     host_funcs: usize,
885     func_refs: &Arc<[VMFuncRef]>,
886 ) -> Result<OwnedImports> {
887     // Register this module and use it to fill out any funcref wasm_call holes
888     // we can. For more comments on this see `typecheck_externs`.
889     store.modules_mut().register_module(module);
890     let (funcrefs, modules) = store.func_refs_and_modules();
891     funcrefs.fill(modules);
892 
893     if host_funcs > 0 {
894         // Any linker-defined function of the `Definition::HostFunc` variant
895         // will insert a function into the store automatically as part of
896         // instantiation, so reserve space here to make insertion more efficient
897         // as it won't have to realloc during the instantiation.
898         funcrefs.reserve_storage(host_funcs);
899 
900         // The usage of `to_extern_store_rooted` requires that the items are
901         // rooted via another means, which happens here by cloning the list of
902         // items into the store once. This avoids cloning each individual item
903         // below.
904         funcrefs.push_instance_pre_definitions(items.clone());
905         funcrefs.push_instance_pre_func_refs(func_refs.clone());
906     }
907 
908     let mut func_refs = func_refs.iter().map(|f| NonNull::from(f));
909     let mut imports = OwnedImports::new(module);
910     for import in items.iter() {
911         if !import.comes_from_same_store(store) {
912             bail!("cross-`Store` instantiation is not currently supported");
913         }
914         // This unsafety should be encapsulated in the constructor of
915         // `InstancePre` where the `T` of the original item should match the
916         // `T` of the store. Additionally the rooting necessary has happened
917         // above.
918         let item = match import {
919             Definition::Extern(e, _) => e.clone(),
920             Definition::HostFunc(func) => unsafe {
921                 func.to_func_store_rooted(
922                     store,
923                     if func.func_ref().wasm_call.is_none() {
924                         Some(func_refs.next().unwrap())
925                     } else {
926                         None
927                     },
928                 )
929                 .into()
930             },
931         };
932         imports.push(&item, store);
933     }
934 
935     Ok(imports)
936 }
937 
938 fn typecheck<I>(
939     module: &Module,
940     import_args: &[I],
941     check: impl Fn(&matching::MatchCx<'_>, &EntityType, &I) -> Result<()>,
942 ) -> Result<()> {
943     let env_module = module.compiled_module().module();
944     let expected_len = env_module.imports().count();
945     let actual_len = import_args.len();
946     if expected_len != actual_len {
947         bail!("expected {expected_len} imports, found {actual_len}");
948     }
949     let cx = matching::MatchCx::new(module.engine());
950     for ((name, field, expected_ty), actual) in env_module.imports().zip(import_args) {
951         debug_assert!(expected_ty.is_canonicalized_for_runtime_usage());
952         check(&cx, &expected_ty, actual)
953             .with_context(|| format!("incompatible import type for `{name}::{field}`"))?;
954     }
955     Ok(())
956 }
957