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