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