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