1use 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#[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 #[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 #[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 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 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 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 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 pub fn get_default_extension(triple: &Triple) -> &'static str {
196 UniversalArtifactBuild::get_default_extension(triple)
197 }
198 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}