wasmer_engine_universal/
artifact.rs

1//! Define `UniversalArtifact`, based on `UniversalArtifactBuild`
2//! to allow compiling and instantiating to be done as separate steps.
3
4use crate::engine::{UniversalEngine, UniversalEngineInner};
5use crate::link::link_module;
6use enumset::EnumSet;
7use loupe::MemoryUsage;
8use std::sync::{Arc, Mutex};
9#[cfg(feature = "compiler")]
10use wasmer_compiler::ModuleEnvironment;
11use wasmer_compiler::{CompileError, CpuFeature, Features, Triple};
12use wasmer_engine::{
13    register_frame_info, Artifact, DeserializeError, FunctionExtent, GlobalFrameInfoRegistration,
14    MetadataHeader, SerializeError,
15};
16#[cfg(feature = "compiler")]
17use wasmer_engine::{Engine, Tunables};
18use wasmer_engine_universal_artifact::ArtifactCreate;
19use wasmer_engine_universal_artifact::{SerializableModule, UniversalArtifactBuild};
20use wasmer_types::entity::{BoxedSlice, PrimaryMap};
21use wasmer_types::{
22    FunctionIndex, LocalFunctionIndex, MemoryIndex, ModuleInfo, OwnedDataInitializer,
23    SignatureIndex, TableIndex,
24};
25use wasmer_vm::{
26    FuncDataRegistry, FunctionBodyPtr, MemoryStyle, TableStyle, VMSharedSignatureIndex,
27    VMTrampoline,
28};
29
30/// A compiled wasm module, ready to be instantiated.
31#[derive(MemoryUsage)]
32pub struct UniversalArtifact {
33    artifact: UniversalArtifactBuild,
34    finished_functions: BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
35    #[loupe(skip)]
36    finished_function_call_trampolines: BoxedSlice<SignatureIndex, VMTrampoline>,
37    finished_dynamic_function_trampolines: BoxedSlice<FunctionIndex, FunctionBodyPtr>,
38    signatures: BoxedSlice<SignatureIndex, VMSharedSignatureIndex>,
39    func_data_registry: Arc<FuncDataRegistry>,
40    frame_info_registration: Mutex<Option<GlobalFrameInfoRegistration>>,
41    finished_function_lengths: BoxedSlice<LocalFunctionIndex, usize>,
42}
43
44impl UniversalArtifact {
45    /// Compile a data buffer into a `UniversalArtifactBuild`, which may then be instantiated.
46    #[cfg(feature = "compiler")]
47    pub fn new(
48        engine: &UniversalEngine,
49        data: &[u8],
50        tunables: &dyn Tunables,
51    ) -> Result<Self, CompileError> {
52        let environ = ModuleEnvironment::new();
53        let mut inner_engine = engine.inner_mut();
54        let translation = environ.translate(data).map_err(CompileError::Wasm)?;
55        let module = translation.module;
56        let memory_styles: PrimaryMap<MemoryIndex, MemoryStyle> = module
57            .memories
58            .values()
59            .map(|memory_type| tunables.memory_style(memory_type))
60            .collect();
61        let table_styles: PrimaryMap<TableIndex, TableStyle> = module
62            .tables
63            .values()
64            .map(|table_type| tunables.table_style(table_type))
65            .collect();
66
67        let artifact = UniversalArtifactBuild::new(
68            inner_engine.builder_mut(),
69            data,
70            engine.target(),
71            memory_styles,
72            table_styles,
73        )?;
74
75        Self::from_parts(&mut inner_engine, artifact)
76    }
77
78    /// Compile a data buffer into a `UniversalArtifactBuild`, which may then be instantiated.
79    #[cfg(not(feature = "compiler"))]
80    pub fn new(_engine: &UniversalEngine, _data: &[u8]) -> Result<Self, CompileError> {
81        Err(CompileError::Codegen(
82            "Compilation is not enabled in the engine".to_string(),
83        ))
84    }
85
86    /// Deserialize a UniversalArtifactBuild
87    ///
88    /// # Safety
89    /// This function is unsafe because rkyv reads directly without validating
90    /// the data.
91    pub unsafe fn deserialize(
92        engine: &UniversalEngine,
93        bytes: &[u8],
94    ) -> Result<Self, DeserializeError> {
95        if !UniversalArtifactBuild::is_deserializable(bytes) {
96            return Err(DeserializeError::Incompatible(
97                "The provided bytes are not wasmer-universal".to_string(),
98            ));
99        }
100        let bytes = &bytes[UniversalArtifactBuild::MAGIC_HEADER.len()..];
101        let metadata_len = MetadataHeader::parse(bytes)?;
102        let metadata_slice: &[u8] = &bytes[MetadataHeader::LEN..][..metadata_len];
103        let serializable = SerializableModule::deserialize(metadata_slice)?;
104        let artifact = UniversalArtifactBuild::from_serializable(serializable);
105        let mut inner_engine = engine.inner_mut();
106        Self::from_parts(&mut inner_engine, artifact).map_err(DeserializeError::Compiler)
107    }
108
109    /// Construct a `UniversalArtifactBuild` from component parts.
110    pub fn from_parts(
111        engine_inner: &mut UniversalEngineInner,
112        artifact: UniversalArtifactBuild,
113    ) -> Result<Self, CompileError> {
114        let (
115            finished_functions,
116            finished_function_call_trampolines,
117            finished_dynamic_function_trampolines,
118            custom_sections,
119        ) = engine_inner.allocate(
120            artifact.module_ref(),
121            artifact.get_function_bodies_ref(),
122            artifact.get_function_call_trampolines_ref(),
123            artifact.get_dynamic_function_trampolines_ref(),
124            artifact.get_custom_sections_ref(),
125        )?;
126
127        link_module(
128            artifact.module_ref(),
129            &finished_functions,
130            artifact.get_function_relocations().clone(),
131            &custom_sections,
132            artifact.get_custom_section_relocations_ref(),
133            artifact.get_libcall_trampolines(),
134            artifact.get_libcall_trampoline_len(),
135        );
136
137        // Compute indices into the shared signature table.
138        let signatures = {
139            let signature_registry = engine_inner.signatures();
140            artifact
141                .module()
142                .signatures
143                .values()
144                .map(|sig| signature_registry.register(sig))
145                .collect::<PrimaryMap<_, _>>()
146        };
147
148        let eh_frame = match artifact.get_debug_ref() {
149            Some(debug) => {
150                let eh_frame_section_size = artifact.get_custom_sections_ref()[debug.eh_frame]
151                    .bytes
152                    .len();
153                let eh_frame_section_pointer = custom_sections[debug.eh_frame];
154                Some(unsafe {
155                    std::slice::from_raw_parts(*eh_frame_section_pointer, eh_frame_section_size)
156                })
157            }
158            None => None,
159        };
160
161        // Make all code compiled thus far executable.
162        engine_inner.publish_compiled_code();
163
164        engine_inner.publish_eh_frame(eh_frame)?;
165
166        let finished_function_lengths = finished_functions
167            .values()
168            .map(|extent| extent.length)
169            .collect::<PrimaryMap<LocalFunctionIndex, usize>>()
170            .into_boxed_slice();
171        let finished_functions = finished_functions
172            .values()
173            .map(|extent| extent.ptr)
174            .collect::<PrimaryMap<LocalFunctionIndex, FunctionBodyPtr>>()
175            .into_boxed_slice();
176        let finished_function_call_trampolines =
177            finished_function_call_trampolines.into_boxed_slice();
178        let finished_dynamic_function_trampolines =
179            finished_dynamic_function_trampolines.into_boxed_slice();
180        let signatures = signatures.into_boxed_slice();
181        let func_data_registry = engine_inner.func_data().clone();
182
183        Ok(Self {
184            artifact,
185            finished_functions,
186            finished_function_call_trampolines,
187            finished_dynamic_function_trampolines,
188            signatures,
189            frame_info_registration: Mutex::new(None),
190            finished_function_lengths,
191            func_data_registry,
192        })
193    }
194    /// Get the default extension when serializing this artifact
195    pub fn get_default_extension(triple: &Triple) -> &'static str {
196        UniversalArtifactBuild::get_default_extension(triple)
197    }
198    /// Check if the provided bytes look like a serialized `UniversalArtifactBuild`.
199    pub fn is_deserializable(bytes: &[u8]) -> bool {
200        UniversalArtifactBuild::is_deserializable(bytes)
201    }
202}
203
204impl ArtifactCreate for UniversalArtifact {
205    fn module(&self) -> Arc<ModuleInfo> {
206        self.artifact.module()
207    }
208
209    fn module_ref(&self) -> &ModuleInfo {
210        self.artifact.module_ref()
211    }
212
213    fn module_mut(&mut self) -> Option<&mut ModuleInfo> {
214        self.artifact.module_mut()
215    }
216
217    fn features(&self) -> &Features {
218        self.artifact.features()
219    }
220
221    fn cpu_features(&self) -> EnumSet<CpuFeature> {
222        self.artifact.cpu_features()
223    }
224
225    fn data_initializers(&self) -> &[OwnedDataInitializer] {
226        self.artifact.data_initializers()
227    }
228
229    fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
230        self.artifact.memory_styles()
231    }
232
233    fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
234        self.artifact.table_styles()
235    }
236
237    fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
238        self.artifact.serialize()
239    }
240}
241
242impl Artifact for UniversalArtifact {
243    fn register_frame_info(&self) {
244        let mut info = self.frame_info_registration.lock().unwrap();
245
246        if info.is_some() {
247            return;
248        }
249
250        let finished_function_extents = self
251            .finished_functions
252            .values()
253            .copied()
254            .zip(self.finished_function_lengths.values().copied())
255            .map(|(ptr, length)| FunctionExtent { ptr, length })
256            .collect::<PrimaryMap<LocalFunctionIndex, _>>()
257            .into_boxed_slice();
258
259        let frame_infos = self.artifact.get_frame_info_ref();
260        *info = register_frame_info(
261            self.artifact.module(),
262            &finished_function_extents,
263            frame_infos.clone(),
264        );
265    }
266
267    fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> {
268        &self.finished_functions
269    }
270
271    fn finished_function_call_trampolines(&self) -> &BoxedSlice<SignatureIndex, VMTrampoline> {
272        &self.finished_function_call_trampolines
273    }
274
275    fn finished_dynamic_function_trampolines(&self) -> &BoxedSlice<FunctionIndex, FunctionBodyPtr> {
276        &self.finished_dynamic_function_trampolines
277    }
278
279    fn signatures(&self) -> &BoxedSlice<SignatureIndex, VMSharedSignatureIndex> {
280        &self.signatures
281    }
282
283    fn func_data_registry(&self) -> &FuncDataRegistry {
284        &self.func_data_registry
285    }
286}