wasmer_engine/
artifact.rs

1use crate::{resolve_imports, InstantiationError, Resolver, RuntimeError, Tunables};
2use loupe::MemoryUsage;
3use std::any::Any;
4pub use wasmer_artifact::MetadataHeader;
5use wasmer_artifact::{ArtifactCreate, Upcastable};
6use wasmer_compiler::CpuFeature;
7use wasmer_types::entity::BoxedSlice;
8use wasmer_types::{DataInitializer, FunctionIndex, LocalFunctionIndex, SignatureIndex};
9use wasmer_vm::{
10    FuncDataRegistry, FunctionBodyPtr, InstanceAllocator, InstanceHandle, TrapHandler,
11    VMSharedSignatureIndex, VMTrampoline,
12};
13
14/// An `Artifact` is the product that the `Engine`
15/// implementation produce and use.
16///
17
18/// An `Artifact` is the product that the `Engine`
19/// implementation produce and use.
20///
21/// The `ArtifactRun` contains the extra information needed to run the
22/// module at runtime, such as [`ModuleInfo`] and [`Features`].
23pub trait Artifact: Send + Sync + Upcastable + MemoryUsage + ArtifactCreate {
24    /// Register thie `Artifact` stack frame information into the global scope.
25    ///
26    /// This is required to ensure that any traps can be properly symbolicated.
27    fn register_frame_info(&self);
28
29    /// Returns the functions allocated in memory or this `Artifact`
30    /// ready to be run.
31    fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>;
32
33    /// Returns the function call trampolines allocated in memory of this
34    /// `Artifact`, ready to be run.
35    fn finished_function_call_trampolines(&self) -> &BoxedSlice<SignatureIndex, VMTrampoline>;
36
37    /// Returns the dynamic function trampolines allocated in memory
38    /// of this `Artifact`, ready to be run.
39    fn finished_dynamic_function_trampolines(&self) -> &BoxedSlice<FunctionIndex, FunctionBodyPtr>;
40
41    /// Returns the associated VM signatures for this `Artifact`.
42    fn signatures(&self) -> &BoxedSlice<SignatureIndex, VMSharedSignatureIndex>;
43
44    /// Get the func data registry
45    fn func_data_registry(&self) -> &FuncDataRegistry;
46
47    /// Do preinstantiation logic that is executed before instantiating
48    fn preinstantiate(&self) -> Result<(), InstantiationError> {
49        Ok(())
50    }
51    /// Crate an `Instance` from this `Artifact`.
52    ///
53    /// # Safety
54    ///
55    /// See [`InstanceHandle::new`].
56    unsafe fn instantiate(
57        &self,
58        tunables: &dyn Tunables,
59        resolver: &dyn Resolver,
60        host_state: Box<dyn Any>,
61    ) -> Result<InstanceHandle, InstantiationError> {
62        // Validate the CPU features this module was compiled with against the
63        // host CPU features.
64        let host_cpu_features = CpuFeature::for_host();
65        if !host_cpu_features.is_superset(self.cpu_features()) {
66            Err(InstantiationError::CpuFeature(format!(
67                "{:?}",
68                self.cpu_features().difference(host_cpu_features)
69            )))?;
70        }
71
72        self.preinstantiate()?;
73
74        let module = self.module();
75        let (imports, import_function_envs) = {
76            let mut imports = resolve_imports(
77                &module,
78                resolver,
79                &self.finished_dynamic_function_trampolines(),
80                self.memory_styles(),
81                self.table_styles(),
82            )
83            .map_err(InstantiationError::Link)?;
84
85            // Get the `WasmerEnv::init_with_instance` function pointers and the pointers
86            // to the envs to call it on.
87            let import_function_envs = imports.get_imported_function_envs();
88
89            (imports, import_function_envs)
90        };
91
92        // Get pointers to where metadata about local memories should live in VM memory.
93        // Get pointers to where metadata about local tables should live in VM memory.
94
95        let (allocator, memory_definition_locations, table_definition_locations) =
96            InstanceAllocator::new(&*module);
97        let finished_memories = tunables
98            .create_memories(&module, self.memory_styles(), &memory_definition_locations)
99            .map_err(InstantiationError::Link)?
100            .into_boxed_slice();
101        let finished_tables = tunables
102            .create_tables(&module, self.table_styles(), &table_definition_locations)
103            .map_err(InstantiationError::Link)?
104            .into_boxed_slice();
105        let finished_globals = tunables
106            .create_globals(&module)
107            .map_err(InstantiationError::Link)?
108            .into_boxed_slice();
109
110        self.register_frame_info();
111
112        let handle = InstanceHandle::new(
113            allocator,
114            module,
115            self.finished_functions().clone(),
116            self.finished_function_call_trampolines().clone(),
117            finished_memories,
118            finished_tables,
119            finished_globals,
120            imports,
121            self.signatures().clone(),
122            host_state,
123            import_function_envs,
124        )
125        .map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap)))?;
126        Ok(handle)
127    }
128    /// Finishes the instantiation of a just created `InstanceHandle`.
129    ///
130    /// # Safety
131    ///
132    /// See [`InstanceHandle::finish_instantiation`].
133    unsafe fn finish_instantiation(
134        &self,
135        trap_handler: &(dyn TrapHandler + 'static),
136        handle: &InstanceHandle,
137    ) -> Result<(), InstantiationError> {
138        let data_initializers = self
139            .data_initializers()
140            .iter()
141            .map(|init| DataInitializer {
142                location: init.location.clone(),
143                data: &*init.data,
144            })
145            .collect::<Vec<_>>();
146        handle
147            .finish_instantiation(trap_handler, &data_initializers)
148            .map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap)))
149    }
150}
151
152impl dyn Artifact + 'static {
153    /// Try to downcast the artifact into a given type.
154    #[inline]
155    pub fn downcast_ref<T: 'static>(&'_ self) -> Option<&'_ T> {
156        self.upcast_any_ref().downcast_ref::<T>()
157    }
158
159    /// Try to downcast the artifact into a given type mutably.
160    #[inline]
161    pub fn downcast_mut<T: 'static>(&'_ mut self) -> Option<&'_ mut T> {
162        self.upcast_any_mut().downcast_mut::<T>()
163    }
164}