1 //! An `Instance` contains all the runtime state used by execution of a
2 //! wasm module (except its callstack and register state). An
3 //! `InstanceHandle` is a reference-counting handle for an `Instance`.
4 
5 use crate::prelude::*;
6 use crate::runtime::vm::const_expr::{ConstEvalContext, ConstExprEvaluator};
7 use crate::runtime::vm::export::Export;
8 use crate::runtime::vm::memory::{Memory, RuntimeMemoryCreator};
9 use crate::runtime::vm::table::{Table, TableElement, TableElementType};
10 use crate::runtime::vm::vmcontext::{
11     VMBuiltinFunctionsArray, VMContext, VMFuncRef, VMFunctionImport, VMGlobalDefinition,
12     VMGlobalImport, VMMemoryDefinition, VMMemoryImport, VMOpaqueContext, VMRuntimeLimits,
13     VMTableDefinition, VMTableImport,
14 };
15 use crate::runtime::vm::{
16     ExportFunction, ExportGlobal, ExportMemory, ExportTable, GcStore, Imports, ModuleRuntimeInfo,
17     SendSyncPtr, Store, VMFunctionBody, VMGcRef, WasmFault,
18 };
19 use alloc::sync::Arc;
20 use anyhow::{Error, Result};
21 use core::alloc::Layout;
22 use core::any::Any;
23 use core::ops::Range;
24 use core::ptr::NonNull;
25 use core::sync::atomic::AtomicU64;
26 use core::{mem, ptr};
27 use sptr::Strict;
28 use wasmtime_environ::{
29     packed_option::ReservedValue, DataIndex, DefinedGlobalIndex, DefinedMemoryIndex,
30     DefinedTableIndex, ElemIndex, EntityIndex, EntityRef, EntitySet, FuncIndex, GlobalIndex,
31     HostPtr, MemoryIndex, MemoryPlan, Module, ModuleInternedTypeIndex, PrimaryMap, TableIndex,
32     TableInitialValue, TableSegmentElements, Trap, VMOffsets, VMSharedTypeIndex, WasmHeapTopType,
33     VMCONTEXT_MAGIC,
34 };
35 #[cfg(feature = "wmemcheck")]
36 use wasmtime_wmemcheck::Wmemcheck;
37 
38 mod allocator;
39 
40 pub use allocator::*;
41 
42 /// A type that roughly corresponds to a WebAssembly instance, but is also used
43 /// for host-defined objects.
44 ///
45 /// This structure is is never allocated directly but is instead managed through
46 /// an `InstanceHandle`. This structure ends with a `VMContext` which has a
47 /// dynamic size corresponding to the `module` configured within. Memory
48 /// management of this structure is always externalized.
49 ///
50 /// Instances here can correspond to actual instantiated modules, but it's also
51 /// used ubiquitously for host-defined objects. For example creating a
52 /// host-defined memory will have a `module` that looks like it exports a single
53 /// memory (and similar for other constructs).
54 ///
55 /// This `Instance` type is used as a ubiquitous representation for WebAssembly
56 /// values, whether or not they were created on the host or through a module.
57 #[repr(C)] // ensure that the vmctx field is last.
58 pub struct Instance {
59     /// The runtime info (corresponding to the "compiled module"
60     /// abstraction in higher layers) that is retained and needed for
61     /// lazy initialization. This provides access to the underlying
62     /// Wasm module entities, the compiled JIT code, metadata about
63     /// functions, lazy initialization state, etc.
64     runtime_info: Arc<dyn ModuleRuntimeInfo>,
65 
66     /// WebAssembly linear memory data.
67     ///
68     /// This is where all runtime information about defined linear memories in
69     /// this module lives.
70     ///
71     /// The `MemoryAllocationIndex` was given from our `InstanceAllocator` and
72     /// must be given back to the instance allocator when deallocating each
73     /// memory.
74     memories: PrimaryMap<DefinedMemoryIndex, (MemoryAllocationIndex, Memory)>,
75 
76     /// WebAssembly table data.
77     ///
78     /// Like memories, this is only for defined tables in the module and
79     /// contains all of their runtime state.
80     ///
81     /// The `TableAllocationIndex` was given from our `InstanceAllocator` and
82     /// must be given back to the instance allocator when deallocating each
83     /// table.
84     tables: PrimaryMap<DefinedTableIndex, (TableAllocationIndex, Table)>,
85 
86     /// Stores the dropped passive element segments in this instantiation by index.
87     /// If the index is present in the set, the segment has been dropped.
88     dropped_elements: EntitySet<ElemIndex>,
89 
90     /// Stores the dropped passive data segments in this instantiation by index.
91     /// If the index is present in the set, the segment has been dropped.
92     dropped_data: EntitySet<DataIndex>,
93 
94     /// Hosts can store arbitrary per-instance information here.
95     ///
96     /// Most of the time from Wasmtime this is `Box::new(())`, a noop
97     /// allocation, but some host-defined objects will store their state here.
98     host_state: Box<dyn Any + Send + Sync>,
99 
100     /// A pointer to the `vmctx` field at the end of the `Instance`.
101     ///
102     /// If you're looking at this a reasonable question would be "why do we need
103     /// a pointer to ourselves?" because after all the pointer's value is
104     /// trivially derivable from any `&Instance` pointer. The rationale for this
105     /// field's existence is subtle, but it's required for correctness. The
106     /// short version is "this makes miri happy".
107     ///
108     /// The long version of why this field exists is that the rules that MIRI
109     /// uses to ensure pointers are used correctly have various conditions on
110     /// them depend on how pointers are used. More specifically if `*mut T` is
111     /// derived from `&mut T`, then that invalidates all prior pointers drived
112     /// from the `&mut T`. This means that while we liberally want to re-acquire
113     /// a `*mut VMContext` throughout the implementation of `Instance` the
114     /// trivial way, a function `fn vmctx(&mut Instance) -> *mut VMContext`
115     /// would effectively invalidate all prior `*mut VMContext` pointers
116     /// acquired. The purpose of this field is to serve as a sort of
117     /// source-of-truth for where `*mut VMContext` pointers come from.
118     ///
119     /// This field is initialized when the `Instance` is created with the
120     /// original allocation's pointer. That means that the provenance of this
121     /// pointer contains the entire allocation (both instance and `VMContext`).
122     /// This provenance bit is then "carried through" where `fn vmctx` will base
123     /// all returned pointers on this pointer itself. This provides the means of
124     /// never invalidating this pointer throughout MIRI and additionally being
125     /// able to still temporarily have `&mut Instance` methods and such.
126     ///
127     /// It's important to note, though, that this is not here purely for MIRI.
128     /// The careful construction of the `fn vmctx` method has ramifications on
129     /// the LLVM IR generated, for example. A historical CVE on Wasmtime,
130     /// GHSA-ch89-5g45-qwc7, was caused due to relying on undefined behavior. By
131     /// deriving VMContext pointers from this pointer it specifically hints to
132     /// LLVM that trickery is afoot and it properly informs `noalias` and such
133     /// annotations and analysis. More-or-less this pointer is actually loaded
134     /// in LLVM IR which helps defeat otherwise present aliasing optimizations,
135     /// which we want, since writes to this should basically never be optimized
136     /// out.
137     ///
138     /// As a final note it's worth pointing out that the machine code generated
139     /// for accessing `fn vmctx` is still as one would expect. This member isn't
140     /// actually ever loaded at runtime (or at least shouldn't be). Perhaps in
141     /// the future if the memory consumption of this field is a problem we could
142     /// shrink it slightly, but for now one extra pointer per wasm instance
143     /// seems not too bad.
144     vmctx_self_reference: SendSyncPtr<VMContext>,
145 
146     // TODO: add support for multiple memories; `wmemcheck_state` corresponds to
147     // memory 0.
148     #[cfg(feature = "wmemcheck")]
149     pub(crate) wmemcheck_state: Option<Wmemcheck>,
150 
151     /// Additional context used by compiled wasm code. This field is last, and
152     /// represents a dynamically-sized array that extends beyond the nominal
153     /// end of the struct (similar to a flexible array member).
154     vmctx: VMContext,
155 }
156 
157 impl Instance {
158     /// Create an instance at the given memory address.
159     ///
160     /// It is assumed the memory was properly aligned and the
161     /// allocation was `alloc_size` in bytes.
162     unsafe fn new(
163         req: InstanceAllocationRequest,
164         memories: PrimaryMap<DefinedMemoryIndex, (MemoryAllocationIndex, Memory)>,
165         tables: PrimaryMap<DefinedTableIndex, (TableAllocationIndex, Table)>,
166         memory_plans: &PrimaryMap<MemoryIndex, MemoryPlan>,
167     ) -> InstanceHandle {
168         // The allocation must be *at least* the size required of `Instance`.
169         let layout = Self::alloc_layout(req.runtime_info.offsets());
170         let ptr = alloc::alloc::alloc(layout);
171         if ptr.is_null() {
172             alloc::alloc::handle_alloc_error(layout);
173         }
174         let ptr = ptr.cast::<Instance>();
175 
176         let module = req.runtime_info.module();
177         let dropped_elements = EntitySet::with_capacity(module.passive_elements.len());
178         let dropped_data = EntitySet::with_capacity(module.passive_data_map.len());
179 
180         #[cfg(not(feature = "wmemcheck"))]
181         let _ = memory_plans;
182 
183         ptr::write(
184             ptr,
185             Instance {
186                 runtime_info: req.runtime_info.clone(),
187                 memories,
188                 tables,
189                 dropped_elements,
190                 dropped_data,
191                 host_state: req.host_state,
192                 vmctx_self_reference: SendSyncPtr::new(NonNull::new(ptr.add(1).cast()).unwrap()),
193                 vmctx: VMContext {
194                     _marker: core::marker::PhantomPinned,
195                 },
196                 #[cfg(feature = "wmemcheck")]
197                 wmemcheck_state: {
198                     if req.wmemcheck {
199                         let size = memory_plans
200                             .iter()
201                             .next()
202                             .map(|plan| plan.1.memory.minimum)
203                             .unwrap_or(0)
204                             * 64
205                             * 1024;
206                         Some(Wmemcheck::new(size as usize))
207                     } else {
208                         None
209                     }
210                 },
211             },
212         );
213 
214         (*ptr).initialize_vmctx(module, req.runtime_info.offsets(), req.store, req.imports);
215         InstanceHandle {
216             instance: Some(SendSyncPtr::new(NonNull::new(ptr).unwrap())),
217         }
218     }
219 
220     /// Converts the provided `*mut VMContext` to an `Instance` pointer and runs
221     /// the provided closure with the instance.
222     ///
223     /// This method will move the `vmctx` pointer backwards to point to the
224     /// original `Instance` that precedes it. The closure is provided a
225     /// temporary version of the `Instance` pointer with a constrained lifetime
226     /// to the closure to ensure it doesn't accidentally escape.
227     ///
228     /// # Unsafety
229     ///
230     /// Callers must validate that the `vmctx` pointer is a valid allocation
231     /// and that it's valid to acquire `&mut Instance` at this time. For example
232     /// this can't be called twice on the same `VMContext` to get two active
233     /// pointers to the same `Instance`.
234     #[inline]
235     pub unsafe fn from_vmctx<R>(vmctx: *mut VMContext, f: impl FnOnce(&mut Instance) -> R) -> R {
236         assert!(!vmctx.is_null());
237         let ptr = vmctx
238             .byte_sub(mem::size_of::<Instance>())
239             .cast::<Instance>();
240         f(&mut *ptr)
241     }
242 
243     /// Helper function to access various locations offset from our `*mut
244     /// VMContext` object.
245     ///
246     /// # Safety
247     ///
248     /// This method is unsafe because the `offset` must be within bounds of the
249     /// `VMContext` object trailing this instance.
250     unsafe fn vmctx_plus_offset<T>(&self, offset: u32) -> *const T {
251         self.vmctx()
252             .byte_add(usize::try_from(offset).unwrap())
253             .cast()
254     }
255 
256     /// Dual of `vmctx_plus_offset`, but for mutability.
257     unsafe fn vmctx_plus_offset_mut<T>(&mut self, offset: u32) -> *mut T {
258         self.vmctx()
259             .byte_add(usize::try_from(offset).unwrap())
260             .cast()
261     }
262 
263     pub(crate) fn module(&self) -> &Arc<Module> {
264         self.runtime_info.module()
265     }
266 
267     /// Translate a module-level interned type index into an engine-level
268     /// interned type index.
269     pub fn engine_type_index(&self, module_index: ModuleInternedTypeIndex) -> VMSharedTypeIndex {
270         self.runtime_info.engine_type_index(module_index)
271     }
272 
273     #[inline]
274     fn offsets(&self) -> &VMOffsets<HostPtr> {
275         self.runtime_info.offsets()
276     }
277 
278     /// Return the indexed `VMFunctionImport`.
279     fn imported_function(&self, index: FuncIndex) -> &VMFunctionImport {
280         unsafe { &*self.vmctx_plus_offset(self.offsets().vmctx_vmfunction_import(index)) }
281     }
282 
283     /// Return the index `VMTableImport`.
284     fn imported_table(&self, index: TableIndex) -> &VMTableImport {
285         unsafe { &*self.vmctx_plus_offset(self.offsets().vmctx_vmtable_import(index)) }
286     }
287 
288     /// Return the indexed `VMMemoryImport`.
289     fn imported_memory(&self, index: MemoryIndex) -> &VMMemoryImport {
290         unsafe { &*self.vmctx_plus_offset(self.offsets().vmctx_vmmemory_import(index)) }
291     }
292 
293     /// Return the indexed `VMGlobalImport`.
294     fn imported_global(&self, index: GlobalIndex) -> &VMGlobalImport {
295         unsafe { &*self.vmctx_plus_offset(self.offsets().vmctx_vmglobal_import(index)) }
296     }
297 
298     /// Return the indexed `VMTableDefinition`.
299     #[allow(dead_code)]
300     fn table(&mut self, index: DefinedTableIndex) -> VMTableDefinition {
301         unsafe { *self.table_ptr(index) }
302     }
303 
304     /// Updates the value for a defined table to `VMTableDefinition`.
305     fn set_table(&mut self, index: DefinedTableIndex, table: VMTableDefinition) {
306         unsafe {
307             *self.table_ptr(index) = table;
308         }
309     }
310 
311     /// Return the indexed `VMTableDefinition`.
312     fn table_ptr(&mut self, index: DefinedTableIndex) -> *mut VMTableDefinition {
313         unsafe { self.vmctx_plus_offset_mut(self.offsets().vmctx_vmtable_definition(index)) }
314     }
315 
316     /// Get a locally defined or imported memory.
317     pub(crate) fn get_memory(&self, index: MemoryIndex) -> VMMemoryDefinition {
318         if let Some(defined_index) = self.module().defined_memory_index(index) {
319             self.memory(defined_index)
320         } else {
321             let import = self.imported_memory(index);
322             unsafe { VMMemoryDefinition::load(import.from) }
323         }
324     }
325 
326     /// Get a locally defined or imported memory.
327     #[cfg(feature = "threads")]
328     pub(crate) fn get_runtime_memory(&mut self, index: MemoryIndex) -> &mut Memory {
329         if let Some(defined_index) = self.module().defined_memory_index(index) {
330             unsafe { &mut *self.get_defined_memory(defined_index) }
331         } else {
332             let import = self.imported_memory(index);
333             unsafe {
334                 let ptr =
335                     Instance::from_vmctx(import.vmctx, |i| i.get_defined_memory(import.index));
336                 &mut *ptr
337             }
338         }
339     }
340 
341     /// Return the indexed `VMMemoryDefinition`.
342     fn memory(&self, index: DefinedMemoryIndex) -> VMMemoryDefinition {
343         unsafe { VMMemoryDefinition::load(self.memory_ptr(index)) }
344     }
345 
346     /// Set the indexed memory to `VMMemoryDefinition`.
347     fn set_memory(&self, index: DefinedMemoryIndex, mem: VMMemoryDefinition) {
348         unsafe {
349             *self.memory_ptr(index) = mem;
350         }
351     }
352 
353     /// Return the indexed `VMMemoryDefinition`.
354     fn memory_ptr(&self, index: DefinedMemoryIndex) -> *mut VMMemoryDefinition {
355         unsafe { *self.vmctx_plus_offset(self.offsets().vmctx_vmmemory_pointer(index)) }
356     }
357 
358     /// Return the indexed `VMGlobalDefinition`.
359     fn global_ptr(&mut self, index: DefinedGlobalIndex) -> *mut VMGlobalDefinition {
360         unsafe { self.vmctx_plus_offset_mut(self.offsets().vmctx_vmglobal_definition(index)) }
361     }
362 
363     /// Get a raw pointer to the global at the given index regardless whether it
364     /// is defined locally or imported from another module.
365     ///
366     /// Panics if the index is out of bound or is the reserved value.
367     pub(crate) fn defined_or_imported_global_ptr(
368         &mut self,
369         index: GlobalIndex,
370     ) -> *mut VMGlobalDefinition {
371         if let Some(index) = self.module().defined_global_index(index) {
372             self.global_ptr(index)
373         } else {
374             self.imported_global(index).from
375         }
376     }
377 
378     /// Get all globals within this instance.
379     ///
380     /// Returns both import and defined globals.
381     ///
382     /// Returns both exported and non-exported globals.
383     ///
384     /// Gives access to the full globals space.
385     pub fn all_globals<'a>(
386         &'a mut self,
387     ) -> impl ExactSizeIterator<Item = (GlobalIndex, ExportGlobal)> + 'a {
388         let module = self.module().clone();
389         module.globals.keys().map(move |idx| {
390             (
391                 idx,
392                 ExportGlobal {
393                     definition: self.defined_or_imported_global_ptr(idx),
394                     vmctx: self.vmctx(),
395                     global: self.module().globals[idx],
396                 },
397             )
398         })
399     }
400 
401     /// Get the globals defined in this instance (not imported).
402     pub fn defined_globals<'a>(
403         &'a mut self,
404     ) -> impl ExactSizeIterator<Item = (DefinedGlobalIndex, ExportGlobal)> + 'a {
405         let module = self.module().clone();
406         module
407             .globals
408             .keys()
409             .skip(module.num_imported_globals)
410             .map(move |global_idx| {
411                 let def_idx = module.defined_global_index(global_idx).unwrap();
412                 let global = ExportGlobal {
413                     definition: self.global_ptr(def_idx),
414                     vmctx: self.vmctx(),
415                     global: self.module().globals[global_idx],
416                 };
417                 (def_idx, global)
418             })
419     }
420 
421     /// Return a pointer to the interrupts structure
422     #[inline]
423     pub fn runtime_limits(&mut self) -> *mut *const VMRuntimeLimits {
424         unsafe { self.vmctx_plus_offset_mut(self.offsets().vmctx_runtime_limits()) }
425     }
426 
427     /// Return a pointer to the global epoch counter used by this instance.
428     pub fn epoch_ptr(&mut self) -> *mut *const AtomicU64 {
429         unsafe { self.vmctx_plus_offset_mut(self.offsets().vmctx_epoch_ptr()) }
430     }
431 
432     /// Return a pointer to the GC heap base pointer.
433     pub fn gc_heap_base(&mut self) -> *mut *mut u8 {
434         unsafe { self.vmctx_plus_offset_mut(self.offsets().vmctx_gc_heap_base()) }
435     }
436 
437     /// Return a pointer to the GC heap bound.
438     pub fn gc_heap_bound(&mut self) -> *mut usize {
439         unsafe { self.vmctx_plus_offset_mut(self.offsets().vmctx_gc_heap_bound()) }
440     }
441 
442     /// Return a pointer to the collector-specific heap data.
443     pub fn gc_heap_data(&mut self) -> *mut *mut u8 {
444         unsafe { self.vmctx_plus_offset_mut(self.offsets().vmctx_gc_heap_data()) }
445     }
446 
447     /// Gets a pointer to this instance's `Store` which was originally
448     /// configured on creation.
449     ///
450     /// # Panics
451     ///
452     /// This will panic if the originally configured store was `None`. That can
453     /// happen for host functions so host functions can't be queried what their
454     /// original `Store` was since it's just retained as null (since host
455     /// functions are shared amongst threads and don't all share the same
456     /// store).
457     #[inline]
458     pub fn store(&self) -> *mut dyn Store {
459         let ptr =
460             unsafe { *self.vmctx_plus_offset::<*mut dyn Store>(self.offsets().vmctx_store()) };
461         assert!(!ptr.is_null());
462         ptr
463     }
464 
465     pub(crate) unsafe fn set_store(&mut self, store: Option<*mut dyn Store>) {
466         if let Some(store) = store {
467             *self.vmctx_plus_offset_mut(self.offsets().vmctx_store()) = store;
468             *self.runtime_limits() = (*store).vmruntime_limits();
469             *self.epoch_ptr() = (*store).epoch_ptr();
470             self.set_gc_heap((*store).maybe_gc_store());
471         } else {
472             assert_eq!(
473                 mem::size_of::<*mut dyn Store>(),
474                 mem::size_of::<[*mut (); 2]>()
475             );
476             *self.vmctx_plus_offset_mut::<[*mut (); 2]>(self.offsets().vmctx_store()) =
477                 [ptr::null_mut(), ptr::null_mut()];
478             *self.runtime_limits() = ptr::null_mut();
479             *self.epoch_ptr() = ptr::null_mut();
480             self.set_gc_heap(None);
481         }
482     }
483 
484     unsafe fn set_gc_heap(&mut self, gc_store: Option<&mut GcStore>) {
485         if let Some(gc_store) = gc_store {
486             *self.gc_heap_base() = gc_store.gc_heap.vmctx_gc_heap_base();
487             *self.gc_heap_bound() = gc_store.gc_heap.vmctx_gc_heap_bound();
488             *self.gc_heap_data() = gc_store.gc_heap.vmctx_gc_heap_data();
489         } else {
490             *self.gc_heap_base() = ptr::null_mut();
491             *self.gc_heap_bound() = 0;
492             *self.gc_heap_data() = ptr::null_mut();
493         }
494     }
495 
496     pub(crate) unsafe fn set_callee(&mut self, callee: Option<NonNull<VMFunctionBody>>) {
497         *self.vmctx_plus_offset_mut(self.offsets().vmctx_callee()) =
498             callee.map_or(ptr::null_mut(), |c| c.as_ptr());
499     }
500 
501     /// Return a reference to the vmctx used by compiled wasm code.
502     #[inline]
503     pub fn vmctx(&self) -> *mut VMContext {
504         // The definition of this method is subtle but intentional. The goal
505         // here is that effectively this should return `&mut self.vmctx`, but
506         // it's not quite so simple. Some more documentation is available on the
507         // `vmctx_self_reference` field, but the general idea is that we're
508         // creating a pointer to return with proper provenance. Provenance is
509         // still in the works in Rust at the time of this writing but the load
510         // of the `self.vmctx_self_reference` field is important here as it
511         // affects how LLVM thinks about aliasing with respect to the returned
512         // pointer.
513         //
514         // The intention of this method is to codegen to machine code as `&mut
515         // self.vmctx`, however. While it doesn't show up like this in LLVM IR
516         // (there's an actual load of the field) it does look like that by the
517         // time the backend runs. (that's magic to me, the backend removing
518         // loads...)
519         //
520         // As a final minor note, strict provenance APIs are not stable on Rust
521         // today so the `sptr` crate is used. This crate provides the extension
522         // trait `Strict` but the method names conflict with the nightly methods
523         // so a different syntax is used to invoke methods here.
524         let addr = ptr::addr_of!(self.vmctx);
525         Strict::with_addr(self.vmctx_self_reference.as_ptr(), Strict::addr(addr))
526     }
527 
528     fn get_exported_func(&mut self, index: FuncIndex) -> ExportFunction {
529         let func_ref = self.get_func_ref(index).unwrap();
530         let func_ref = NonNull::new(func_ref as *const VMFuncRef as *mut _).unwrap();
531         ExportFunction { func_ref }
532     }
533 
534     fn get_exported_table(&mut self, index: TableIndex) -> ExportTable {
535         let (definition, vmctx) = if let Some(def_index) = self.module().defined_table_index(index)
536         {
537             (self.table_ptr(def_index), self.vmctx())
538         } else {
539             let import = self.imported_table(index);
540             (import.from, import.vmctx)
541         };
542         ExportTable {
543             definition,
544             vmctx,
545             table: self.module().table_plans[index].clone(),
546         }
547     }
548 
549     fn get_exported_memory(&mut self, index: MemoryIndex) -> ExportMemory {
550         let (definition, vmctx, def_index) =
551             if let Some(def_index) = self.module().defined_memory_index(index) {
552                 (self.memory_ptr(def_index), self.vmctx(), def_index)
553             } else {
554                 let import = self.imported_memory(index);
555                 (import.from, import.vmctx, import.index)
556             };
557         ExportMemory {
558             definition,
559             vmctx,
560             memory: self.module().memory_plans[index].clone(),
561             index: def_index,
562         }
563     }
564 
565     fn get_exported_global(&mut self, index: GlobalIndex) -> ExportGlobal {
566         ExportGlobal {
567             definition: if let Some(def_index) = self.module().defined_global_index(index) {
568                 self.global_ptr(def_index)
569             } else {
570                 self.imported_global(index).from
571             },
572             vmctx: self.vmctx(),
573             global: self.module().globals[index],
574         }
575     }
576 
577     /// Return an iterator over the exports of this instance.
578     ///
579     /// Specifically, it provides access to the key-value pairs, where the keys
580     /// are export names, and the values are export declarations which can be
581     /// resolved `lookup_by_declaration`.
582     pub fn exports(&self) -> indexmap::map::Iter<String, EntityIndex> {
583         self.module().exports.iter()
584     }
585 
586     /// Return a reference to the custom state attached to this instance.
587     #[inline]
588     pub fn host_state(&self) -> &dyn Any {
589         &*self.host_state
590     }
591 
592     /// Return the table index for the given `VMTableDefinition`.
593     pub unsafe fn table_index(&mut self, table: &VMTableDefinition) -> DefinedTableIndex {
594         let index = DefinedTableIndex::new(
595             usize::try_from(
596                 (table as *const VMTableDefinition)
597                     .offset_from(self.table_ptr(DefinedTableIndex::new(0))),
598             )
599             .unwrap(),
600         );
601         assert!(index.index() < self.tables.len());
602         index
603     }
604 
605     /// Grow memory by the specified amount of pages.
606     ///
607     /// Returns `None` if memory can't be grown by the specified amount
608     /// of pages. Returns `Some` with the old size in bytes if growth was
609     /// successful.
610     pub(crate) fn memory_grow(
611         &mut self,
612         index: MemoryIndex,
613         delta: u64,
614     ) -> Result<Option<usize>, Error> {
615         match self.module().defined_memory_index(index) {
616             Some(idx) => self.defined_memory_grow(idx, delta),
617             None => {
618                 let import = self.imported_memory(index);
619                 unsafe {
620                     Instance::from_vmctx(import.vmctx, |i| {
621                         i.defined_memory_grow(import.index, delta)
622                     })
623                 }
624             }
625         }
626     }
627 
628     fn defined_memory_grow(
629         &mut self,
630         idx: DefinedMemoryIndex,
631         delta: u64,
632     ) -> Result<Option<usize>, Error> {
633         let store = unsafe { &mut *self.store() };
634         let memory = &mut self.memories[idx].1;
635 
636         let result = unsafe { memory.grow(delta, Some(store)) };
637 
638         // Update the state used by a non-shared Wasm memory in case the base
639         // pointer and/or the length changed.
640         if memory.as_shared_memory().is_none() {
641             let vmmemory = memory.vmmemory();
642             self.set_memory(idx, vmmemory);
643         }
644 
645         result
646     }
647 
648     pub(crate) fn table_element_type(&mut self, table_index: TableIndex) -> TableElementType {
649         unsafe { (*self.get_table(table_index)).element_type() }
650     }
651 
652     /// Grow table by the specified amount of elements, filling them with
653     /// `init_value`.
654     ///
655     /// Returns `None` if table can't be grown by the specified amount of
656     /// elements, or if `init_value` is the wrong type of table element.
657     pub(crate) fn table_grow(
658         &mut self,
659         table_index: TableIndex,
660         delta: u32,
661         init_value: TableElement,
662     ) -> Result<Option<u32>, Error> {
663         self.with_defined_table_index_and_instance(table_index, |i, instance| {
664             instance.defined_table_grow(i, delta, init_value)
665         })
666     }
667 
668     fn defined_table_grow(
669         &mut self,
670         table_index: DefinedTableIndex,
671         delta: u32,
672         init_value: TableElement,
673     ) -> Result<Option<u32>, Error> {
674         let store = unsafe { &mut *self.store() };
675         let table = &mut self
676             .tables
677             .get_mut(table_index)
678             .unwrap_or_else(|| panic!("no table for index {}", table_index.index()))
679             .1;
680 
681         let result = unsafe { table.grow(delta, init_value, store) };
682 
683         // Keep the `VMContext` pointers used by compiled Wasm code up to
684         // date.
685         let element = self.tables[table_index].1.vmtable();
686         self.set_table(table_index, element);
687 
688         result
689     }
690 
691     fn alloc_layout(offsets: &VMOffsets<HostPtr>) -> Layout {
692         let size = mem::size_of::<Self>()
693             .checked_add(usize::try_from(offsets.size_of_vmctx()).unwrap())
694             .unwrap();
695         let align = mem::align_of::<Self>();
696         Layout::from_size_align(size, align).unwrap()
697     }
698 
699     /// Construct a new VMFuncRef for the given function
700     /// (imported or defined in this module) and store into the given
701     /// location. Used during lazy initialization.
702     ///
703     /// Note that our current lazy-init scheme actually calls this every
704     /// time the funcref pointer is fetched; this turns out to be better
705     /// than tracking state related to whether it's been initialized
706     /// before, because resetting that state on (re)instantiation is
707     /// very expensive if there are many funcrefs.
708     fn construct_func_ref(
709         &mut self,
710         index: FuncIndex,
711         sig: ModuleInternedTypeIndex,
712         into: *mut VMFuncRef,
713     ) {
714         let type_index = unsafe {
715             let base: *const VMSharedTypeIndex =
716                 *self.vmctx_plus_offset_mut(self.offsets().vmctx_type_ids_array());
717             *base.add(sig.index())
718         };
719 
720         let func_ref = if let Some(def_index) = self.module().defined_func_index(index) {
721             VMFuncRef {
722                 native_call: self
723                     .runtime_info
724                     .native_to_wasm_trampoline(def_index)
725                     .expect("should have native-to-Wasm trampoline for escaping function"),
726                 array_call: self
727                     .runtime_info
728                     .array_to_wasm_trampoline(def_index)
729                     .expect("should have array-to-Wasm trampoline for escaping function"),
730                 wasm_call: Some(self.runtime_info.function(def_index)),
731                 vmctx: VMOpaqueContext::from_vmcontext(self.vmctx()),
732                 type_index,
733             }
734         } else {
735             let import = self.imported_function(index);
736             VMFuncRef {
737                 native_call: import.native_call,
738                 array_call: import.array_call,
739                 wasm_call: Some(import.wasm_call),
740                 vmctx: import.vmctx,
741                 type_index,
742             }
743         };
744 
745         // Safety: we have a `&mut self`, so we have exclusive access
746         // to this Instance.
747         unsafe {
748             ptr::write(into, func_ref);
749         }
750     }
751 
752     /// Get a `&VMFuncRef` for the given `FuncIndex`.
753     ///
754     /// Returns `None` if the index is the reserved index value.
755     ///
756     /// The returned reference is a stable reference that won't be moved and can
757     /// be passed into JIT code.
758     pub(crate) fn get_func_ref(&mut self, index: FuncIndex) -> Option<*mut VMFuncRef> {
759         if index == FuncIndex::reserved_value() {
760             return None;
761         }
762 
763         // Safety: we have a `&mut self`, so we have exclusive access
764         // to this Instance.
765         unsafe {
766             // For now, we eagerly initialize an funcref struct in-place
767             // whenever asked for a reference to it. This is mostly
768             // fine, because in practice each funcref is unlikely to be
769             // requested more than a few times: once-ish for funcref
770             // tables used for call_indirect (the usual compilation
771             // strategy places each function in the table at most once),
772             // and once or a few times when fetching exports via API.
773             // Note that for any case driven by table accesses, the lazy
774             // table init behaves like a higher-level cache layer that
775             // protects this initialization from happening multiple
776             // times, via that particular table at least.
777             //
778             // When `ref.func` becomes more commonly used or if we
779             // otherwise see a use-case where this becomes a hotpath,
780             // we can reconsider by using some state to track
781             // "uninitialized" explicitly, for example by zeroing the
782             // funcrefs (perhaps together with other
783             // zeroed-at-instantiate-time state) or using a separate
784             // is-initialized bitmap.
785             //
786             // We arrived at this design because zeroing memory is
787             // expensive, so it's better for instantiation performance
788             // if we don't have to track "is-initialized" state at
789             // all!
790             let func = &self.module().functions[index];
791             let sig = func.signature;
792             let func_ref: *mut VMFuncRef = self
793                 .vmctx_plus_offset_mut::<VMFuncRef>(self.offsets().vmctx_func_ref(func.func_ref));
794             self.construct_func_ref(index, sig, func_ref);
795 
796             Some(func_ref)
797         }
798     }
799 
800     /// The `table.init` operation: initializes a portion of a table with a
801     /// passive element.
802     ///
803     /// # Errors
804     ///
805     /// Returns a `Trap` error when the range within the table is out of bounds
806     /// or the range within the passive element is out of bounds.
807     pub(crate) fn table_init(
808         &mut self,
809         table_index: TableIndex,
810         elem_index: ElemIndex,
811         dst: u32,
812         src: u32,
813         len: u32,
814     ) -> Result<(), Trap> {
815         // TODO: this `clone()` shouldn't be necessary but is used for now to
816         // inform `rustc` that the lifetime of the elements here are
817         // disconnected from the lifetime of `self`.
818         let module = self.module().clone();
819 
820         // NB: fall back to an expressions-based list of elements which doesn't
821         // have static type information (as opposed to `Functions`) since we
822         // don't know just yet what type the table has. The type will be be
823         // inferred in the next step within `table_init_segment`.
824         let empty = TableSegmentElements::Expressions(Box::new([]));
825 
826         let elements = match module.passive_elements_map.get(&elem_index) {
827             Some(index) if !self.dropped_elements.contains(elem_index) => {
828                 &module.passive_elements[*index]
829             }
830             _ => &empty,
831         };
832         let mut const_evaluator = ConstExprEvaluator::default();
833         self.table_init_segment(&mut const_evaluator, table_index, elements, dst, src, len)
834     }
835 
836     pub(crate) fn table_init_segment(
837         &mut self,
838         const_evaluator: &mut ConstExprEvaluator,
839         table_index: TableIndex,
840         elements: &TableSegmentElements,
841         dst: u32,
842         src: u32,
843         len: u32,
844     ) -> Result<(), Trap> {
845         // https://webassembly.github.io/bulk-memory-operations/core/exec/instructions.html#exec-table-init
846 
847         let table = unsafe { &mut *self.get_table(table_index) };
848         let src = usize::try_from(src).map_err(|_| Trap::TableOutOfBounds)?;
849         let len = usize::try_from(len).map_err(|_| Trap::TableOutOfBounds)?;
850         let module = self.module().clone();
851 
852         match elements {
853             TableSegmentElements::Functions(funcs) => {
854                 let elements = funcs
855                     .get(src..)
856                     .and_then(|s| s.get(..len))
857                     .ok_or(Trap::TableOutOfBounds)?;
858                 table.init_func(
859                     dst,
860                     elements
861                         .iter()
862                         .map(|idx| self.get_func_ref(*idx).unwrap_or(ptr::null_mut())),
863                 )?;
864             }
865             TableSegmentElements::Expressions(exprs) => {
866                 let exprs = exprs
867                     .get(src..)
868                     .and_then(|s| s.get(..len))
869                     .ok_or(Trap::TableOutOfBounds)?;
870                 let mut context = ConstEvalContext::new(self, &module);
871                 match module.table_plans[table_index]
872                     .table
873                     .wasm_ty
874                     .heap_type
875                     .top()
876                 {
877                     WasmHeapTopType::Extern => table.init_gc_refs(
878                         dst,
879                         exprs.iter().map(|expr| unsafe {
880                             let raw = const_evaluator
881                                 .eval(&mut context, expr)
882                                 .expect("const expr should be valid");
883                             VMGcRef::from_raw_u32(raw.get_externref())
884                         }),
885                     )?,
886                     WasmHeapTopType::Any => table.init_gc_refs(
887                         dst,
888                         exprs.iter().map(|expr| unsafe {
889                             let raw = const_evaluator
890                                 .eval(&mut context, expr)
891                                 .expect("const expr should be valid");
892                             VMGcRef::from_raw_u32(raw.get_anyref())
893                         }),
894                     )?,
895                     WasmHeapTopType::Func => table.init_func(
896                         dst,
897                         exprs.iter().map(|expr| unsafe {
898                             const_evaluator
899                                 .eval(&mut context, expr)
900                                 .expect("const expr should be valid")
901                                 .get_funcref()
902                                 .cast()
903                         }),
904                     )?,
905                 }
906             }
907         }
908 
909         Ok(())
910     }
911 
912     /// Drop an element.
913     pub(crate) fn elem_drop(&mut self, elem_index: ElemIndex) {
914         // https://webassembly.github.io/reference-types/core/exec/instructions.html#exec-elem-drop
915 
916         self.dropped_elements.insert(elem_index);
917 
918         // Note that we don't check that we actually removed a segment because
919         // dropping a non-passive segment is a no-op (not a trap).
920     }
921 
922     /// Get a locally-defined memory.
923     pub fn get_defined_memory(&mut self, index: DefinedMemoryIndex) -> *mut Memory {
924         ptr::addr_of_mut!(self.memories[index].1)
925     }
926 
927     /// Do a `memory.copy`
928     ///
929     /// # Errors
930     ///
931     /// Returns a `Trap` error when the source or destination ranges are out of
932     /// bounds.
933     pub(crate) fn memory_copy(
934         &mut self,
935         dst_index: MemoryIndex,
936         dst: u64,
937         src_index: MemoryIndex,
938         src: u64,
939         len: u64,
940     ) -> Result<(), Trap> {
941         // https://webassembly.github.io/reference-types/core/exec/instructions.html#exec-memory-copy
942 
943         let src_mem = self.get_memory(src_index);
944         let dst_mem = self.get_memory(dst_index);
945 
946         let src = self.validate_inbounds(src_mem.current_length(), src, len)?;
947         let dst = self.validate_inbounds(dst_mem.current_length(), dst, len)?;
948 
949         // Bounds and casts are checked above, by this point we know that
950         // everything is safe.
951         unsafe {
952             let dst = dst_mem.base.add(dst);
953             let src = src_mem.base.add(src);
954             // FIXME audit whether this is safe in the presence of shared memory
955             // (https://github.com/bytecodealliance/wasmtime/issues/4203).
956             ptr::copy(src, dst, len as usize);
957         }
958 
959         Ok(())
960     }
961 
962     fn validate_inbounds(&self, max: usize, ptr: u64, len: u64) -> Result<usize, Trap> {
963         let oob = || Trap::MemoryOutOfBounds;
964         let end = ptr
965             .checked_add(len)
966             .and_then(|i| usize::try_from(i).ok())
967             .ok_or_else(oob)?;
968         if end > max {
969             Err(oob())
970         } else {
971             Ok(ptr as usize)
972         }
973     }
974 
975     /// Perform the `memory.fill` operation on a locally defined memory.
976     ///
977     /// # Errors
978     ///
979     /// Returns a `Trap` error if the memory range is out of bounds.
980     pub(crate) fn memory_fill(
981         &mut self,
982         memory_index: MemoryIndex,
983         dst: u64,
984         val: u8,
985         len: u64,
986     ) -> Result<(), Trap> {
987         let memory = self.get_memory(memory_index);
988         let dst = self.validate_inbounds(memory.current_length(), dst, len)?;
989 
990         // Bounds and casts are checked above, by this point we know that
991         // everything is safe.
992         unsafe {
993             let dst = memory.base.add(dst);
994             // FIXME audit whether this is safe in the presence of shared memory
995             // (https://github.com/bytecodealliance/wasmtime/issues/4203).
996             ptr::write_bytes(dst, val, len as usize);
997         }
998 
999         Ok(())
1000     }
1001 
1002     /// Performs the `memory.init` operation.
1003     ///
1004     /// # Errors
1005     ///
1006     /// Returns a `Trap` error if the destination range is out of this module's
1007     /// memory's bounds or if the source range is outside the data segment's
1008     /// bounds.
1009     pub(crate) fn memory_init(
1010         &mut self,
1011         memory_index: MemoryIndex,
1012         data_index: DataIndex,
1013         dst: u64,
1014         src: u32,
1015         len: u32,
1016     ) -> Result<(), Trap> {
1017         let range = match self.module().passive_data_map.get(&data_index).cloned() {
1018             Some(range) if !self.dropped_data.contains(data_index) => range,
1019             _ => 0..0,
1020         };
1021         self.memory_init_segment(memory_index, range, dst, src, len)
1022     }
1023 
1024     pub(crate) fn wasm_data(&self, range: Range<u32>) -> &[u8] {
1025         &self.runtime_info.wasm_data()[range.start as usize..range.end as usize]
1026     }
1027 
1028     pub(crate) fn memory_init_segment(
1029         &mut self,
1030         memory_index: MemoryIndex,
1031         range: Range<u32>,
1032         dst: u64,
1033         src: u32,
1034         len: u32,
1035     ) -> Result<(), Trap> {
1036         // https://webassembly.github.io/bulk-memory-operations/core/exec/instructions.html#exec-memory-init
1037 
1038         let memory = self.get_memory(memory_index);
1039         let data = self.wasm_data(range);
1040         let dst = self.validate_inbounds(memory.current_length(), dst, len.into())?;
1041         let src = self.validate_inbounds(data.len(), src.into(), len.into())?;
1042         let len = len as usize;
1043 
1044         unsafe {
1045             let src_start = data.as_ptr().add(src);
1046             let dst_start = memory.base.add(dst);
1047             // FIXME audit whether this is safe in the presence of shared memory
1048             // (https://github.com/bytecodealliance/wasmtime/issues/4203).
1049             ptr::copy_nonoverlapping(src_start, dst_start, len);
1050         }
1051 
1052         Ok(())
1053     }
1054 
1055     /// Drop the given data segment, truncating its length to zero.
1056     pub(crate) fn data_drop(&mut self, data_index: DataIndex) {
1057         self.dropped_data.insert(data_index);
1058 
1059         // Note that we don't check that we actually removed a segment because
1060         // dropping a non-passive segment is a no-op (not a trap).
1061     }
1062 
1063     /// Get a table by index regardless of whether it is locally-defined
1064     /// or an imported, foreign table. Ensure that the given range of
1065     /// elements in the table is lazily initialized.  We define this
1066     /// operation all-in-one for safety, to ensure the lazy-init
1067     /// happens.
1068     ///
1069     /// Takes an `Iterator` for the index-range to lazy-initialize,
1070     /// for flexibility. This can be a range, single item, or empty
1071     /// sequence, for example. The iterator should return indices in
1072     /// increasing order, so that the break-at-out-of-bounds behavior
1073     /// works correctly.
1074     pub(crate) fn get_table_with_lazy_init(
1075         &mut self,
1076         table_index: TableIndex,
1077         range: impl Iterator<Item = u32>,
1078     ) -> *mut Table {
1079         self.with_defined_table_index_and_instance(table_index, |idx, instance| {
1080             instance.get_defined_table_with_lazy_init(idx, range)
1081         })
1082     }
1083 
1084     /// Gets the raw runtime table data structure owned by this instance
1085     /// given the provided `idx`.
1086     ///
1087     /// The `range` specified is eagerly initialized for funcref tables.
1088     pub fn get_defined_table_with_lazy_init(
1089         &mut self,
1090         idx: DefinedTableIndex,
1091         range: impl Iterator<Item = u32>,
1092     ) -> *mut Table {
1093         let elt_ty = self.tables[idx].1.element_type();
1094 
1095         if elt_ty == TableElementType::Func {
1096             for i in range {
1097                 let gc_store = unsafe { (*self.store()).gc_store() };
1098                 let value = match self.tables[idx].1.get(gc_store, i) {
1099                     Some(value) => value,
1100                     None => {
1101                         // Out-of-bounds; caller will handle by likely
1102                         // throwing a trap. No work to do to lazy-init
1103                         // beyond the end.
1104                         break;
1105                     }
1106                 };
1107 
1108                 if !value.is_uninit() {
1109                     continue;
1110                 }
1111 
1112                 // The table element `i` is uninitialized and is now being
1113                 // initialized. This must imply that a `precompiled` list of
1114                 // function indices is available for this table. The precompiled
1115                 // list is extracted and then it is consulted with `i` to
1116                 // determine the function that is going to be initialized. Note
1117                 // that `i` may be outside the limits of the static
1118                 // initialization so it's a fallible `get` instead of an index.
1119                 let module = self.module();
1120                 let precomputed = match &module.table_initialization.initial_values[idx] {
1121                     TableInitialValue::Null { precomputed } => precomputed,
1122                     TableInitialValue::Expr(_) => unreachable!(),
1123                 };
1124                 let func_index = precomputed.get(i as usize).cloned();
1125                 let func_ref = func_index
1126                     .and_then(|func_index| self.get_func_ref(func_index))
1127                     .unwrap_or(ptr::null_mut());
1128                 self.tables[idx]
1129                     .1
1130                     .set(i, TableElement::FuncRef(func_ref))
1131                     .expect("Table type should match and index should be in-bounds");
1132             }
1133         }
1134 
1135         ptr::addr_of_mut!(self.tables[idx].1)
1136     }
1137 
1138     /// Get a table by index regardless of whether it is locally-defined or an
1139     /// imported, foreign table.
1140     pub(crate) fn get_table(&mut self, table_index: TableIndex) -> *mut Table {
1141         self.with_defined_table_index_and_instance(table_index, |idx, instance| {
1142             ptr::addr_of_mut!(instance.tables[idx].1)
1143         })
1144     }
1145 
1146     /// Get a locally-defined table.
1147     pub(crate) fn get_defined_table(&mut self, index: DefinedTableIndex) -> *mut Table {
1148         ptr::addr_of_mut!(self.tables[index].1)
1149     }
1150 
1151     pub(crate) fn with_defined_table_index_and_instance<R>(
1152         &mut self,
1153         index: TableIndex,
1154         f: impl FnOnce(DefinedTableIndex, &mut Instance) -> R,
1155     ) -> R {
1156         if let Some(defined_table_index) = self.module().defined_table_index(index) {
1157             f(defined_table_index, self)
1158         } else {
1159             let import = self.imported_table(index);
1160             unsafe {
1161                 Instance::from_vmctx(import.vmctx, |foreign_instance| {
1162                     let foreign_table_def = import.from;
1163                     let foreign_table_index = foreign_instance.table_index(&*foreign_table_def);
1164                     f(foreign_table_index, foreign_instance)
1165                 })
1166             }
1167         }
1168     }
1169 
1170     /// Initialize the VMContext data associated with this Instance.
1171     ///
1172     /// The `VMContext` memory is assumed to be uninitialized; any field
1173     /// that we need in a certain state will be explicitly written by this
1174     /// function.
1175     unsafe fn initialize_vmctx(
1176         &mut self,
1177         module: &Module,
1178         offsets: &VMOffsets<HostPtr>,
1179         store: StorePtr,
1180         imports: Imports,
1181     ) {
1182         assert!(ptr::eq(module, self.module().as_ref()));
1183 
1184         *self.vmctx_plus_offset_mut(offsets.vmctx_magic()) = VMCONTEXT_MAGIC;
1185         self.set_callee(None);
1186         self.set_store(store.as_raw());
1187 
1188         // Initialize shared types
1189         let types = self.runtime_info.type_ids();
1190         *self.vmctx_plus_offset_mut(offsets.vmctx_type_ids_array()) = types.as_ptr();
1191 
1192         // Initialize the built-in functions
1193         *self.vmctx_plus_offset_mut(offsets.vmctx_builtin_functions()) =
1194             &VMBuiltinFunctionsArray::INIT;
1195 
1196         // Initialize the imports
1197         debug_assert_eq!(imports.functions.len(), module.num_imported_funcs);
1198         ptr::copy_nonoverlapping(
1199             imports.functions.as_ptr(),
1200             self.vmctx_plus_offset_mut(offsets.vmctx_imported_functions_begin()),
1201             imports.functions.len(),
1202         );
1203         debug_assert_eq!(imports.tables.len(), module.num_imported_tables);
1204         ptr::copy_nonoverlapping(
1205             imports.tables.as_ptr(),
1206             self.vmctx_plus_offset_mut(offsets.vmctx_imported_tables_begin()),
1207             imports.tables.len(),
1208         );
1209         debug_assert_eq!(imports.memories.len(), module.num_imported_memories);
1210         ptr::copy_nonoverlapping(
1211             imports.memories.as_ptr(),
1212             self.vmctx_plus_offset_mut(offsets.vmctx_imported_memories_begin()),
1213             imports.memories.len(),
1214         );
1215         debug_assert_eq!(imports.globals.len(), module.num_imported_globals);
1216         ptr::copy_nonoverlapping(
1217             imports.globals.as_ptr(),
1218             self.vmctx_plus_offset_mut(offsets.vmctx_imported_globals_begin()),
1219             imports.globals.len(),
1220         );
1221 
1222         // N.B.: there is no need to initialize the funcrefs array because we
1223         // eagerly construct each element in it whenever asked for a reference
1224         // to that element. In other words, there is no state needed to track
1225         // the lazy-init, so we don't need to initialize any state now.
1226 
1227         // Initialize the defined tables
1228         let mut ptr = self.vmctx_plus_offset_mut(offsets.vmctx_tables_begin());
1229         for i in 0..module.table_plans.len() - module.num_imported_tables {
1230             ptr::write(ptr, self.tables[DefinedTableIndex::new(i)].1.vmtable());
1231             ptr = ptr.add(1);
1232         }
1233 
1234         // Initialize the defined memories. This fills in both the
1235         // `defined_memories` table and the `owned_memories` table at the same
1236         // time. Entries in `defined_memories` hold a pointer to a definition
1237         // (all memories) whereas the `owned_memories` hold the actual
1238         // definitions of memories owned (not shared) in the module.
1239         let mut ptr = self.vmctx_plus_offset_mut(offsets.vmctx_memories_begin());
1240         let mut owned_ptr = self.vmctx_plus_offset_mut(offsets.vmctx_owned_memories_begin());
1241         for i in 0..module.memory_plans.len() - module.num_imported_memories {
1242             let defined_memory_index = DefinedMemoryIndex::new(i);
1243             let memory_index = module.memory_index(defined_memory_index);
1244             if module.memory_plans[memory_index].memory.shared {
1245                 let def_ptr = self.memories[defined_memory_index]
1246                     .1
1247                     .as_shared_memory()
1248                     .unwrap()
1249                     .vmmemory_ptr();
1250                 ptr::write(ptr, def_ptr.cast_mut());
1251             } else {
1252                 ptr::write(owned_ptr, self.memories[defined_memory_index].1.vmmemory());
1253                 ptr::write(ptr, owned_ptr);
1254                 owned_ptr = owned_ptr.add(1);
1255             }
1256             ptr = ptr.add(1);
1257         }
1258 
1259         // Initialize the defined globals
1260         let mut const_evaluator = ConstExprEvaluator::default();
1261         self.initialize_vmctx_globals(&mut const_evaluator, module);
1262     }
1263 
1264     unsafe fn initialize_vmctx_globals(
1265         &mut self,
1266         const_evaluator: &mut ConstExprEvaluator,
1267         module: &Module,
1268     ) {
1269         for (index, init) in module.global_initializers.iter() {
1270             let mut context = ConstEvalContext::new(self, module);
1271             let raw = const_evaluator
1272                 .eval(&mut context, init)
1273                 .expect("should be a valid const expr");
1274 
1275             let to = self.global_ptr(index);
1276             let wasm_ty = module.globals[module.global_index(index)].wasm_ty;
1277 
1278             #[cfg(feature = "wmemcheck")]
1279             if index.index() == 0 && wasm_ty == wasmtime_environ::WasmValType::I32 {
1280                 if let Some(wmemcheck) = &mut self.wmemcheck_state {
1281                     let size = usize::try_from(raw.get_i32()).unwrap();
1282                     wmemcheck.set_stack_size(size);
1283                 }
1284             }
1285 
1286             ptr::write(to, VMGlobalDefinition::from_val_raw(wasm_ty, raw));
1287         }
1288     }
1289 
1290     fn wasm_fault(&self, addr: usize) -> Option<WasmFault> {
1291         let mut fault = None;
1292         for (_, (_, memory)) in self.memories.iter() {
1293             let accessible = memory.wasm_accessible();
1294             if accessible.start <= addr && addr < accessible.end {
1295                 // All linear memories should be disjoint so assert that no
1296                 // prior fault has been found.
1297                 assert!(fault.is_none());
1298                 fault = Some(WasmFault {
1299                     memory_size: memory.byte_size(),
1300                     wasm_address: u64::try_from(addr - accessible.start).unwrap(),
1301                 });
1302             }
1303         }
1304         fault
1305     }
1306 }
1307 
1308 /// A handle holding an `Instance` of a WebAssembly module.
1309 #[derive(Debug)]
1310 pub struct InstanceHandle {
1311     instance: Option<SendSyncPtr<Instance>>,
1312 }
1313 
1314 impl InstanceHandle {
1315     /// Creates an "empty" instance handle which internally has a null pointer
1316     /// to an instance.
1317     pub fn null() -> InstanceHandle {
1318         InstanceHandle { instance: None }
1319     }
1320 
1321     /// Return a raw pointer to the vmctx used by compiled wasm code.
1322     #[inline]
1323     pub fn vmctx(&self) -> *mut VMContext {
1324         self.instance().vmctx()
1325     }
1326 
1327     /// Return a reference to a module.
1328     pub fn module(&self) -> &Arc<Module> {
1329         self.instance().module()
1330     }
1331 
1332     /// Lookup a function by index.
1333     pub fn get_exported_func(&mut self, export: FuncIndex) -> ExportFunction {
1334         self.instance_mut().get_exported_func(export)
1335     }
1336 
1337     /// Lookup a global by index.
1338     pub fn get_exported_global(&mut self, export: GlobalIndex) -> ExportGlobal {
1339         self.instance_mut().get_exported_global(export)
1340     }
1341 
1342     /// Lookup a memory by index.
1343     pub fn get_exported_memory(&mut self, export: MemoryIndex) -> ExportMemory {
1344         self.instance_mut().get_exported_memory(export)
1345     }
1346 
1347     /// Lookup a table by index.
1348     pub fn get_exported_table(&mut self, export: TableIndex) -> ExportTable {
1349         self.instance_mut().get_exported_table(export)
1350     }
1351 
1352     /// Lookup an item with the given index.
1353     pub fn get_export_by_index(&mut self, export: EntityIndex) -> Export {
1354         match export {
1355             EntityIndex::Function(i) => Export::Function(self.get_exported_func(i)),
1356             EntityIndex::Global(i) => Export::Global(self.get_exported_global(i)),
1357             EntityIndex::Table(i) => Export::Table(self.get_exported_table(i)),
1358             EntityIndex::Memory(i) => Export::Memory(self.get_exported_memory(i)),
1359         }
1360     }
1361 
1362     /// Return an iterator over the exports of this instance.
1363     ///
1364     /// Specifically, it provides access to the key-value pairs, where the keys
1365     /// are export names, and the values are export declarations which can be
1366     /// resolved `lookup_by_declaration`.
1367     pub fn exports(&self) -> indexmap::map::Iter<String, EntityIndex> {
1368         self.instance().exports()
1369     }
1370 
1371     /// Return a reference to the custom state attached to this instance.
1372     pub fn host_state(&self) -> &dyn Any {
1373         self.instance().host_state()
1374     }
1375 
1376     /// Get a table defined locally within this module.
1377     pub fn get_defined_table(&mut self, index: DefinedTableIndex) -> *mut Table {
1378         self.instance_mut().get_defined_table(index)
1379     }
1380 
1381     /// Get a table defined locally within this module, lazily
1382     /// initializing the given range first.
1383     pub fn get_defined_table_with_lazy_init(
1384         &mut self,
1385         index: DefinedTableIndex,
1386         range: impl Iterator<Item = u32>,
1387     ) -> *mut Table {
1388         let index = self.instance().module().table_index(index);
1389         self.instance_mut().get_table_with_lazy_init(index, range)
1390     }
1391 
1392     /// Get all tables within this instance.
1393     ///
1394     /// Returns both import and defined tables.
1395     ///
1396     /// Returns both exported and non-exported tables.
1397     ///
1398     /// Gives access to the full tables space.
1399     pub fn all_tables<'a>(
1400         &'a mut self,
1401     ) -> impl ExactSizeIterator<Item = (TableIndex, ExportTable)> + 'a {
1402         let indices = (0..self.module().table_plans.len())
1403             .map(|i| TableIndex::new(i))
1404             .collect::<Vec<_>>();
1405         indices.into_iter().map(|i| (i, self.get_exported_table(i)))
1406     }
1407 
1408     /// Return the tables defined in this instance (not imported).
1409     pub fn defined_tables<'a>(&'a mut self) -> impl ExactSizeIterator<Item = ExportTable> + 'a {
1410         let num_imported = self.module().num_imported_tables;
1411         self.all_tables()
1412             .skip(num_imported)
1413             .map(|(_i, table)| table)
1414     }
1415 
1416     /// Get all memories within this instance.
1417     ///
1418     /// Returns both import and defined memories.
1419     ///
1420     /// Returns both exported and non-exported memories.
1421     ///
1422     /// Gives access to the full memories space.
1423     pub fn all_memories<'a>(
1424         &'a mut self,
1425     ) -> impl ExactSizeIterator<Item = (MemoryIndex, ExportMemory)> + 'a {
1426         let indices = (0..self.module().memory_plans.len())
1427             .map(|i| MemoryIndex::new(i))
1428             .collect::<Vec<_>>();
1429         indices
1430             .into_iter()
1431             .map(|i| (i, self.get_exported_memory(i)))
1432     }
1433 
1434     /// Return the memories defined in this instance (not imported).
1435     pub fn defined_memories<'a>(&'a mut self) -> impl ExactSizeIterator<Item = ExportMemory> + 'a {
1436         let num_imported = self.module().num_imported_memories;
1437         self.all_memories()
1438             .skip(num_imported)
1439             .map(|(_i, memory)| memory)
1440     }
1441 
1442     /// Get all globals within this instance.
1443     ///
1444     /// Returns both import and defined globals.
1445     ///
1446     /// Returns both exported and non-exported globals.
1447     ///
1448     /// Gives access to the full globals space.
1449     pub fn all_globals<'a>(
1450         &'a mut self,
1451     ) -> impl ExactSizeIterator<Item = (GlobalIndex, ExportGlobal)> + 'a {
1452         self.instance_mut().all_globals()
1453     }
1454 
1455     /// Get the globals defined in this instance (not imported).
1456     pub fn defined_globals<'a>(
1457         &'a mut self,
1458     ) -> impl ExactSizeIterator<Item = (DefinedGlobalIndex, ExportGlobal)> + 'a {
1459         self.instance_mut().defined_globals()
1460     }
1461 
1462     /// Return a reference to the contained `Instance`.
1463     #[inline]
1464     pub(crate) fn instance(&self) -> &Instance {
1465         unsafe { &*self.instance.unwrap().as_ptr() }
1466     }
1467 
1468     pub(crate) fn instance_mut(&mut self) -> &mut Instance {
1469         unsafe { &mut *self.instance.unwrap().as_ptr() }
1470     }
1471 
1472     /// Returns the `Store` pointer that was stored on creation
1473     #[inline]
1474     pub fn store(&self) -> *mut dyn Store {
1475         self.instance().store()
1476     }
1477 
1478     /// Configure the `*mut dyn Store` internal pointer after-the-fact.
1479     ///
1480     /// This is provided for the original `Store` itself to configure the first
1481     /// self-pointer after the original `Box` has been initialized.
1482     pub unsafe fn set_store(&mut self, store: *mut dyn Store) {
1483         self.instance_mut().set_store(Some(store));
1484     }
1485 
1486     /// Returns a clone of this instance.
1487     ///
1488     /// This is unsafe because the returned handle here is just a cheap clone
1489     /// of the internals, there's no lifetime tracking around its validity.
1490     /// You'll need to ensure that the returned handles all go out of scope at
1491     /// the same time.
1492     #[inline]
1493     pub unsafe fn clone(&self) -> InstanceHandle {
1494         InstanceHandle {
1495             instance: self.instance,
1496         }
1497     }
1498 
1499     /// Performs post-initialization of an instance after its handle has been
1500     /// created and registered with a store.
1501     ///
1502     /// Failure of this function means that the instance still must persist
1503     /// within the store since failure may indicate partial failure, or some
1504     /// state could be referenced by other instances.
1505     pub fn initialize(&mut self, module: &Module, is_bulk_memory: bool) -> Result<()> {
1506         allocator::initialize_instance(self.instance_mut(), module, is_bulk_memory)
1507     }
1508 
1509     /// Attempts to convert from the host `addr` specified to a WebAssembly
1510     /// based address recorded in `WasmFault`.
1511     ///
1512     /// This method will check all linear memories that this instance contains
1513     /// to see if any of them contain `addr`. If one does then `Some` is
1514     /// returned with metadata about the wasm fault. Otherwise `None` is
1515     /// returned and `addr` doesn't belong to this instance.
1516     pub fn wasm_fault(&self, addr: usize) -> Option<WasmFault> {
1517         self.instance().wasm_fault(addr)
1518     }
1519 }
1520