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