1 //! Runtime support for the component model in Wasmtime
2 //!
3 //! Currently this runtime support includes a `VMComponentContext` which is
4 //! similar in purpose to `VMContext`. The context is read from
5 //! cranelift-generated trampolines when entering the host from a wasm module.
6 //! Eventually it's intended that module-to-module calls, which would be
7 //! cranelift-compiled adapters, will use this `VMComponentContext` as well.
8 
9 use crate::component::{Component, Instance, InstancePre, ResourceType, RuntimeImport};
10 use crate::module::ModuleRegistry;
11 use crate::runtime::component::ComponentInstanceId;
12 #[cfg(feature = "component-model-async")]
13 use crate::runtime::component::concurrent::ConcurrentInstanceState;
14 use crate::runtime::vm::instance::{InstanceLayout, OwnedInstance, OwnedVMContext};
15 use crate::runtime::vm::vmcontext::VMFunctionBody;
16 use crate::runtime::vm::{
17     HostResult, SendSyncPtr, VMArrayCallFunction, VMFuncRef, VMGlobalDefinition,
18     VMMemoryDefinition, VMOpaqueContext, VMStore, VMStoreRawPtr, VMTableImport, VMWasmCallFunction,
19     ValRaw, VmPtr, VmSafe, catch_unwind_and_record_trap,
20 };
21 use crate::store::InstanceId;
22 use crate::{Func, vm};
23 use alloc::alloc::Layout;
24 use alloc::sync::Arc;
25 use anyhow::Result;
26 use core::mem;
27 use core::mem::offset_of;
28 use core::pin::Pin;
29 use core::ptr::NonNull;
30 use wasmtime_environ::component::*;
31 use wasmtime_environ::{HostPtr, PrimaryMap, VMSharedTypeIndex};
32 
33 #[allow(
34     clippy::cast_possible_truncation,
35     reason = "it's intended this is truncated on 32-bit platforms"
36 )]
37 const INVALID_PTR: usize = 0xdead_dead_beef_beef_u64 as usize;
38 
39 mod handle_table;
40 mod libcalls;
41 mod resources;
42 
43 pub use self::handle_table::{HandleTable, RemovedResource};
44 #[cfg(feature = "component-model-async")]
45 pub use self::handle_table::{TransmitLocalState, Waitable};
46 #[cfg(feature = "component-model-async")]
47 pub use self::resources::CallContext;
48 pub use self::resources::{CallContexts, ResourceTables, TypedResource, TypedResourceIndex};
49 
50 /// Represents the state of a (sub-)component instance.
51 #[derive(Default)]
52 pub struct InstanceState {
53     /// Represents the Component Model Async state of a (sub-)component instance.
54     #[cfg(feature = "component-model-async")]
55     concurrent_state: ConcurrentInstanceState,
56 
57     /// State of handles (e.g. resources, waitables, etc.) for this instance.
58     ///
59     /// For resource handles, this is paired with other information to create a
60     /// `ResourceTables` and manipulated through that.  For other handles, this
61     /// is used directly to translate guest handles to host representations and
62     /// vice-versa.
63     handle_table: HandleTable,
64 }
65 
66 impl InstanceState {
67     /// Represents the Component Model Async state of a (sub-)component instance.
68     #[cfg(feature = "component-model-async")]
69     pub fn concurrent_state(&mut self) -> &mut ConcurrentInstanceState {
70         &mut self.concurrent_state
71     }
72 
73     /// State of handles (e.g. resources, waitables, etc.) for this instance.
74     pub fn handle_table(&mut self) -> &mut HandleTable {
75         &mut self.handle_table
76     }
77 }
78 
79 /// Runtime representation of a component instance and all state necessary for
80 /// the instance itself.
81 ///
82 /// This type never exists by-value, but rather it's always behind a pointer.
83 /// The size of the allocation for `ComponentInstance` includes the trailing
84 /// `VMComponentContext` which is variably sized based on the `offsets`
85 /// contained within.
86 ///
87 /// # Pin
88 ///
89 /// Note that this type is mutated through `Pin<&mut ComponentInstance>` in the
90 /// same manner as `vm::Instance` for core modules, and see more information
91 /// over there for documentation and rationale.
92 #[repr(C)]
93 pub struct ComponentInstance {
94     /// The index within the store of where to find this component instance.
95     id: ComponentInstanceId,
96 
97     /// Size and offset information for the trailing `VMComponentContext`.
98     offsets: VMComponentOffsets<HostPtr>,
99 
100     /// The component that this instance was created from.
101     //
102     // NB: in the future if necessary it would be possible to avoid storing an
103     // entire `Component` here and instead storing only information such as:
104     //
105     // * Some reference to `Arc<ComponentTypes>`
106     // * Necessary references to closed-over modules which are exported from the
107     //   component itself.
108     //
109     // Otherwise the full guts of this component should only ever be used during
110     // the instantiation of this instance, meaning that after instantiation much
111     // of the component can be thrown away (theoretically).
112     //
113     // SAFETY: this field cannot be overwritten after an instance is created. It
114     // must contain this exact same value for the entire lifetime of this
115     // instance. This enables borrowing the component and this instance at the
116     // same time (instance mutably, component not). Additionally it enables
117     // borrowing a store mutably at the same time as a contained instance.
118     component: Component,
119 
120     /// Contains state specific to each (sub-)component instance within this
121     /// top-level instance.
122     instance_states: PrimaryMap<RuntimeComponentInstanceIndex, InstanceState>,
123 
124     /// What all compile-time-identified core instances are mapped to within the
125     /// `Store` that this component belongs to.
126     instances: PrimaryMap<RuntimeInstanceIndex, InstanceId>,
127 
128     /// Storage for the type information about resources within this component
129     /// instance.
130     resource_types: Arc<PrimaryMap<ResourceIndex, ResourceType>>,
131 
132     /// Arguments that this instance used to be instantiated.
133     ///
134     /// Strong references are stored to these arguments since pointers are saved
135     /// into the structures such as functions within the
136     /// `OwnedComponentInstance` but it's our job to keep them alive.
137     ///
138     /// One purpose of this storage is to enable embedders to drop a `Linker`,
139     /// for example, after a component is instantiated. In that situation if the
140     /// arguments weren't held here then they might be dropped, and structures
141     /// such as `.lowering()` which point back into the original function would
142     /// become stale and use-after-free conditions when used. By preserving the
143     /// entire list here though we're guaranteed that nothing is lost for the
144     /// duration of the lifetime of this instance.
145     imports: Arc<PrimaryMap<RuntimeImportIndex, RuntimeImport>>,
146 
147     /// Self-pointer back to `Store<T>` and its functions.
148     store: VMStoreRawPtr,
149 
150     /// Cached ABI return value from the last-invoked function call along with
151     /// the function index that was invoked.
152     ///
153     /// Used in `post_return_arg_set` and `post_return_arg_take` below.
154     post_return_arg: Option<(ExportIndex, ValRaw)>,
155 
156     /// Required by `InstanceLayout`, also required to be the last field (with
157     /// repr(C))
158     vmctx: OwnedVMContext<VMComponentContext>,
159 }
160 
161 /// Type signature for host-defined trampolines that are called from
162 /// WebAssembly.
163 ///
164 /// This function signature is invoked from a cranelift-compiled trampoline that
165 /// adapts from the core wasm System-V ABI into the ABI provided here:
166 ///
167 /// * `vmctx` - this is the first argument to the wasm import, and should always
168 ///   end up being a `VMComponentContext`.
169 /// * `data` - this is the data pointer associated with the `VMLowering` for
170 ///   which this function pointer was registered.
171 /// * `ty` - the type index, relative to the tables in `vmctx`, that is the
172 ///   type of the function being called.
173 /// * `options` - the `OptionsIndex` which indicates the canonical ABI options
174 ///   in use for this call.
175 /// * `args_and_results` - pointer to stack-allocated space in the caller where
176 ///   all the arguments are stored as well as where the results will be written
177 ///   to. The size and initialized bytes of this depends on the core wasm type
178 ///   signature that this callee corresponds to.
179 /// * `nargs_and_results` - the size, in units of `ValRaw`, of
180 ///   `args_and_results`.
181 ///
182 /// This function returns a `bool` which indicates whether the call succeeded
183 /// or not. On failure this function records trap information in TLS which
184 /// should be suitable for reading later.
185 pub type VMLoweringCallee = unsafe extern "C" fn(
186     vmctx: NonNull<VMOpaqueContext>,
187     data: NonNull<u8>,
188     ty: u32,
189     options: u32,
190     args_and_results: NonNull<mem::MaybeUninit<ValRaw>>,
191     nargs_and_results: usize,
192 ) -> bool;
193 
194 /// An opaque function pointer which is a `VMLoweringFunction` under the hood
195 /// but this is stored as `VMPtr<VMLoweringFunction>` within `VMLowering` below
196 /// to handle provenance correctly when using Pulley.
197 #[repr(transparent)]
198 pub struct VMLoweringFunction(VMFunctionBody);
199 
200 /// Structure describing a lowered host function stored within a
201 /// `VMComponentContext` per-lowering.
202 #[derive(Copy, Clone)]
203 #[repr(C)]
204 pub struct VMLowering {
205     /// The host function pointer that is invoked when this lowering is
206     /// invoked.
207     pub callee: VmPtr<VMLoweringFunction>,
208     /// The host data pointer (think void* pointer) to get passed to `callee`.
209     pub data: VmPtr<u8>,
210 }
211 
212 // SAFETY: the above structure is repr(C) and only contains `VmSafe` fields.
213 unsafe impl VmSafe for VMLowering {}
214 
215 /// This is a marker type to represent the underlying allocation of a
216 /// `VMComponentContext`.
217 ///
218 /// This type is similar to `VMContext` for core wasm and is allocated once per
219 /// component instance in Wasmtime. While the static size of this type is 0 the
220 /// actual runtime size is variable depending on the shape of the component that
221 /// this corresponds to. This structure always trails a `ComponentInstance`
222 /// allocation and the allocation/lifetime of this allocation is managed by
223 /// `ComponentInstance`.
224 #[repr(C)]
225 // Set an appropriate alignment for this structure where the most-aligned value
226 // internally right now `VMGlobalDefinition` which has an alignment of 16 bytes.
227 #[repr(align(16))]
228 pub struct VMComponentContext;
229 
230 impl ComponentInstance {
231     /// Converts the `vmctx` provided into a `ComponentInstance` and runs the
232     /// provided closure with that instance.
233     ///
234     /// This function will also catch any failures that `f` produces and returns
235     /// an appropriate ABI value to return to wasm. This includes normal errors
236     /// such as traps as well as Rust-side panics which require wasm to unwind.
237     ///
238     /// # Unsafety
239     ///
240     /// This is `unsafe` because `vmctx` cannot be guaranteed to be a valid
241     /// pointer and it cannot be proven statically that it's safe to get a
242     /// mutable reference at this time to the instance from `vmctx`. Note that
243     /// it must be also safe to borrow the store mutably, meaning it can't
244     /// already be in use elsewhere.
245     pub unsafe fn enter_host_from_wasm<R>(
246         vmctx: NonNull<VMComponentContext>,
247         f: impl FnOnce(&mut dyn VMStore, Instance) -> R,
248     ) -> R::Abi
249     where
250         R: HostResult,
251     {
252         // SAFETY: it's a contract of this function that `vmctx` is a valid
253         // allocation which can go backwards to a `ComponentInstance`.
254         let mut ptr = unsafe { Self::from_vmctx(vmctx) };
255 
256         // SAFETY: it's a contract of this function that it's safe to use `ptr`
257         // as a mutable reference.
258         let reference = unsafe { ptr.as_mut() };
259 
260         // SAFETY: it's a contract of this function that it's safe to use the
261         // store mutably at this time.
262         let store = unsafe { &mut *reference.store.0.as_ptr() };
263 
264         let instance = Instance::from_wasmtime(store, reference.id);
265         catch_unwind_and_record_trap(store, |store| f(store, instance))
266     }
267 
268     /// Returns the `InstanceId` associated with the `vmctx` provided.
269     ///
270     /// # Safety
271     ///
272     /// The `vmctx` pointer must be a valid pointer and allocation within a
273     /// `ComponentInstance`. See `Instance::from_vmctx` for some more
274     /// information.
275     unsafe fn from_vmctx(vmctx: NonNull<VMComponentContext>) -> NonNull<ComponentInstance> {
276         // SAFETY: it's a contract of this function that `vmctx` is a valid
277         // pointer to do this pointer arithmetic on.
278         unsafe {
279             vmctx
280                 .byte_sub(mem::size_of::<ComponentInstance>())
281                 .cast::<ComponentInstance>()
282         }
283     }
284 
285     /// Returns the `InstanceId` associated with the `vmctx` provided.
286     ///
287     /// # Safety
288     ///
289     /// The `vmctx` pointer must be a valid pointer to read the
290     /// `ComponentInstanceId` from.
291     pub(crate) unsafe fn vmctx_instance_id(
292         vmctx: NonNull<VMComponentContext>,
293     ) -> ComponentInstanceId {
294         // SAFETY: it's a contract of this function that `vmctx` is a valid
295         // pointer with a `ComponentInstance` in front which can be read.
296         unsafe { Self::from_vmctx(vmctx).as_ref().id }
297     }
298 
299     /// Returns the layout corresponding to what would be an allocation of a
300     /// `ComponentInstance` for the `offsets` provided.
301     ///
302     /// The returned layout has space for both the `ComponentInstance` and the
303     /// trailing `VMComponentContext`.
304     fn alloc_layout(offsets: &VMComponentOffsets<HostPtr>) -> Layout {
305         let size = mem::size_of::<Self>()
306             .checked_add(usize::try_from(offsets.size_of_vmctx()).unwrap())
307             .unwrap();
308         let align = mem::align_of::<Self>();
309         Layout::from_size_align(size, align).unwrap()
310     }
311 
312     /// Allocates a new `ComponentInstance + VMComponentContext` pair on the
313     /// heap with `malloc` and configures it for the `component` specified.
314     pub(crate) fn new(
315         id: ComponentInstanceId,
316         component: &Component,
317         resource_types: Arc<PrimaryMap<ResourceIndex, ResourceType>>,
318         imports: &Arc<PrimaryMap<RuntimeImportIndex, RuntimeImport>>,
319         store: NonNull<dyn VMStore>,
320     ) -> OwnedComponentInstance {
321         let offsets = VMComponentOffsets::new(HostPtr, component.env_component());
322         let num_instances = component.env_component().num_runtime_component_instances;
323         let mut instance_states = PrimaryMap::with_capacity(num_instances.try_into().unwrap());
324         for _ in 0..num_instances {
325             instance_states.push(InstanceState::default());
326         }
327 
328         let mut ret = OwnedInstance::new(ComponentInstance {
329             id,
330             offsets,
331             instance_states,
332             instances: PrimaryMap::with_capacity(
333                 component
334                     .env_component()
335                     .num_runtime_instances
336                     .try_into()
337                     .unwrap(),
338             ),
339             component: component.clone(),
340             resource_types,
341             imports: imports.clone(),
342             store: VMStoreRawPtr(store),
343             post_return_arg: None,
344             vmctx: OwnedVMContext::new(),
345         });
346         unsafe {
347             ret.get_mut().initialize_vmctx();
348         }
349         ret
350     }
351 
352     #[inline]
353     pub fn vmctx(&self) -> NonNull<VMComponentContext> {
354         InstanceLayout::vmctx(self)
355     }
356 
357     /// Returns a pointer to the "may leave" flag for this instance specified
358     /// for canonical lowering and lifting operations.
359     #[inline]
360     pub fn instance_flags(&self, instance: RuntimeComponentInstanceIndex) -> InstanceFlags {
361         unsafe {
362             let ptr = self
363                 .vmctx_plus_offset_raw::<VMGlobalDefinition>(self.offsets.instance_flags(instance));
364             InstanceFlags(SendSyncPtr::new(ptr))
365         }
366     }
367 
368     /// Returns the runtime memory definition corresponding to the index of the
369     /// memory provided.
370     ///
371     /// This can only be called after `idx` has been initialized at runtime
372     /// during the instantiation process of a component.
373     pub fn runtime_memory(&self, idx: RuntimeMemoryIndex) -> NonNull<VMMemoryDefinition> {
374         unsafe {
375             let ret = *self.vmctx_plus_offset::<VmPtr<_>>(self.offsets.runtime_memory(idx));
376             debug_assert!(ret.as_ptr() as usize != INVALID_PTR);
377             ret.as_non_null()
378         }
379     }
380 
381     /// Returns the runtime table definition and associated instance `VMContext`
382     /// corresponding to the index of the table provided.
383     ///
384     /// This can only be called after `idx` has been initialized at runtime
385     /// during the instantiation process of a component.
386     pub fn runtime_table(&self, idx: RuntimeTableIndex) -> VMTableImport {
387         unsafe {
388             let ret = *self.vmctx_plus_offset::<VMTableImport>(self.offsets.runtime_table(idx));
389             debug_assert!(ret.from.as_ptr() as usize != INVALID_PTR);
390             debug_assert!(ret.vmctx.as_ptr() as usize != INVALID_PTR);
391             ret
392         }
393     }
394 
395     /// Returns the `Func` at index `func_idx` in the funcref table at `table_idx`.
396     pub fn index_runtime_func_table(
397         &self,
398         registry: &ModuleRegistry,
399         table_idx: RuntimeTableIndex,
400         func_idx: u64,
401     ) -> Result<Option<Func>> {
402         unsafe {
403             let store = self.store.0.as_ref();
404             let table = self.runtime_table(table_idx);
405             let vmctx = table.vmctx.as_non_null();
406             // SAFETY: it's a contract of this function that `vmctx` is a valid
407             // allocation which can go backwards to a `ComponentInstance`.
408             let mut instance_ptr = vm::Instance::from_vmctx(vmctx);
409             // SAFETY: We just constructed `instance_ptr` from a valid pointer. This pointer won't leave
410             // this call, so we don't need a lifetime to bind it to.
411             let instance = Pin::new_unchecked(instance_ptr.as_mut());
412             let table =
413                 instance.get_defined_table_with_lazy_init(registry, table.index, [func_idx]);
414             let func = table
415                 .get_func(func_idx)?
416                 .map(|funcref| Func::from_vm_func_ref(store.id(), funcref));
417             Ok(func)
418         }
419     }
420 
421     /// Returns the realloc pointer corresponding to the index provided.
422     ///
423     /// This can only be called after `idx` has been initialized at runtime
424     /// during the instantiation process of a component.
425     pub fn runtime_realloc(&self, idx: RuntimeReallocIndex) -> NonNull<VMFuncRef> {
426         unsafe {
427             let ret = *self.vmctx_plus_offset::<VmPtr<_>>(self.offsets.runtime_realloc(idx));
428             debug_assert!(ret.as_ptr() as usize != INVALID_PTR);
429             ret.as_non_null()
430         }
431     }
432 
433     /// Returns the async callback pointer corresponding to the index provided.
434     ///
435     /// This can only be called after `idx` has been initialized at runtime
436     /// during the instantiation process of a component.
437     pub fn runtime_callback(&self, idx: RuntimeCallbackIndex) -> NonNull<VMFuncRef> {
438         unsafe {
439             let ret = *self.vmctx_plus_offset::<VmPtr<_>>(self.offsets.runtime_callback(idx));
440             debug_assert!(ret.as_ptr() as usize != INVALID_PTR);
441             ret.as_non_null()
442         }
443     }
444 
445     /// Returns the post-return pointer corresponding to the index provided.
446     ///
447     /// This can only be called after `idx` has been initialized at runtime
448     /// during the instantiation process of a component.
449     pub fn runtime_post_return(&self, idx: RuntimePostReturnIndex) -> NonNull<VMFuncRef> {
450         unsafe {
451             let ret = *self.vmctx_plus_offset::<VmPtr<_>>(self.offsets.runtime_post_return(idx));
452             debug_assert!(ret.as_ptr() as usize != INVALID_PTR);
453             ret.as_non_null()
454         }
455     }
456 
457     /// Returns the host information for the lowered function at the index
458     /// specified.
459     ///
460     /// This can only be called after `idx` has been initialized at runtime
461     /// during the instantiation process of a component.
462     pub fn lowering(&self, idx: LoweredIndex) -> VMLowering {
463         unsafe {
464             let ret = *self.vmctx_plus_offset::<VMLowering>(self.offsets.lowering(idx));
465             debug_assert!(ret.callee.as_ptr() as usize != INVALID_PTR);
466             debug_assert!(ret.data.as_ptr() as usize != INVALID_PTR);
467             ret
468         }
469     }
470 
471     /// Returns the core wasm `funcref` corresponding to the trampoline
472     /// specified.
473     ///
474     /// The returned function is suitable to pass directly to a wasm module
475     /// instantiation and the function contains cranelift-compiled trampolines.
476     ///
477     /// This can only be called after `idx` has been initialized at runtime
478     /// during the instantiation process of a component.
479     pub fn trampoline_func_ref(&self, idx: TrampolineIndex) -> NonNull<VMFuncRef> {
480         unsafe {
481             let offset = self.offsets.trampoline_func_ref(idx);
482             let ret = self.vmctx_plus_offset_raw::<VMFuncRef>(offset);
483             debug_assert!(
484                 mem::transmute::<Option<VmPtr<VMWasmCallFunction>>, usize>(ret.as_ref().wasm_call)
485                     != INVALID_PTR
486             );
487             debug_assert!(ret.as_ref().vmctx.as_ptr() as usize != INVALID_PTR);
488             ret
489         }
490     }
491 
492     /// Get the core Wasm function reference for the given unsafe intrinsic.
493     pub fn unsafe_intrinsic_func_ref(&self, idx: UnsafeIntrinsic) -> NonNull<VMFuncRef> {
494         unsafe {
495             let offset = self.offsets.unsafe_intrinsic_func_ref(idx);
496             let ret = self.vmctx_plus_offset_raw::<VMFuncRef>(offset);
497             debug_assert!(
498                 mem::transmute::<Option<VmPtr<VMWasmCallFunction>>, usize>(ret.as_ref().wasm_call)
499                     != INVALID_PTR
500             );
501             debug_assert!(ret.as_ref().vmctx.as_ptr() as usize != INVALID_PTR);
502             ret
503         }
504     }
505 
506     /// Stores the runtime memory pointer at the index specified.
507     ///
508     /// This is intended to be called during the instantiation process of a
509     /// component once a memory is available, which may not be until part-way
510     /// through component instantiation.
511     ///
512     /// Note that it should be a property of the component model that the `ptr`
513     /// here is never needed prior to it being configured here in the instance.
514     pub fn set_runtime_memory(
515         self: Pin<&mut Self>,
516         idx: RuntimeMemoryIndex,
517         ptr: NonNull<VMMemoryDefinition>,
518     ) {
519         unsafe {
520             let offset = self.offsets.runtime_memory(idx);
521             let storage = self.vmctx_plus_offset_mut::<VmPtr<VMMemoryDefinition>>(offset);
522             debug_assert!((*storage).as_ptr() as usize == INVALID_PTR);
523             *storage = ptr.into();
524         }
525     }
526 
527     /// Same as `set_runtime_memory` but for realloc function pointers.
528     pub fn set_runtime_realloc(
529         self: Pin<&mut Self>,
530         idx: RuntimeReallocIndex,
531         ptr: NonNull<VMFuncRef>,
532     ) {
533         unsafe {
534             let offset = self.offsets.runtime_realloc(idx);
535             let storage = self.vmctx_plus_offset_mut::<VmPtr<VMFuncRef>>(offset);
536             debug_assert!((*storage).as_ptr() as usize == INVALID_PTR);
537             *storage = ptr.into();
538         }
539     }
540 
541     /// Same as `set_runtime_memory` but for async callback function pointers.
542     pub fn set_runtime_callback(
543         self: Pin<&mut Self>,
544         idx: RuntimeCallbackIndex,
545         ptr: NonNull<VMFuncRef>,
546     ) {
547         unsafe {
548             let offset = self.offsets.runtime_callback(idx);
549             let storage = self.vmctx_plus_offset_mut::<VmPtr<VMFuncRef>>(offset);
550             debug_assert!((*storage).as_ptr() as usize == INVALID_PTR);
551             *storage = ptr.into();
552         }
553     }
554 
555     /// Same as `set_runtime_memory` but for post-return function pointers.
556     pub fn set_runtime_post_return(
557         self: Pin<&mut Self>,
558         idx: RuntimePostReturnIndex,
559         ptr: NonNull<VMFuncRef>,
560     ) {
561         unsafe {
562             let offset = self.offsets.runtime_post_return(idx);
563             let storage = self.vmctx_plus_offset_mut::<VmPtr<VMFuncRef>>(offset);
564             debug_assert!((*storage).as_ptr() as usize == INVALID_PTR);
565             *storage = ptr.into();
566         }
567     }
568 
569     /// Stores the runtime table pointer at the index specified.
570     ///
571     /// This is intended to be called during the instantiation process of a
572     /// component once a table is available, which may not be until part-way
573     /// through component instantiation.
574     ///
575     /// Note that it should be a property of the component model that the `ptr`
576     /// here is never needed prior to it being configured here in the instance.
577     pub fn set_runtime_table(self: Pin<&mut Self>, idx: RuntimeTableIndex, import: VMTableImport) {
578         unsafe {
579             let offset = self.offsets.runtime_table(idx);
580             let storage = self.vmctx_plus_offset_mut::<VMTableImport>(offset);
581             debug_assert!((*storage).vmctx.as_ptr() as usize == INVALID_PTR);
582             debug_assert!((*storage).from.as_ptr() as usize == INVALID_PTR);
583             *storage = import;
584         }
585     }
586 
587     /// Configures host runtime lowering information associated with imported f
588     /// functions for the `idx` specified.
589     pub fn set_lowering(self: Pin<&mut Self>, idx: LoweredIndex, lowering: VMLowering) {
590         unsafe {
591             let callee = self.offsets.lowering_callee(idx);
592             debug_assert!(*self.vmctx_plus_offset::<usize>(callee) == INVALID_PTR);
593             let data = self.offsets.lowering_data(idx);
594             debug_assert!(*self.vmctx_plus_offset::<usize>(data) == INVALID_PTR);
595             let offset = self.offsets.lowering(idx);
596             *self.vmctx_plus_offset_mut(offset) = lowering;
597         }
598     }
599 
600     /// Same as `set_lowering` but for the resource.drop functions.
601     pub fn set_trampoline(
602         self: Pin<&mut Self>,
603         idx: TrampolineIndex,
604         wasm_call: NonNull<VMWasmCallFunction>,
605         array_call: NonNull<VMArrayCallFunction>,
606         type_index: VMSharedTypeIndex,
607     ) {
608         unsafe {
609             let offset = self.offsets.trampoline_func_ref(idx);
610             debug_assert!(*self.vmctx_plus_offset::<usize>(offset) == INVALID_PTR);
611             let vmctx = VMOpaqueContext::from_vmcomponent(self.vmctx());
612             *self.vmctx_plus_offset_mut(offset) = VMFuncRef {
613                 wasm_call: Some(wasm_call.into()),
614                 array_call: array_call.into(),
615                 type_index,
616                 vmctx: vmctx.into(),
617             };
618         }
619     }
620 
621     /// Same as `set_trampoline` but for intrinsic functions.
622     pub fn set_intrinsic(
623         self: Pin<&mut Self>,
624         intrinsic: UnsafeIntrinsic,
625         wasm_call: NonNull<VMWasmCallFunction>,
626         array_call: NonNull<VMArrayCallFunction>,
627         type_index: VMSharedTypeIndex,
628     ) {
629         unsafe {
630             let offset = self.offsets.unsafe_intrinsic_func_ref(intrinsic);
631             debug_assert!(*self.vmctx_plus_offset::<usize>(offset) == INVALID_PTR);
632             let vmctx = VMOpaqueContext::from_vmcomponent(self.vmctx());
633             *self.vmctx_plus_offset_mut(offset) = VMFuncRef {
634                 wasm_call: Some(wasm_call.into()),
635                 array_call: array_call.into(),
636                 type_index,
637                 vmctx: vmctx.into(),
638             };
639         }
640     }
641 
642     /// Configures the destructor for a resource at the `idx` specified.
643     ///
644     /// This is required to be called for each resource as it's defined within a
645     /// component during the instantiation process.
646     pub fn set_resource_destructor(
647         self: Pin<&mut Self>,
648         idx: ResourceIndex,
649         dtor: Option<NonNull<VMFuncRef>>,
650     ) {
651         unsafe {
652             let offset = self.offsets.resource_destructor(idx);
653             debug_assert!(*self.vmctx_plus_offset::<usize>(offset) == INVALID_PTR);
654             *self.vmctx_plus_offset_mut(offset) = dtor.map(VmPtr::from);
655         }
656     }
657 
658     /// Returns the destructor, if any, for `idx`.
659     ///
660     /// This is only valid to call after `set_resource_destructor`, or typically
661     /// after instantiation.
662     pub fn resource_destructor(&self, idx: ResourceIndex) -> Option<NonNull<VMFuncRef>> {
663         unsafe {
664             let offset = self.offsets.resource_destructor(idx);
665             debug_assert!(*self.vmctx_plus_offset::<usize>(offset) != INVALID_PTR);
666             (*self.vmctx_plus_offset::<Option<VmPtr<VMFuncRef>>>(offset)).map(|p| p.as_non_null())
667         }
668     }
669 
670     unsafe fn initialize_vmctx(mut self: Pin<&mut Self>) {
671         let offset = self.offsets.magic();
672         // SAFETY: it's safe to write the magic value during initialization and
673         // this is also the right type of value to write.
674         unsafe {
675             *self.as_mut().vmctx_plus_offset_mut(offset) = VMCOMPONENT_MAGIC;
676         }
677 
678         // Initialize the built-in functions
679         //
680         // SAFETY: it's safe to initialize the vmctx in this function and this
681         // is also the right type of value to store in the vmctx.
682         static BUILTINS: libcalls::VMComponentBuiltins = libcalls::VMComponentBuiltins::INIT;
683         let ptr = BUILTINS.expose_provenance();
684         let offset = self.offsets.builtins();
685         unsafe {
686             *self.as_mut().vmctx_plus_offset_mut(offset) = VmPtr::from(ptr);
687         }
688 
689         // SAFETY: it's safe to initialize the vmctx in this function and this
690         // is also the right type of value to store in the vmctx.
691         let offset = self.offsets.vm_store_context();
692         unsafe {
693             *self.as_mut().vmctx_plus_offset_mut(offset) =
694                 VmPtr::from(self.store.0.as_ref().vm_store_context_ptr());
695         }
696 
697         for i in 0..self.offsets.num_runtime_component_instances {
698             let i = RuntimeComponentInstanceIndex::from_u32(i);
699             let mut def = VMGlobalDefinition::new();
700             // SAFETY: this is a valid initialization of all globals which are
701             // 32-bit values.
702             unsafe {
703                 *def.as_i32_mut() = FLAG_MAY_ENTER | FLAG_MAY_LEAVE;
704                 self.instance_flags(i).as_raw().write(def);
705             }
706         }
707 
708         // In debug mode set non-null bad values to all "pointer looking" bits
709         // and pieces related to lowering and such. This'll help detect any
710         // erroneous usage and enable debug assertions above as well to prevent
711         // loading these before they're configured or setting them twice.
712         //
713         // SAFETY: it's valid to write a garbage pointer during initialization
714         // when this is otherwise uninitialized memory
715         if cfg!(debug_assertions) {
716             for i in 0..self.offsets.num_lowerings {
717                 let i = LoweredIndex::from_u32(i);
718                 let offset = self.offsets.lowering_callee(i);
719                 // SAFETY: see above
720                 unsafe {
721                     *self.as_mut().vmctx_plus_offset_mut(offset) = INVALID_PTR;
722                 }
723                 let offset = self.offsets.lowering_data(i);
724                 // SAFETY: see above
725                 unsafe {
726                     *self.as_mut().vmctx_plus_offset_mut(offset) = INVALID_PTR;
727                 }
728             }
729             for i in 0..self.offsets.num_trampolines {
730                 let i = TrampolineIndex::from_u32(i);
731                 let offset = self.offsets.trampoline_func_ref(i);
732                 // SAFETY: see above
733                 unsafe {
734                     *self.as_mut().vmctx_plus_offset_mut(offset) = INVALID_PTR;
735                 }
736             }
737             for i in 0..self.offsets.num_unsafe_intrinsics {
738                 let i = UnsafeIntrinsic::from_u32(i);
739                 let offset = self.offsets.unsafe_intrinsic_func_ref(i);
740                 // SAFETY: see above
741                 unsafe {
742                     *self.as_mut().vmctx_plus_offset_mut(offset) = INVALID_PTR;
743                 }
744             }
745             for i in 0..self.offsets.num_runtime_memories {
746                 let i = RuntimeMemoryIndex::from_u32(i);
747                 let offset = self.offsets.runtime_memory(i);
748                 // SAFETY: see above
749                 unsafe {
750                     *self.as_mut().vmctx_plus_offset_mut(offset) = INVALID_PTR;
751                 }
752             }
753             for i in 0..self.offsets.num_runtime_reallocs {
754                 let i = RuntimeReallocIndex::from_u32(i);
755                 let offset = self.offsets.runtime_realloc(i);
756                 // SAFETY: see above
757                 unsafe {
758                     *self.as_mut().vmctx_plus_offset_mut(offset) = INVALID_PTR;
759                 }
760             }
761             for i in 0..self.offsets.num_runtime_callbacks {
762                 let i = RuntimeCallbackIndex::from_u32(i);
763                 let offset = self.offsets.runtime_callback(i);
764                 // SAFETY: see above
765                 unsafe {
766                     *self.as_mut().vmctx_plus_offset_mut(offset) = INVALID_PTR;
767                 }
768             }
769             for i in 0..self.offsets.num_runtime_post_returns {
770                 let i = RuntimePostReturnIndex::from_u32(i);
771                 let offset = self.offsets.runtime_post_return(i);
772                 // SAFETY: see above
773                 unsafe {
774                     *self.as_mut().vmctx_plus_offset_mut(offset) = INVALID_PTR;
775                 }
776             }
777             for i in 0..self.offsets.num_resources {
778                 let i = ResourceIndex::from_u32(i);
779                 let offset = self.offsets.resource_destructor(i);
780                 // SAFETY: see above
781                 unsafe {
782                     *self.as_mut().vmctx_plus_offset_mut(offset) = INVALID_PTR;
783                 }
784             }
785             for i in 0..self.offsets.num_runtime_tables {
786                 let i = RuntimeTableIndex::from_u32(i);
787                 let offset = self.offsets.runtime_table(i);
788                 // SAFETY: see above
789                 #[allow(clippy::cast_possible_truncation, reason = "known to not overflow")]
790                 unsafe {
791                     *self.as_mut().vmctx_plus_offset_mut::<usize>(
792                         offset + offset_of!(VMTableImport, from) as u32,
793                     ) = INVALID_PTR;
794                     *self.as_mut().vmctx_plus_offset_mut::<usize>(
795                         offset + offset_of!(VMTableImport, vmctx) as u32,
796                     ) = INVALID_PTR;
797                 }
798             }
799         }
800     }
801 
802     /// Returns a reference to the component type information for this
803     /// instance.
804     pub fn component(&self) -> &Component {
805         &self.component
806     }
807 
808     /// Same as [`Self::component`] but additionally returns the
809     /// `Pin<&mut Self>` with the same original lifetime.
810     pub fn component_and_self(self: Pin<&mut Self>) -> (&Component, Pin<&mut Self>) {
811         // SAFETY: this function is projecting both `&Component` and the same
812         // pointer both connected to the same lifetime. This is safe because
813         // it's a contract of `Pin<&mut Self>` that the `Component` field is
814         // never written, meaning it's effectively unsafe to have `&mut
815         // Component` projected from `Pin<&mut Self>`. Consequently it's safe to
816         // have a read-only view of the field while still retaining mutable
817         // access to all other fields.
818         let component = unsafe { &*(&raw const self.component) };
819         (component, self)
820     }
821 
822     /// Returns a reference to the resource type information.
823     pub fn resource_types(&self) -> &Arc<PrimaryMap<ResourceIndex, ResourceType>> {
824         &self.resource_types
825     }
826 
827     /// Returns a mutable reference to the resource type information.
828     pub fn resource_types_mut(
829         self: Pin<&mut Self>,
830     ) -> &mut Arc<PrimaryMap<ResourceIndex, ResourceType>> {
831         // SAFETY: we've chosen the `Pin` guarantee of `Self` to not apply to
832         // the map returned.
833         unsafe { &mut self.get_unchecked_mut().resource_types }
834     }
835 
836     /// Returns whether the resource that `ty` points to is owned by the
837     /// instance that `ty` correspond to.
838     ///
839     /// This is used when lowering borrows to skip table management and instead
840     /// thread through the underlying representation directly.
841     pub fn resource_owned_by_own_instance(&self, ty: TypeResourceTableIndex) -> bool {
842         let (resource_ty, resource_instance) = match self.component.types()[ty] {
843             TypeResourceTable::Concrete { ty, instance } => (ty, instance),
844             TypeResourceTable::Abstract(_) => return false,
845         };
846         let component = self.component.env_component();
847         let idx = match component.defined_resource_index(resource_ty) {
848             Some(idx) => idx,
849             None => return false,
850         };
851         resource_instance == component.defined_resource_instances[idx]
852     }
853 
854     /// Returns the runtime state of resources and concurrency associated with
855     /// this component.
856     #[inline]
857     pub fn instance_states(
858         self: Pin<&mut Self>,
859     ) -> (
860         &mut PrimaryMap<RuntimeComponentInstanceIndex, InstanceState>,
861         &ComponentTypes,
862     ) {
863         // safety: we've chosen the `pin` guarantee of `self` to not apply to
864         // the map returned.
865         unsafe {
866             let me = self.get_unchecked_mut();
867             (&mut me.instance_states, me.component.types())
868         }
869     }
870 
871     pub fn instance_state(
872         self: Pin<&mut Self>,
873         instance: RuntimeComponentInstanceIndex,
874     ) -> Option<&mut InstanceState> {
875         self.instance_states().0.get_mut(instance)
876     }
877 
878     /// Returns the destructor and instance flags for the specified resource
879     /// table type.
880     ///
881     /// This will lookup the origin definition of the `ty` table and return the
882     /// destructor/flags for that.
883     pub fn dtor_and_flags(
884         &self,
885         ty: TypeResourceTableIndex,
886     ) -> (Option<NonNull<VMFuncRef>>, Option<InstanceFlags>) {
887         let resource = self.component.types()[ty].unwrap_concrete_ty();
888         let dtor = self.resource_destructor(resource);
889         let component = self.component.env_component();
890         let flags = component.defined_resource_index(resource).map(|i| {
891             let instance = component.defined_resource_instances[i];
892             self.instance_flags(instance)
893         });
894         (dtor, flags)
895     }
896 
897     /// Returns the store-local id that points to this component.
898     pub fn id(&self) -> ComponentInstanceId {
899         self.id
900     }
901 
902     /// Pushes a new runtime instance that's been created into
903     /// `self.instances`.
904     pub fn push_instance_id(self: Pin<&mut Self>, id: InstanceId) -> RuntimeInstanceIndex {
905         self.instances_mut().push(id)
906     }
907 
908     /// Returns the [`InstanceId`] previously pushed by `push_instance_id`
909     /// above.
910     ///
911     /// # Panics
912     ///
913     /// Panics if `idx` hasn't been initialized yet.
914     pub fn instance(&self, idx: RuntimeInstanceIndex) -> InstanceId {
915         self.instances[idx]
916     }
917 
918     fn instances_mut(self: Pin<&mut Self>) -> &mut PrimaryMap<RuntimeInstanceIndex, InstanceId> {
919         // SAFETY: we've chosen the `Pin` guarantee of `Self` to not apply to
920         // the map returned.
921         unsafe { &mut self.get_unchecked_mut().instances }
922     }
923 
924     /// Looks up the value used for `import` at runtime.
925     ///
926     /// # Panics
927     ///
928     /// Panics of `import` is out of bounds for this component.
929     pub(crate) fn runtime_import(&self, import: RuntimeImportIndex) -> &RuntimeImport {
930         &self.imports[import]
931     }
932 
933     /// Returns an `InstancePre<T>` which can be used to re-instantiated this
934     /// component if desired.
935     ///
936     /// # Safety
937     ///
938     /// This function places no bounds on `T` so it's up to the caller to match
939     /// that up appropriately with the store that this instance resides within.
940     pub unsafe fn instance_pre<T>(&self) -> InstancePre<T> {
941         // SAFETY: The `T` part of `new_unchecked` is forwarded as a contract of
942         // this function, and otherwise the validity of the components of the
943         // InstancePre should be guaranteed as it's what we were built with
944         // ourselves.
945         unsafe {
946             InstancePre::new_unchecked(
947                 self.component.clone(),
948                 self.imports.clone(),
949                 self.resource_types.clone(),
950             )
951         }
952     }
953 
954     /// Sets the cached argument for the canonical ABI option `post-return` to
955     /// the `arg` specified.
956     ///
957     /// This function is used in conjunction with function calls to record,
958     /// after a function call completes, the optional ABI return value. This
959     /// return value is cached within this instance for future use when the
960     /// `post_return` Rust-API-level function is invoked.
961     ///
962     /// Note that `index` here is the index of the export that was just
963     /// invoked, and this is used to ensure that `post_return` is called on the
964     /// same function afterwards. This restriction technically isn't necessary
965     /// though and may be one we want to lift in the future.
966     ///
967     /// # Panics
968     ///
969     /// This function will panic if `post_return_arg` is already set to `Some`.
970     pub fn post_return_arg_set(self: Pin<&mut Self>, index: ExportIndex, arg: ValRaw) {
971         assert!(self.post_return_arg.is_none());
972         *self.post_return_arg_mut() = Some((index, arg));
973     }
974 
975     /// Re-acquires the value originally saved via `post_return_arg_set`.
976     ///
977     /// This function will take a function `index` that's having its
978     /// `post_return` function called. If an argument was previously stored and
979     /// `index` matches the index that was stored then `Some(arg)` is returned.
980     /// Otherwise `None` is returned.
981     pub fn post_return_arg_take(self: Pin<&mut Self>, index: ExportIndex) -> Option<ValRaw> {
982         let post_return_arg = self.post_return_arg_mut();
983         let (expected_index, arg) = post_return_arg.take()?;
984         if index != expected_index {
985             *post_return_arg = Some((expected_index, arg));
986             None
987         } else {
988             Some(arg)
989         }
990     }
991 
992     fn post_return_arg_mut(self: Pin<&mut Self>) -> &mut Option<(ExportIndex, ValRaw)> {
993         // SAFETY: we've chosen the `Pin` guarantee of `Self` to not apply to
994         // the map returned.
995         unsafe { &mut self.get_unchecked_mut().post_return_arg }
996     }
997 
998     pub(crate) fn check_may_leave(
999         &self,
1000         instance: RuntimeComponentInstanceIndex,
1001     ) -> anyhow::Result<()> {
1002         let flags = self.instance_flags(instance);
1003         if unsafe { flags.may_leave() } {
1004             Ok(())
1005         } else {
1006             Err(anyhow::anyhow!(crate::Trap::CannotLeaveComponent))
1007         }
1008     }
1009 }
1010 
1011 // SAFETY: `layout` should describe this accurately and `OwnedVMContext` is the
1012 // last field of `ComponentInstance`.
1013 unsafe impl InstanceLayout for ComponentInstance {
1014     /// Technically it is not required to `alloc_zeroed` here. The primary
1015     /// reason for doing this is because a component context start is a "partly
1016     /// initialized" state where pointers and such are configured as the
1017     /// instantiation process continues. The component model should guarantee
1018     /// that we never access uninitialized memory in the context, but to help
1019     /// protect against possible bugs a zeroed allocation is done here to try to
1020     /// contain use-before-initialized issues.
1021     const INIT_ZEROED: bool = true;
1022 
1023     type VMContext = VMComponentContext;
1024 
1025     fn layout(&self) -> Layout {
1026         ComponentInstance::alloc_layout(&self.offsets)
1027     }
1028 
1029     fn owned_vmctx(&self) -> &OwnedVMContext<VMComponentContext> {
1030         &self.vmctx
1031     }
1032 
1033     fn owned_vmctx_mut(&mut self) -> &mut OwnedVMContext<VMComponentContext> {
1034         &mut self.vmctx
1035     }
1036 }
1037 
1038 pub type OwnedComponentInstance = OwnedInstance<ComponentInstance>;
1039 
1040 impl VMComponentContext {
1041     /// Moves the `self` pointer backwards to the `ComponentInstance` pointer
1042     /// that this `VMComponentContext` trails.
1043     pub fn instance(&self) -> *mut ComponentInstance {
1044         unsafe {
1045             (self as *const Self as *mut u8)
1046                 .offset(-(offset_of!(ComponentInstance, vmctx) as isize))
1047                 as *mut ComponentInstance
1048         }
1049     }
1050 
1051     /// Helper function to cast between context types using a debug assertion to
1052     /// protect against some mistakes.
1053     ///
1054     /// # Safety
1055     ///
1056     /// The `opaque` value must be a valid pointer where it's safe to read its
1057     /// "magic" value.
1058     #[inline]
1059     pub unsafe fn from_opaque(opaque: NonNull<VMOpaqueContext>) -> NonNull<VMComponentContext> {
1060         // See comments in `VMContext::from_opaque` for this debug assert
1061         //
1062         // SAFETY: it's a contract of this function that it's safe to read
1063         // `opaque`.
1064         unsafe {
1065             debug_assert_eq!(opaque.as_ref().magic, VMCOMPONENT_MAGIC);
1066         }
1067         opaque.cast()
1068     }
1069 }
1070 
1071 impl VMOpaqueContext {
1072     /// Helper function to clearly indicate the cast desired
1073     #[inline]
1074     pub fn from_vmcomponent(ptr: NonNull<VMComponentContext>) -> NonNull<VMOpaqueContext> {
1075         ptr.cast()
1076     }
1077 }
1078 
1079 #[repr(transparent)]
1080 #[derive(Copy, Clone)]
1081 pub struct InstanceFlags(SendSyncPtr<VMGlobalDefinition>);
1082 
1083 impl InstanceFlags {
1084     /// Wraps the given pointer as an `InstanceFlags`
1085     ///
1086     /// # Unsafety
1087     ///
1088     /// This is a raw pointer argument which needs to be valid for the lifetime
1089     /// that `InstanceFlags` is used.
1090     pub unsafe fn from_raw(ptr: NonNull<VMGlobalDefinition>) -> InstanceFlags {
1091         InstanceFlags(SendSyncPtr::from(ptr))
1092     }
1093 
1094     #[inline]
1095     pub unsafe fn may_leave(&self) -> bool {
1096         unsafe { *self.as_raw().as_ref().as_i32() & FLAG_MAY_LEAVE != 0 }
1097     }
1098 
1099     #[inline]
1100     pub unsafe fn set_may_leave(&mut self, val: bool) {
1101         unsafe {
1102             if val {
1103                 *self.as_raw().as_mut().as_i32_mut() |= FLAG_MAY_LEAVE;
1104             } else {
1105                 *self.as_raw().as_mut().as_i32_mut() &= !FLAG_MAY_LEAVE;
1106             }
1107         }
1108     }
1109 
1110     #[inline]
1111     pub unsafe fn may_enter(&self) -> bool {
1112         unsafe { *self.as_raw().as_ref().as_i32() & FLAG_MAY_ENTER != 0 }
1113     }
1114 
1115     #[inline]
1116     pub unsafe fn set_may_enter(&mut self, val: bool) {
1117         unsafe {
1118             if val {
1119                 *self.as_raw().as_mut().as_i32_mut() |= FLAG_MAY_ENTER;
1120             } else {
1121                 *self.as_raw().as_mut().as_i32_mut() &= !FLAG_MAY_ENTER;
1122             }
1123         }
1124     }
1125 
1126     #[inline]
1127     pub unsafe fn needs_post_return(&self) -> bool {
1128         unsafe { *self.as_raw().as_ref().as_i32() & FLAG_NEEDS_POST_RETURN != 0 }
1129     }
1130 
1131     #[inline]
1132     pub unsafe fn set_needs_post_return(&mut self, val: bool) {
1133         unsafe {
1134             if val {
1135                 *self.as_raw().as_mut().as_i32_mut() |= FLAG_NEEDS_POST_RETURN;
1136             } else {
1137                 *self.as_raw().as_mut().as_i32_mut() &= !FLAG_NEEDS_POST_RETURN;
1138             }
1139         }
1140     }
1141 
1142     #[inline]
1143     pub fn as_raw(&self) -> NonNull<VMGlobalDefinition> {
1144         self.0.as_non_null()
1145     }
1146 }
1147