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