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