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