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