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