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