1use std::sync::{
5 Arc,
6 atomic::{AtomicUsize, Ordering::SeqCst},
7};
8
9#[cfg(feature = "compiler")]
10use crate::ModuleEnvironment;
11use crate::{
12 ArtifactBuild, ArtifactBuildFromArchive, ArtifactCreate, Engine, EngineInner, Features,
13 FrameInfosVariant, FunctionExtent, GlobalFrameInfoRegistration, InstantiationError, Tunables,
14 engine::{link::link_module, resolver::resolve_tags},
15 lib::std::vec::IntoIter,
16 register_frame_info, resolve_imports,
17 serialize::{MetadataHeader, SerializableModule},
18 types::relocation::{RelocationLike, RelocationTarget},
19};
20#[cfg(feature = "static-artifact-create")]
21use crate::{Compiler, FunctionBodyData, ModuleTranslationState, types::module::CompileModuleInfo};
22#[cfg(any(feature = "static-artifact-create", feature = "static-artifact-load"))]
23use crate::{serialize::SerializableCompilation, types::symbols::ModuleMetadata};
24
25use enumset::EnumSet;
26use shared_buffer::OwnedBuffer;
27
28#[cfg(any(feature = "static-artifact-create", feature = "static-artifact-load"))]
29use std::mem;
30
31#[cfg(feature = "static-artifact-create")]
32use crate::object::{
33 Object, ObjectMetadataBuilder, emit_compilation, emit_data, get_object_for_target,
34};
35
36use wasmer_types::{
37 ArchivedDataInitializerLocation, ArchivedOwnedDataInitializer, CompilationProgressCallback,
38 CompileError, DataInitializer, DataInitializerLike, DataInitializerLocation,
39 DataInitializerLocationLike, DeserializeError, FunctionIndex, LocalFunctionIndex, MemoryIndex,
40 ModuleInfo, OwnedDataInitializer, SerializeError, SignatureIndex, TableIndex,
41 entity::{BoxedSlice, PrimaryMap},
42 target::{CpuFeature, Target},
43};
44
45use wasmer_vm::{
46 FunctionBodyPtr, InstanceAllocator, MemoryStyle, StoreObjects, TableStyle, TrapHandlerFn,
47 VMConfig, VMExtern, VMInstance, VMSignatureHash, VMTrampoline,
48};
49
50#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
51pub struct AllocatedArtifact {
52 frame_info_registered: bool,
57 frame_info_registration: Option<GlobalFrameInfoRegistration>,
61 finished_functions: BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
62
63 #[cfg_attr(feature = "artifact-size", loupe(skip))]
64 finished_function_call_trampolines: BoxedSlice<SignatureIndex, VMTrampoline>,
65 finished_dynamic_function_trampolines: BoxedSlice<FunctionIndex, FunctionBodyPtr>,
66 signatures: BoxedSlice<SignatureIndex, VMSignatureHash>,
67 finished_function_lengths: BoxedSlice<LocalFunctionIndex, usize>,
68}
69
70#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
71#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
72#[repr(transparent)]
73pub struct ArtifactId {
75 id: usize,
76}
77
78impl ArtifactId {
79 pub fn id(&self) -> String {
81 format!("{}", &self.id)
82 }
83}
84
85impl Clone for ArtifactId {
86 fn clone(&self) -> Self {
87 Self::default()
88 }
89}
90
91impl Default for ArtifactId {
92 fn default() -> Self {
93 static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
94 Self {
95 id: NEXT_ID.fetch_add(1, SeqCst),
96 }
97 }
98}
99
100#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
102pub struct Artifact {
103 id: ArtifactId,
104 artifact: ArtifactBuildVariant,
105 allocated: Option<AllocatedArtifact>,
108}
109
110#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
114#[allow(clippy::large_enum_variant)]
115pub enum ArtifactBuildVariant {
116 Plain(ArtifactBuild),
117 Archived(ArtifactBuildFromArchive),
118}
119
120impl Artifact {
121 #[cfg(feature = "compiler")]
123 pub fn new(
124 engine: &Engine,
125 data: &[u8],
126 tunables: &dyn Tunables,
127 progress_callback: Option<CompilationProgressCallback>,
128 ) -> Result<Self, CompileError> {
129 let mut inner_engine = engine.inner_mut();
130 let environ = ModuleEnvironment::new();
131 let translation = environ.translate(data).map_err(CompileError::Wasm)?;
132 let module = translation.module;
133 let memory_styles: PrimaryMap<MemoryIndex, MemoryStyle> = module
134 .memories
135 .values()
136 .map(|memory_type| tunables.memory_style(memory_type))
137 .collect();
138 let table_styles: PrimaryMap<TableIndex, TableStyle> = module
139 .tables
140 .values()
141 .map(|table_type| tunables.table_style(table_type))
142 .collect();
143
144 let artifact = ArtifactBuild::new(
145 &mut inner_engine,
146 data,
147 engine.target(),
148 memory_styles,
149 table_styles,
150 progress_callback.as_ref(),
151 )?;
152
153 Self::from_parts(
154 &mut inner_engine,
155 ArtifactBuildVariant::Plain(artifact),
156 engine.target(),
157 )
158 .map_err(|e| match e {
159 DeserializeError::Compiler(c) => c,
160
161 _ => unreachable!(),
170 })
171 }
172
173 pub fn allocated(&self) -> bool {
177 self.allocated.is_some()
178 }
179
180 pub fn id(&self) -> &ArtifactId {
186 &self.id
187 }
188
189 #[cfg(not(feature = "compiler"))]
191 pub fn new(_engine: &Engine, _data: &[u8]) -> Result<Self, CompileError> {
192 Err(CompileError::Codegen(
193 "Compilation is not enabled in the engine".to_string(),
194 ))
195 }
196
197 pub unsafe fn deserialize(
206 engine: &Engine,
207 bytes: OwnedBuffer,
208 ) -> Result<Self, DeserializeError> {
209 unsafe {
210 if !ArtifactBuild::is_deserializable(bytes.as_ref()) {
211 let static_artifact = Self::deserialize_object(engine, bytes);
212 match static_artifact {
213 Ok(v) => {
214 return Ok(v);
215 }
216 Err(e) => {
217 return Err(DeserializeError::Incompatible(format!(
218 "The provided bytes are not wasmer-universal: {e}"
219 )));
220 }
221 }
222 }
223
224 let artifact = ArtifactBuildFromArchive::try_new(bytes, |bytes| {
225 let bytes =
226 Self::get_byte_slice(bytes, ArtifactBuild::MAGIC_HEADER.len(), bytes.len())?;
227
228 let metadata_len = MetadataHeader::parse(bytes)?;
229 let metadata_slice = Self::get_byte_slice(bytes, MetadataHeader::LEN, bytes.len())?;
230 let metadata_slice = Self::get_byte_slice(metadata_slice, 0, metadata_len)?;
231
232 SerializableModule::archive_from_slice_checked(metadata_slice)
233 })?;
234
235 let mut inner_engine = engine.inner_mut();
236 Self::from_parts(
237 &mut inner_engine,
238 ArtifactBuildVariant::Archived(artifact),
239 engine.target(),
240 )
241 }
242 }
243
244 pub unsafe fn deserialize_unchecked(
253 engine: &Engine,
254 bytes: OwnedBuffer,
255 ) -> Result<Self, DeserializeError> {
256 unsafe {
257 if !ArtifactBuild::is_deserializable(bytes.as_ref()) {
258 let static_artifact = Self::deserialize_object(engine, bytes);
259 match static_artifact {
260 Ok(v) => {
261 return Ok(v);
262 }
263 Err(e) => {
264 return Err(DeserializeError::Incompatible(format!(
265 "The provided bytes are not wasmer-universal: {e}"
266 )));
267 }
268 }
269 }
270
271 let artifact = ArtifactBuildFromArchive::try_new(bytes, |bytes| {
272 let bytes =
273 Self::get_byte_slice(bytes, ArtifactBuild::MAGIC_HEADER.len(), bytes.len())?;
274
275 let metadata_len = MetadataHeader::parse(bytes)?;
276 let metadata_slice = Self::get_byte_slice(bytes, MetadataHeader::LEN, bytes.len())?;
277 let metadata_slice = Self::get_byte_slice(metadata_slice, 0, metadata_len)?;
278
279 SerializableModule::archive_from_slice(metadata_slice)
280 })?;
281
282 let mut inner_engine = engine.inner_mut();
283 Self::from_parts(
284 &mut inner_engine,
285 ArtifactBuildVariant::Archived(artifact),
286 engine.target(),
287 )
288 }
289 }
290
291 pub fn from_parts(
293 engine_inner: &mut EngineInner,
294 artifact: ArtifactBuildVariant,
295 target: &Target,
296 ) -> Result<Self, DeserializeError> {
297 if !target.is_native() {
298 return Ok(Self {
299 id: Default::default(),
300 artifact,
301 allocated: None,
302 });
303 } else {
304 let cpu_features = artifact.cpu_features();
306 if !target.cpu_features().is_superset(cpu_features) {
307 return Err(DeserializeError::Incompatible(format!(
308 "Some CPU Features needed for the artifact are missing: {:?}",
309 cpu_features.difference(*target.cpu_features())
310 )));
311 }
312 }
313 let module_info = artifact.module_info();
314 let (
315 finished_functions,
316 finished_function_call_trampolines,
317 finished_dynamic_function_trampolines,
318 custom_sections,
319 ) = match &artifact {
320 ArtifactBuildVariant::Plain(p) => engine_inner.allocate(
321 module_info,
322 p.get_function_bodies_ref().values(),
323 p.get_function_call_trampolines_ref().values(),
324 p.get_dynamic_function_trampolines_ref().values(),
325 p.get_custom_sections_ref().values(),
326 )?,
327 ArtifactBuildVariant::Archived(a) => engine_inner.allocate(
328 module_info,
329 a.get_function_bodies_ref().values(),
330 a.get_function_call_trampolines_ref().values(),
331 a.get_dynamic_function_trampolines_ref().values(),
332 a.get_custom_sections_ref().values(),
333 )?,
334 };
335
336 let get_got_address: Box<dyn Fn(RelocationTarget) -> Option<usize>> = match &artifact {
337 ArtifactBuildVariant::Plain(p) => {
338 if let Some(got) = p.get_got_ref().index {
339 let relocs: Vec<_> = p.get_custom_section_relocations_ref()[got]
340 .iter()
341 .map(|v| (v.reloc_target, v.offset))
342 .collect();
343 let got_base = custom_sections[got].0 as usize;
344 Box::new(move |t: RelocationTarget| {
345 relocs
346 .iter()
347 .find(|(v, _)| v == &t)
348 .map(|(_, o)| got_base + (*o as usize))
349 })
350 } else {
351 Box::new(|_: RelocationTarget| None)
352 }
353 }
354
355 ArtifactBuildVariant::Archived(p) => {
356 if let Some(got) = p.get_got_ref().index {
357 let relocs: Vec<_> = p.get_custom_section_relocations_ref()[got]
358 .iter()
359 .map(|v| (v.reloc_target(), v.offset))
360 .collect();
361 let got_base = custom_sections[got].0 as usize;
362 Box::new(move |t: RelocationTarget| {
363 relocs
364 .iter()
365 .find(|(v, _)| v == &t)
366 .map(|(_, o)| got_base + (o.to_native() as usize))
367 })
368 } else {
369 Box::new(|_: RelocationTarget| None)
370 }
371 }
372 };
373
374 match &artifact {
375 ArtifactBuildVariant::Plain(p) => link_module(
376 module_info,
377 &finished_functions,
378 &finished_dynamic_function_trampolines,
379 p.get_function_relocations()
380 .iter()
381 .map(|(k, v)| (k, v.iter())),
382 &custom_sections,
383 p.get_custom_section_relocations_ref()
384 .iter()
385 .map(|(k, v)| (k, v.iter())),
386 p.get_libcall_trampolines(),
387 p.get_libcall_trampoline_len(),
388 &get_got_address,
389 ),
390 ArtifactBuildVariant::Archived(a) => link_module(
391 module_info,
392 &finished_functions,
393 &finished_dynamic_function_trampolines,
394 a.get_function_relocations()
395 .iter()
396 .map(|(k, v)| (k, v.iter())),
397 &custom_sections,
398 a.get_custom_section_relocations_ref()
399 .iter()
400 .map(|(k, v)| (k, v.iter())),
401 a.get_libcall_trampolines(),
402 a.get_libcall_trampoline_len(),
403 &get_got_address,
404 ),
405 };
406
407 let signatures = {
409 let signature_registry = engine_inner.signatures();
410 module_info
411 .signatures
412 .values()
413 .zip(module_info.signature_hashes.values())
414 .map(|(sig, sig_hash)| signature_registry.register(sig, *sig_hash))
415 .collect::<PrimaryMap<_, _>>()
416 };
417
418 #[allow(unused_variables)]
419 let eh_frame = match &artifact {
420 ArtifactBuildVariant::Plain(p) => p.get_unwind_info().eh_frame.map(|v| unsafe {
421 std::slice::from_raw_parts(
422 *custom_sections[v],
423 p.get_custom_sections_ref()[v].bytes.len(),
424 )
425 }),
426 ArtifactBuildVariant::Archived(a) => a.get_unwind_info().eh_frame.map(|v| unsafe {
427 std::slice::from_raw_parts(
428 *custom_sections[v],
429 a.get_custom_sections_ref()[v].bytes.len(),
430 )
431 }),
432 };
433 #[allow(unused_variables)]
434 let compact_unwind = match &artifact {
435 ArtifactBuildVariant::Plain(p) => p.get_unwind_info().compact_unwind.map(|v| unsafe {
436 std::slice::from_raw_parts(
437 *custom_sections[v],
438 p.get_custom_sections_ref()[v].bytes.len(),
439 )
440 }),
441 ArtifactBuildVariant::Archived(a) => {
442 a.get_unwind_info().compact_unwind.map(|v| unsafe {
443 std::slice::from_raw_parts(
444 *custom_sections[v],
445 a.get_custom_sections_ref()[v].bytes.len(),
446 )
447 })
448 }
449 };
450
451 #[cfg(all(not(target_arch = "wasm32"), feature = "compiler"))]
452 {
453 engine_inner.register_perfmap(&finished_functions, module_info)?;
454 }
455
456 engine_inner.publish_compiled_code();
458
459 #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
460 if let Some(compact_unwind) = compact_unwind {
461 engine_inner.publish_compact_unwind(
462 compact_unwind,
463 get_got_address(RelocationTarget::LibCall(wasmer_vm::LibCall::EHPersonality)),
464 )?;
465 }
466 #[cfg(not(any(
467 target_arch = "wasm32",
468 all(target_os = "macos", target_arch = "aarch64")
469 )))]
470 engine_inner.publish_eh_frame(eh_frame)?;
471
472 drop(get_got_address);
473
474 let finished_function_lengths = finished_functions
475 .values()
476 .map(|extent| extent.length)
477 .collect::<PrimaryMap<LocalFunctionIndex, usize>>()
478 .into_boxed_slice();
479 let finished_functions = finished_functions
480 .values()
481 .map(|extent| extent.ptr)
482 .collect::<PrimaryMap<LocalFunctionIndex, FunctionBodyPtr>>()
483 .into_boxed_slice();
484 let finished_function_call_trampolines =
485 finished_function_call_trampolines.into_boxed_slice();
486 let finished_dynamic_function_trampolines =
487 finished_dynamic_function_trampolines.into_boxed_slice();
488 let signatures = signatures.into_boxed_slice();
489
490 let mut artifact = Self {
491 id: Default::default(),
492 artifact,
493 allocated: Some(AllocatedArtifact {
494 frame_info_registered: false,
495 frame_info_registration: None,
496 finished_functions,
497 finished_function_call_trampolines,
498 finished_dynamic_function_trampolines,
499 signatures,
500 finished_function_lengths,
501 }),
502 };
503
504 artifact
505 .internal_register_frame_info()
506 .map_err(|e| DeserializeError::CorruptedBinary(format!("{e:?}")))?;
507 if let Some(frame_info) = artifact.internal_take_frame_info_registration() {
508 engine_inner.register_frame_info(frame_info);
509 }
510
511 Ok(artifact)
512 }
513
514 pub fn is_deserializable(bytes: &[u8]) -> bool {
516 ArtifactBuild::is_deserializable(bytes)
517 }
518}
519
520impl PartialEq for Artifact {
521 fn eq(&self, other: &Self) -> bool {
522 self.id == other.id
523 }
524}
525impl Eq for Artifact {}
526
527impl std::fmt::Debug for Artifact {
528 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
529 f.debug_struct("Artifact")
530 .field("artifact_id", &self.id)
531 .field("module_info", &self.module_info())
532 .finish()
533 }
534}
535
536impl<'a> ArtifactCreate<'a> for Artifact {
537 type OwnedDataInitializer = <ArtifactBuildVariant as ArtifactCreate<'a>>::OwnedDataInitializer;
538 type OwnedDataInitializerIterator =
539 <ArtifactBuildVariant as ArtifactCreate<'a>>::OwnedDataInitializerIterator;
540
541 fn set_module_info_name(&mut self, name: String) -> bool {
542 self.artifact.set_module_info_name(name)
543 }
544
545 fn create_module_info(&self) -> Arc<ModuleInfo> {
546 self.artifact.create_module_info()
547 }
548
549 fn module_info(&self) -> &ModuleInfo {
550 self.artifact.module_info()
551 }
552
553 fn features(&self) -> &Features {
554 self.artifact.features()
555 }
556
557 fn cpu_features(&self) -> EnumSet<CpuFeature> {
558 self.artifact.cpu_features()
559 }
560
561 fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
562 self.artifact.data_initializers()
563 }
564
565 fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
566 self.artifact.memory_styles()
567 }
568
569 fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
570 self.artifact.table_styles()
571 }
572
573 fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
574 self.artifact.serialize()
575 }
576}
577
578impl<'a> ArtifactCreate<'a> for ArtifactBuildVariant {
579 type OwnedDataInitializer = OwnedDataInitializerVariant<'a>;
580 type OwnedDataInitializerIterator = IntoIter<Self::OwnedDataInitializer>;
581
582 fn create_module_info(&self) -> Arc<ModuleInfo> {
583 match self {
584 Self::Plain(artifact) => artifact.create_module_info(),
585 Self::Archived(artifact) => artifact.create_module_info(),
586 }
587 }
588
589 fn set_module_info_name(&mut self, name: String) -> bool {
590 match self {
591 Self::Plain(artifact) => artifact.set_module_info_name(name),
592 Self::Archived(artifact) => artifact.set_module_info_name(name),
593 }
594 }
595
596 fn module_info(&self) -> &ModuleInfo {
597 match self {
598 Self::Plain(artifact) => artifact.module_info(),
599 Self::Archived(artifact) => artifact.module_info(),
600 }
601 }
602
603 fn features(&self) -> &Features {
604 match self {
605 Self::Plain(artifact) => artifact.features(),
606 Self::Archived(artifact) => artifact.features(),
607 }
608 }
609
610 fn cpu_features(&self) -> EnumSet<CpuFeature> {
611 match self {
612 Self::Plain(artifact) => artifact.cpu_features(),
613 Self::Archived(artifact) => artifact.cpu_features(),
614 }
615 }
616
617 fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
618 match self {
619 Self::Plain(artifact) => artifact.memory_styles(),
620 Self::Archived(artifact) => artifact.memory_styles(),
621 }
622 }
623
624 fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
625 match self {
626 Self::Plain(artifact) => artifact.table_styles(),
627 Self::Archived(artifact) => artifact.table_styles(),
628 }
629 }
630
631 fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
632 match self {
633 Self::Plain(artifact) => artifact
634 .data_initializers()
635 .map(OwnedDataInitializerVariant::Plain)
636 .collect::<Vec<_>>()
637 .into_iter(),
638 Self::Archived(artifact) => artifact
639 .data_initializers()
640 .map(OwnedDataInitializerVariant::Archived)
641 .collect::<Vec<_>>()
642 .into_iter(),
643 }
644 }
645
646 fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
647 match self {
648 Self::Plain(artifact) => artifact.serialize(),
649 Self::Archived(artifact) => artifact.serialize(),
650 }
651 }
652}
653
654#[derive(Clone, Copy)]
655pub enum OwnedDataInitializerVariant<'a> {
656 Plain(&'a OwnedDataInitializer),
657 Archived(&'a ArchivedOwnedDataInitializer),
658}
659
660impl<'a> DataInitializerLike<'a> for OwnedDataInitializerVariant<'a> {
661 type Location = DataInitializerLocationVariant<'a>;
662
663 fn location(&self) -> Self::Location {
664 match self {
665 Self::Plain(plain) => DataInitializerLocationVariant::Plain(plain.location()),
666 Self::Archived(archived) => {
667 DataInitializerLocationVariant::Archived(archived.location())
668 }
669 }
670 }
671
672 fn data(&self) -> &'a [u8] {
673 match self {
674 Self::Plain(plain) => plain.data(),
675 Self::Archived(archived) => archived.data(),
676 }
677 }
678}
679
680#[derive(Clone, Copy)]
681pub enum DataInitializerLocationVariant<'a> {
682 Plain(&'a DataInitializerLocation),
683 Archived(&'a ArchivedDataInitializerLocation),
684}
685
686impl DataInitializerLocationVariant<'_> {
687 pub fn clone_to_plain(&self) -> DataInitializerLocation {
688 match self {
689 Self::Plain(p) => (*p).clone(),
690 Self::Archived(a) => DataInitializerLocation {
691 memory_index: a.memory_index(),
692 offset_expr: a.offset_expr(),
693 },
694 }
695 }
696}
697
698impl DataInitializerLocationLike for DataInitializerLocationVariant<'_> {
699 fn memory_index(&self) -> MemoryIndex {
700 match self {
701 Self::Plain(plain) => plain.memory_index(),
702 Self::Archived(archived) => archived.memory_index(),
703 }
704 }
705
706 fn offset_expr(&self) -> wasmer_types::InitExpr {
707 match self {
708 Self::Plain(plain) => plain.offset_expr(),
709 Self::Archived(archived) => archived.offset_expr(),
710 }
711 }
712}
713
714impl Artifact {
715 fn internal_register_frame_info(&mut self) -> Result<(), DeserializeError> {
716 if self
717 .allocated
718 .as_ref()
719 .expect("It must be allocated")
720 .frame_info_registered
721 {
722 return Ok(()); }
724
725 let finished_function_extents = self
726 .allocated
727 .as_ref()
728 .expect("It must be allocated")
729 .finished_functions
730 .values()
731 .copied()
732 .zip(
733 self.allocated
734 .as_ref()
735 .expect("It must be allocated")
736 .finished_function_lengths
737 .values()
738 .copied(),
739 )
740 .map(|(ptr, length)| FunctionExtent { ptr, length })
741 .collect::<PrimaryMap<LocalFunctionIndex, _>>()
742 .into_boxed_slice();
743
744 let frame_info_registration = &mut self
745 .allocated
746 .as_mut()
747 .expect("It must be allocated")
748 .frame_info_registration;
749
750 *frame_info_registration = register_frame_info(
751 self.artifact.create_module_info(),
752 &finished_function_extents,
753 match &self.artifact {
754 ArtifactBuildVariant::Plain(p) => {
755 FrameInfosVariant::Owned(p.get_frame_info_ref().clone())
756 }
757 ArtifactBuildVariant::Archived(a) => FrameInfosVariant::Archived(a.clone()),
758 },
759 );
760
761 self.allocated
762 .as_mut()
763 .expect("It must be allocated")
764 .frame_info_registered = true;
765
766 Ok(())
767 }
768
769 fn internal_take_frame_info_registration(&mut self) -> Option<GlobalFrameInfoRegistration> {
770 let frame_info_registration = &mut self
771 .allocated
772 .as_mut()
773 .expect("It must be allocated")
774 .frame_info_registration;
775
776 frame_info_registration.take()
777 }
778
779 pub fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> {
782 &self
783 .allocated
784 .as_ref()
785 .expect("It must be allocated")
786 .finished_functions
787 }
788
789 pub fn finished_function_call_trampolines(&self) -> &BoxedSlice<SignatureIndex, VMTrampoline> {
792 &self
793 .allocated
794 .as_ref()
795 .expect("It must be allocated")
796 .finished_function_call_trampolines
797 }
798
799 pub fn finished_dynamic_function_trampolines(
802 &self,
803 ) -> &BoxedSlice<FunctionIndex, FunctionBodyPtr> {
804 &self
805 .allocated
806 .as_ref()
807 .expect("It must be allocated")
808 .finished_dynamic_function_trampolines
809 }
810
811 pub fn signatures(&self) -> &BoxedSlice<SignatureIndex, VMSignatureHash> {
813 &self
814 .allocated
815 .as_ref()
816 .expect("It must be allocated")
817 .signatures
818 }
819
820 #[allow(clippy::result_large_err)]
822 pub fn preinstantiate(&self) -> Result<(), InstantiationError> {
823 Ok(())
824 }
825
826 #[allow(clippy::result_large_err)]
832 pub unsafe fn instantiate(
833 &self,
834 tunables: &dyn Tunables,
835 imports: &[VMExtern],
836 context: &mut StoreObjects,
837 ) -> Result<VMInstance, InstantiationError> {
838 unsafe {
839 let host_cpu_features = CpuFeature::for_host();
842 if !host_cpu_features.is_superset(self.cpu_features()) {
843 return Err(InstantiationError::CpuFeature(format!(
844 "{:?}",
845 self.cpu_features().difference(host_cpu_features)
846 )));
847 }
848
849 self.preinstantiate()?;
850
851 let module = self.create_module_info();
852
853 let tags = resolve_tags(&module, imports, context).map_err(InstantiationError::Link)?;
854
855 let imports = resolve_imports(
856 &module,
857 imports,
858 context,
859 self.finished_dynamic_function_trampolines(),
860 self.memory_styles(),
861 self.table_styles(),
862 )
863 .map_err(InstantiationError::Link)?;
864
865 let (
869 allocator,
870 memory_definition_locations,
871 table_definition_locations,
872 global_definition_locations,
873 ) = InstanceAllocator::new(&module);
874 let finished_memories = tunables
875 .create_memories(
876 context,
877 &module,
878 self.memory_styles(),
879 &memory_definition_locations,
880 )
881 .map_err(InstantiationError::Link)?
882 .into_boxed_slice();
883 let finished_tables = tunables
884 .create_tables(
885 context,
886 &module,
887 self.table_styles(),
888 &table_definition_locations,
889 )
890 .map_err(InstantiationError::Link)?
891 .into_boxed_slice();
892 let finished_globals = tunables
893 .create_globals(context, &module, &global_definition_locations)
894 .map_err(InstantiationError::Link)?
895 .into_boxed_slice();
896
897 let handle = VMInstance::new(
898 allocator,
899 module,
900 context,
901 self.finished_functions().clone(),
902 self.finished_function_call_trampolines().clone(),
903 finished_memories,
904 finished_tables,
905 finished_globals,
906 tags,
907 imports,
908 self.signatures().clone(),
909 )
910 .map_err(InstantiationError::Start)?;
911 Ok(handle)
912 }
913 }
914
915 #[allow(clippy::result_large_err)]
921 pub unsafe fn finish_instantiation(
922 &self,
923 config: &VMConfig,
924 trap_handler: Option<*const TrapHandlerFn<'static>>,
925 handle: &mut VMInstance,
926 ) -> Result<(), InstantiationError> {
927 unsafe {
928 let data_initializers = self
929 .data_initializers()
930 .map(|init| DataInitializer {
931 location: init.location().clone_to_plain(),
932 data: init.data(),
933 })
934 .collect::<Vec<_>>();
935 handle
936 .finish_instantiation(config, trap_handler, &data_initializers)
937 .map_err(InstantiationError::Start)
938 }
939 }
940
941 #[allow(clippy::type_complexity)]
942 #[cfg(feature = "static-artifact-create")]
943 pub fn generate_metadata<'data>(
945 data: &'data [u8],
946 compiler: &dyn Compiler,
947 tunables: &dyn Tunables,
948 features: &Features,
949 ) -> Result<
950 (
951 CompileModuleInfo,
952 PrimaryMap<LocalFunctionIndex, FunctionBodyData<'data>>,
953 Vec<DataInitializer<'data>>,
954 Option<ModuleTranslationState>,
955 ),
956 CompileError,
957 > {
958 let environ = ModuleEnvironment::new();
959 let translation = environ.translate(data).map_err(CompileError::Wasm)?;
960
961 use crate::translator::ModuleMiddlewareChain;
963 let mut module = translation.module;
964 let middlewares = compiler.get_middlewares();
965 middlewares
966 .apply_on_module_info(&mut module)
967 .map_err(|e| CompileError::MiddlewareError(e.to_string()))?;
968
969 let memory_styles: PrimaryMap<MemoryIndex, MemoryStyle> = module
970 .memories
971 .values()
972 .map(|memory_type| tunables.memory_style(memory_type))
973 .collect();
974 let table_styles: PrimaryMap<TableIndex, TableStyle> = module
975 .tables
976 .values()
977 .map(|table_type| tunables.table_style(table_type))
978 .collect();
979
980 let compile_info = CompileModuleInfo {
981 module: Arc::new(module),
982 features: features.clone(),
983 memory_styles,
984 table_styles,
985 };
986 Ok((
987 compile_info,
988 translation.function_body_inputs,
989 translation.data_initializers,
990 translation.module_translation_state,
991 ))
992 }
993
994 #[cfg(feature = "static-artifact-create")]
996 #[allow(clippy::type_complexity)]
997 pub fn metadata<'a>(
998 compiler: &dyn Compiler,
999 data: &'a [u8],
1000 metadata_prefix: Option<&str>,
1001 target: &Target,
1002 tunables: &dyn Tunables,
1003 features: &Features,
1004 ) -> Result<
1005 (
1006 ModuleMetadata,
1007 Option<ModuleTranslationState>,
1008 PrimaryMap<LocalFunctionIndex, FunctionBodyData<'a>>,
1009 ),
1010 CompileError,
1011 > {
1012 #[allow(dead_code)]
1013 let (compile_info, function_body_inputs, data_initializers, module_translation) =
1014 Self::generate_metadata(data, compiler, tunables, features)?;
1015
1016 let data_initializers = data_initializers
1017 .iter()
1018 .map(OwnedDataInitializer::new)
1019 .collect::<Vec<_>>()
1020 .into_boxed_slice();
1021
1022 let function_body_lengths = function_body_inputs
1026 .keys()
1027 .map(|_function_body| 0u64)
1028 .collect::<PrimaryMap<LocalFunctionIndex, u64>>();
1029
1030 let metadata = ModuleMetadata {
1031 compile_info,
1032 prefix: metadata_prefix.map(|s| s.to_string()).unwrap_or_default(),
1033 data_initializers,
1034 function_body_lengths,
1035 cpu_features: target.cpu_features().as_u64(),
1036 };
1037
1038 Ok((metadata, module_translation, function_body_inputs))
1039 }
1040
1041 #[cfg(feature = "static-artifact-create")]
1049 pub fn generate_object<'data>(
1050 compiler: &dyn Compiler,
1051 data: &[u8],
1052 metadata_prefix: Option<&str>,
1053 target: &'data Target,
1054 tunables: &dyn Tunables,
1055 features: &Features,
1056 ) -> Result<
1057 (
1058 ModuleInfo,
1059 Object<'data>,
1060 usize,
1061 Box<dyn crate::types::symbols::SymbolRegistry>,
1062 ),
1063 CompileError,
1064 > {
1065 use crate::types::symbols::{ModuleMetadataSymbolRegistry, SymbolRegistry};
1066
1067 fn to_compile_error(err: impl std::error::Error) -> CompileError {
1068 CompileError::Codegen(format!("{err}"))
1069 }
1070
1071 let target_triple = target.triple();
1072 let (mut metadata, module_translation, function_body_inputs) =
1073 Self::metadata(compiler, data, metadata_prefix, target, tunables, features)
1074 .map_err(to_compile_error)?;
1075
1076 let mut metadata_builder =
1094 ObjectMetadataBuilder::new(&metadata, target_triple).map_err(to_compile_error)?;
1095
1096 let (_compile_info, symbol_registry) = metadata.split();
1097
1098 let compilation: crate::types::function::Compilation = compiler.compile_module(
1099 target,
1100 &metadata.compile_info,
1101 module_translation.as_ref().unwrap(),
1102 function_body_inputs,
1103 None,
1104 )?;
1105 let mut obj = get_object_for_target(target_triple).map_err(to_compile_error)?;
1106
1107 let object_name = ModuleMetadataSymbolRegistry {
1108 prefix: metadata_prefix.unwrap_or_default().to_string(),
1109 }
1110 .symbol_to_name(crate::types::symbols::Symbol::Metadata);
1111
1112 let default_align = match target_triple.architecture {
1113 target_lexicon::Architecture::Aarch64(_) => {
1114 if matches!(
1115 target_triple.operating_system,
1116 target_lexicon::OperatingSystem::Darwin(_)
1117 ) {
1118 8
1119 } else {
1120 4
1121 }
1122 }
1123 _ => 1,
1124 };
1125
1126 let offset = emit_data(
1129 &mut obj,
1130 object_name.as_bytes(),
1131 metadata_builder.placeholder_data(),
1132 std::cmp::max(8, default_align),
1133 )
1134 .map_err(to_compile_error)?;
1135 metadata_builder.set_section_offset(offset);
1136
1137 emit_compilation(
1138 &mut obj,
1139 compilation,
1140 &symbol_registry,
1141 target_triple,
1142 &metadata_builder,
1143 )
1144 .map_err(to_compile_error)?;
1145 Ok((
1146 Arc::try_unwrap(metadata.compile_info.module).unwrap(),
1147 obj,
1148 metadata_builder.placeholder_data().len(),
1149 Box::new(symbol_registry),
1150 ))
1151 }
1152
1153 #[cfg(not(feature = "static-artifact-load"))]
1158 pub unsafe fn deserialize_object(
1159 _engine: &Engine,
1160 _bytes: OwnedBuffer,
1161 ) -> Result<Self, DeserializeError> {
1162 Err(DeserializeError::Compiler(
1163 CompileError::UnsupportedFeature("static load is not compiled in".to_string()),
1164 ))
1165 }
1166
1167 fn get_byte_slice(input: &[u8], start: usize, end: usize) -> Result<&[u8], DeserializeError> {
1168 if (start == end && input.len() > start)
1169 || (start < end && input.len() > start && input.len() >= end)
1170 {
1171 Ok(&input[start..end])
1172 } else {
1173 Err(DeserializeError::InvalidByteLength {
1174 expected: end - start,
1175 got: input.len(),
1176 })
1177 }
1178 }
1179
1180 #[cfg(feature = "static-artifact-load")]
1185 pub unsafe fn deserialize_object(
1186 engine: &Engine,
1187 bytes: OwnedBuffer,
1188 ) -> Result<Self, DeserializeError> {
1189 unsafe {
1190 let bytes = bytes.as_slice();
1191 let metadata_len = MetadataHeader::parse(bytes)?;
1192 let metadata_slice = Self::get_byte_slice(bytes, MetadataHeader::LEN, bytes.len())?;
1193 let metadata_slice = Self::get_byte_slice(metadata_slice, 0, metadata_len)?;
1194 let metadata: ModuleMetadata = ModuleMetadata::deserialize(metadata_slice)?;
1195
1196 const WORD_SIZE: usize = mem::size_of::<usize>();
1197 let mut byte_buffer = [0u8; WORD_SIZE];
1198
1199 let mut cur_offset = MetadataHeader::LEN + metadata_len;
1200
1201 let byte_buffer_slice =
1202 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1203 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1204 cur_offset += WORD_SIZE;
1205
1206 let num_finished_functions = usize::from_ne_bytes(byte_buffer);
1207 let mut finished_functions: PrimaryMap<LocalFunctionIndex, FunctionBodyPtr> =
1208 PrimaryMap::new();
1209
1210 let engine_inner = engine.inner();
1211 let signature_registry = engine_inner.signatures();
1212
1213 for _i in 0..num_finished_functions {
1215 let byte_buffer_slice =
1216 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1217 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1218 let fp = FunctionBodyPtr(usize::from_ne_bytes(byte_buffer) as _);
1219 cur_offset += WORD_SIZE;
1220
1221 finished_functions.push(fp);
1223 }
1224
1225 let signatures = {
1227 let module = &metadata.compile_info.module;
1228 module
1229 .signatures
1230 .values()
1231 .zip(module.signature_hashes.values())
1232 .map(|(sig, sig_hash)| signature_registry.register(sig, *sig_hash))
1233 .collect::<PrimaryMap<_, _>>()
1234 };
1235
1236 let mut finished_function_call_trampolines = PrimaryMap::new();
1238
1239 let byte_buffer_slice =
1240 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1241 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1242 cur_offset += WORD_SIZE;
1243 let num_function_trampolines = usize::from_ne_bytes(byte_buffer);
1244 for _ in 0..num_function_trampolines {
1245 let byte_buffer_slice =
1246 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1247 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1248 cur_offset += WORD_SIZE;
1249 let trampoline_ptr_bytes = usize::from_ne_bytes(byte_buffer);
1250 let trampoline = mem::transmute::<usize, VMTrampoline>(trampoline_ptr_bytes);
1251 finished_function_call_trampolines.push(trampoline);
1252 }
1254
1255 let mut finished_dynamic_function_trampolines = PrimaryMap::new();
1257 let byte_buffer_slice =
1258 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1259 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1260 cur_offset += WORD_SIZE;
1261 let num_dynamic_trampoline_functions = usize::from_ne_bytes(byte_buffer);
1262 for _i in 0..num_dynamic_trampoline_functions {
1263 let byte_buffer_slice =
1264 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1265 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1266 let fp = FunctionBodyPtr(usize::from_ne_bytes(byte_buffer) as _);
1267 cur_offset += WORD_SIZE;
1268
1269 finished_dynamic_function_trampolines.push(fp);
1272 }
1273
1274 let artifact = ArtifactBuild::from_serializable(SerializableModule {
1275 compilation: SerializableCompilation::default(),
1276 compile_info: metadata.compile_info,
1277 data_initializers: metadata.data_initializers,
1278 cpu_features: metadata.cpu_features,
1279 });
1280
1281 let finished_function_lengths = finished_functions
1282 .values()
1283 .map(|_| 0)
1284 .collect::<PrimaryMap<LocalFunctionIndex, usize>>()
1285 .into_boxed_slice();
1286
1287 Ok(Self {
1288 id: Default::default(),
1289 artifact: ArtifactBuildVariant::Plain(artifact),
1290 allocated: Some(AllocatedArtifact {
1291 frame_info_registered: false,
1292 frame_info_registration: None,
1293 finished_functions: finished_functions.into_boxed_slice(),
1294 finished_function_call_trampolines: finished_function_call_trampolines
1295 .into_boxed_slice(),
1296 finished_dynamic_function_trampolines: finished_dynamic_function_trampolines
1297 .into_boxed_slice(),
1298 signatures: signatures.into_boxed_slice(),
1299 finished_function_lengths,
1300 }),
1301 })
1302 }
1303 }
1304}