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