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