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