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