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, VMSharedSignatureIndex, 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, VMSharedSignatureIndex>,
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 .map(|sig| signature_registry.register(sig))
414 .collect::<PrimaryMap<_, _>>()
415 };
416
417 #[allow(unused_variables)]
418 let eh_frame = match &artifact {
419 ArtifactBuildVariant::Plain(p) => p.get_unwind_info().eh_frame.map(|v| unsafe {
420 std::slice::from_raw_parts(
421 *custom_sections[v],
422 p.get_custom_sections_ref()[v].bytes.len(),
423 )
424 }),
425 ArtifactBuildVariant::Archived(a) => a.get_unwind_info().eh_frame.map(|v| unsafe {
426 std::slice::from_raw_parts(
427 *custom_sections[v],
428 a.get_custom_sections_ref()[v].bytes.len(),
429 )
430 }),
431 };
432 #[allow(unused_variables)]
433 let compact_unwind = match &artifact {
434 ArtifactBuildVariant::Plain(p) => p.get_unwind_info().compact_unwind.map(|v| unsafe {
435 std::slice::from_raw_parts(
436 *custom_sections[v],
437 p.get_custom_sections_ref()[v].bytes.len(),
438 )
439 }),
440 ArtifactBuildVariant::Archived(a) => {
441 a.get_unwind_info().compact_unwind.map(|v| unsafe {
442 std::slice::from_raw_parts(
443 *custom_sections[v],
444 a.get_custom_sections_ref()[v].bytes.len(),
445 )
446 })
447 }
448 };
449
450 #[cfg(all(not(target_arch = "wasm32"), feature = "compiler"))]
451 {
452 engine_inner.register_perfmap(&finished_functions, module_info)?;
453 }
454
455 engine_inner.publish_compiled_code();
457
458 #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
459 if let Some(compact_unwind) = compact_unwind {
460 engine_inner.publish_compact_unwind(
461 compact_unwind,
462 get_got_address(RelocationTarget::LibCall(wasmer_vm::LibCall::EHPersonality)),
463 )?;
464 }
465 #[cfg(not(any(
466 target_arch = "wasm32",
467 all(target_os = "macos", target_arch = "aarch64")
468 )))]
469 engine_inner.publish_eh_frame(eh_frame)?;
470
471 drop(get_got_address);
472
473 let finished_function_lengths = finished_functions
474 .values()
475 .map(|extent| extent.length)
476 .collect::<PrimaryMap<LocalFunctionIndex, usize>>()
477 .into_boxed_slice();
478 let finished_functions = finished_functions
479 .values()
480 .map(|extent| extent.ptr)
481 .collect::<PrimaryMap<LocalFunctionIndex, FunctionBodyPtr>>()
482 .into_boxed_slice();
483 let finished_function_call_trampolines =
484 finished_function_call_trampolines.into_boxed_slice();
485 let finished_dynamic_function_trampolines =
486 finished_dynamic_function_trampolines.into_boxed_slice();
487 let signatures = signatures.into_boxed_slice();
488
489 let mut artifact = Self {
490 id: Default::default(),
491 artifact,
492 allocated: Some(AllocatedArtifact {
493 frame_info_registered: false,
494 frame_info_registration: None,
495 finished_functions,
496 finished_function_call_trampolines,
497 finished_dynamic_function_trampolines,
498 signatures,
499 finished_function_lengths,
500 }),
501 };
502
503 artifact
504 .internal_register_frame_info()
505 .map_err(|e| DeserializeError::CorruptedBinary(format!("{e:?}")))?;
506 if let Some(frame_info) = artifact.internal_take_frame_info_registration() {
507 engine_inner.register_frame_info(frame_info);
508 }
509
510 Ok(artifact)
511 }
512
513 pub fn is_deserializable(bytes: &[u8]) -> bool {
515 ArtifactBuild::is_deserializable(bytes)
516 }
517}
518
519impl PartialEq for Artifact {
520 fn eq(&self, other: &Self) -> bool {
521 self.id == other.id
522 }
523}
524impl Eq for Artifact {}
525
526impl std::fmt::Debug for Artifact {
527 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
528 f.debug_struct("Artifact")
529 .field("artifact_id", &self.id)
530 .field("module_info", &self.module_info())
531 .finish()
532 }
533}
534
535impl<'a> ArtifactCreate<'a> for Artifact {
536 type OwnedDataInitializer = <ArtifactBuildVariant as ArtifactCreate<'a>>::OwnedDataInitializer;
537 type OwnedDataInitializerIterator =
538 <ArtifactBuildVariant as ArtifactCreate<'a>>::OwnedDataInitializerIterator;
539
540 fn set_module_info_name(&mut self, name: String) -> bool {
541 self.artifact.set_module_info_name(name)
542 }
543
544 fn create_module_info(&self) -> Arc<ModuleInfo> {
545 self.artifact.create_module_info()
546 }
547
548 fn module_info(&self) -> &ModuleInfo {
549 self.artifact.module_info()
550 }
551
552 fn features(&self) -> &Features {
553 self.artifact.features()
554 }
555
556 fn cpu_features(&self) -> EnumSet<CpuFeature> {
557 self.artifact.cpu_features()
558 }
559
560 fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
561 self.artifact.data_initializers()
562 }
563
564 fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
565 self.artifact.memory_styles()
566 }
567
568 fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
569 self.artifact.table_styles()
570 }
571
572 fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
573 self.artifact.serialize()
574 }
575}
576
577impl<'a> ArtifactCreate<'a> for ArtifactBuildVariant {
578 type OwnedDataInitializer = OwnedDataInitializerVariant<'a>;
579 type OwnedDataInitializerIterator = IntoIter<Self::OwnedDataInitializer>;
580
581 fn create_module_info(&self) -> Arc<ModuleInfo> {
582 match self {
583 Self::Plain(artifact) => artifact.create_module_info(),
584 Self::Archived(artifact) => artifact.create_module_info(),
585 }
586 }
587
588 fn set_module_info_name(&mut self, name: String) -> bool {
589 match self {
590 Self::Plain(artifact) => artifact.set_module_info_name(name),
591 Self::Archived(artifact) => artifact.set_module_info_name(name),
592 }
593 }
594
595 fn module_info(&self) -> &ModuleInfo {
596 match self {
597 Self::Plain(artifact) => artifact.module_info(),
598 Self::Archived(artifact) => artifact.module_info(),
599 }
600 }
601
602 fn features(&self) -> &Features {
603 match self {
604 Self::Plain(artifact) => artifact.features(),
605 Self::Archived(artifact) => artifact.features(),
606 }
607 }
608
609 fn cpu_features(&self) -> EnumSet<CpuFeature> {
610 match self {
611 Self::Plain(artifact) => artifact.cpu_features(),
612 Self::Archived(artifact) => artifact.cpu_features(),
613 }
614 }
615
616 fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
617 match self {
618 Self::Plain(artifact) => artifact.memory_styles(),
619 Self::Archived(artifact) => artifact.memory_styles(),
620 }
621 }
622
623 fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
624 match self {
625 Self::Plain(artifact) => artifact.table_styles(),
626 Self::Archived(artifact) => artifact.table_styles(),
627 }
628 }
629
630 fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
631 match self {
632 Self::Plain(artifact) => artifact
633 .data_initializers()
634 .map(OwnedDataInitializerVariant::Plain)
635 .collect::<Vec<_>>()
636 .into_iter(),
637 Self::Archived(artifact) => artifact
638 .data_initializers()
639 .map(OwnedDataInitializerVariant::Archived)
640 .collect::<Vec<_>>()
641 .into_iter(),
642 }
643 }
644
645 fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
646 match self {
647 Self::Plain(artifact) => artifact.serialize(),
648 Self::Archived(artifact) => artifact.serialize(),
649 }
650 }
651}
652
653#[derive(Clone, Copy)]
654pub enum OwnedDataInitializerVariant<'a> {
655 Plain(&'a OwnedDataInitializer),
656 Archived(&'a ArchivedOwnedDataInitializer),
657}
658
659impl<'a> DataInitializerLike<'a> for OwnedDataInitializerVariant<'a> {
660 type Location = DataInitializerLocationVariant<'a>;
661
662 fn location(&self) -> Self::Location {
663 match self {
664 Self::Plain(plain) => DataInitializerLocationVariant::Plain(plain.location()),
665 Self::Archived(archived) => {
666 DataInitializerLocationVariant::Archived(archived.location())
667 }
668 }
669 }
670
671 fn data(&self) -> &'a [u8] {
672 match self {
673 Self::Plain(plain) => plain.data(),
674 Self::Archived(archived) => archived.data(),
675 }
676 }
677}
678
679#[derive(Clone, Copy)]
680pub enum DataInitializerLocationVariant<'a> {
681 Plain(&'a DataInitializerLocation),
682 Archived(&'a ArchivedDataInitializerLocation),
683}
684
685impl DataInitializerLocationVariant<'_> {
686 pub fn clone_to_plain(&self) -> DataInitializerLocation {
687 match self {
688 Self::Plain(p) => (*p).clone(),
689 Self::Archived(a) => DataInitializerLocation {
690 memory_index: a.memory_index(),
691 base: a.base(),
692 offset: a.offset(),
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 base(&self) -> Option<wasmer_types::GlobalIndex> {
707 match self {
708 Self::Plain(plain) => plain.base(),
709 Self::Archived(archived) => archived.base(),
710 }
711 }
712
713 fn offset(&self) -> usize {
714 match self {
715 Self::Plain(plain) => plain.offset(),
716 Self::Archived(archived) => archived.offset(),
717 }
718 }
719}
720
721impl Artifact {
722 fn internal_register_frame_info(&mut self) -> Result<(), DeserializeError> {
723 if self
724 .allocated
725 .as_ref()
726 .expect("It must be allocated")
727 .frame_info_registered
728 {
729 return Ok(()); }
731
732 let finished_function_extents = self
733 .allocated
734 .as_ref()
735 .expect("It must be allocated")
736 .finished_functions
737 .values()
738 .copied()
739 .zip(
740 self.allocated
741 .as_ref()
742 .expect("It must be allocated")
743 .finished_function_lengths
744 .values()
745 .copied(),
746 )
747 .map(|(ptr, length)| FunctionExtent { ptr, length })
748 .collect::<PrimaryMap<LocalFunctionIndex, _>>()
749 .into_boxed_slice();
750
751 let frame_info_registration = &mut self
752 .allocated
753 .as_mut()
754 .expect("It must be allocated")
755 .frame_info_registration;
756
757 *frame_info_registration = register_frame_info(
758 self.artifact.create_module_info(),
759 &finished_function_extents,
760 match &self.artifact {
761 ArtifactBuildVariant::Plain(p) => {
762 FrameInfosVariant::Owned(p.get_frame_info_ref().clone())
763 }
764 ArtifactBuildVariant::Archived(a) => FrameInfosVariant::Archived(a.clone()),
765 },
766 );
767
768 self.allocated
769 .as_mut()
770 .expect("It must be allocated")
771 .frame_info_registered = true;
772
773 Ok(())
774 }
775
776 fn internal_take_frame_info_registration(&mut self) -> Option<GlobalFrameInfoRegistration> {
777 let frame_info_registration = &mut self
778 .allocated
779 .as_mut()
780 .expect("It must be allocated")
781 .frame_info_registration;
782
783 frame_info_registration.take()
784 }
785
786 pub fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> {
789 &self
790 .allocated
791 .as_ref()
792 .expect("It must be allocated")
793 .finished_functions
794 }
795
796 pub fn finished_function_call_trampolines(&self) -> &BoxedSlice<SignatureIndex, VMTrampoline> {
799 &self
800 .allocated
801 .as_ref()
802 .expect("It must be allocated")
803 .finished_function_call_trampolines
804 }
805
806 pub fn finished_dynamic_function_trampolines(
809 &self,
810 ) -> &BoxedSlice<FunctionIndex, FunctionBodyPtr> {
811 &self
812 .allocated
813 .as_ref()
814 .expect("It must be allocated")
815 .finished_dynamic_function_trampolines
816 }
817
818 pub fn signatures(&self) -> &BoxedSlice<SignatureIndex, VMSharedSignatureIndex> {
820 &self
821 .allocated
822 .as_ref()
823 .expect("It must be allocated")
824 .signatures
825 }
826
827 #[allow(clippy::result_large_err)]
829 pub fn preinstantiate(&self) -> Result<(), InstantiationError> {
830 Ok(())
831 }
832
833 #[allow(clippy::result_large_err)]
839 pub unsafe fn instantiate(
840 &self,
841 tunables: &dyn Tunables,
842 imports: &[VMExtern],
843 context: &mut StoreObjects,
844 ) -> Result<VMInstance, InstantiationError> {
845 unsafe {
846 let host_cpu_features = CpuFeature::for_host();
849 if !host_cpu_features.is_superset(self.cpu_features()) {
850 return Err(InstantiationError::CpuFeature(format!(
851 "{:?}",
852 self.cpu_features().difference(host_cpu_features)
853 )));
854 }
855
856 self.preinstantiate()?;
857
858 let module = self.create_module_info();
859
860 let tags = resolve_tags(&module, imports, context).map_err(InstantiationError::Link)?;
861
862 let imports = resolve_imports(
863 &module,
864 imports,
865 context,
866 self.finished_dynamic_function_trampolines(),
867 self.memory_styles(),
868 self.table_styles(),
869 )
870 .map_err(InstantiationError::Link)?;
871
872 let (allocator, memory_definition_locations, table_definition_locations) =
876 InstanceAllocator::new(&module);
877 let finished_memories = tunables
878 .create_memories(
879 context,
880 &module,
881 self.memory_styles(),
882 &memory_definition_locations,
883 )
884 .map_err(InstantiationError::Link)?
885 .into_boxed_slice();
886 let finished_tables = tunables
887 .create_tables(
888 context,
889 &module,
890 self.table_styles(),
891 &table_definition_locations,
892 )
893 .map_err(InstantiationError::Link)?
894 .into_boxed_slice();
895 let finished_globals = tunables
896 .create_globals(context, &module)
897 .map_err(InstantiationError::Link)?
898 .into_boxed_slice();
899
900 let handle = VMInstance::new(
901 allocator,
902 module,
903 context,
904 self.finished_functions().clone(),
905 self.finished_function_call_trampolines().clone(),
906 finished_memories,
907 finished_tables,
908 finished_globals,
909 tags,
910 imports,
911 self.signatures().clone(),
912 )
913 .map_err(InstantiationError::Start)?;
914 Ok(handle)
915 }
916 }
917
918 #[allow(clippy::result_large_err)]
924 pub unsafe fn finish_instantiation(
925 &self,
926 config: &VMConfig,
927 trap_handler: Option<*const TrapHandlerFn<'static>>,
928 handle: &mut VMInstance,
929 ) -> Result<(), InstantiationError> {
930 unsafe {
931 let data_initializers = self
932 .data_initializers()
933 .map(|init| DataInitializer {
934 location: init.location().clone_to_plain(),
935 data: init.data(),
936 })
937 .collect::<Vec<_>>();
938 handle
939 .finish_instantiation(config, trap_handler, &data_initializers)
940 .map_err(InstantiationError::Start)
941 }
942 }
943
944 #[allow(clippy::type_complexity)]
945 #[cfg(feature = "static-artifact-create")]
946 pub fn generate_metadata<'data>(
948 data: &'data [u8],
949 compiler: &dyn Compiler,
950 tunables: &dyn Tunables,
951 features: &Features,
952 ) -> Result<
953 (
954 CompileModuleInfo,
955 PrimaryMap<LocalFunctionIndex, FunctionBodyData<'data>>,
956 Vec<DataInitializer<'data>>,
957 Option<ModuleTranslationState>,
958 ),
959 CompileError,
960 > {
961 let environ = ModuleEnvironment::new();
962 let translation = environ.translate(data).map_err(CompileError::Wasm)?;
963
964 use crate::translator::ModuleMiddlewareChain;
966 let mut module = translation.module;
967 let middlewares = compiler.get_middlewares();
968 middlewares
969 .apply_on_module_info(&mut module)
970 .map_err(|e| CompileError::MiddlewareError(e.to_string()))?;
971
972 let memory_styles: PrimaryMap<MemoryIndex, MemoryStyle> = module
973 .memories
974 .values()
975 .map(|memory_type| tunables.memory_style(memory_type))
976 .collect();
977 let table_styles: PrimaryMap<TableIndex, TableStyle> = module
978 .tables
979 .values()
980 .map(|table_type| tunables.table_style(table_type))
981 .collect();
982
983 let compile_info = CompileModuleInfo {
984 module: Arc::new(module),
985 features: features.clone(),
986 memory_styles,
987 table_styles,
988 };
989 Ok((
990 compile_info,
991 translation.function_body_inputs,
992 translation.data_initializers,
993 translation.module_translation_state,
994 ))
995 }
996
997 #[cfg(feature = "static-artifact-create")]
999 #[allow(clippy::type_complexity)]
1000 pub fn metadata<'a>(
1001 compiler: &dyn Compiler,
1002 data: &'a [u8],
1003 metadata_prefix: Option<&str>,
1004 target: &Target,
1005 tunables: &dyn Tunables,
1006 features: &Features,
1007 ) -> Result<
1008 (
1009 ModuleMetadata,
1010 Option<ModuleTranslationState>,
1011 PrimaryMap<LocalFunctionIndex, FunctionBodyData<'a>>,
1012 ),
1013 CompileError,
1014 > {
1015 #[allow(dead_code)]
1016 let (compile_info, function_body_inputs, data_initializers, module_translation) =
1017 Self::generate_metadata(data, compiler, tunables, features)?;
1018
1019 let data_initializers = data_initializers
1020 .iter()
1021 .map(OwnedDataInitializer::new)
1022 .collect::<Vec<_>>()
1023 .into_boxed_slice();
1024
1025 let function_body_lengths = function_body_inputs
1029 .keys()
1030 .map(|_function_body| 0u64)
1031 .collect::<PrimaryMap<LocalFunctionIndex, u64>>();
1032
1033 let metadata = ModuleMetadata {
1034 compile_info,
1035 prefix: metadata_prefix.map(|s| s.to_string()).unwrap_or_default(),
1036 data_initializers,
1037 function_body_lengths,
1038 cpu_features: target.cpu_features().as_u64(),
1039 };
1040
1041 Ok((metadata, module_translation, function_body_inputs))
1042 }
1043
1044 #[cfg(feature = "static-artifact-create")]
1052 pub fn generate_object<'data>(
1053 compiler: &dyn Compiler,
1054 data: &[u8],
1055 metadata_prefix: Option<&str>,
1056 target: &'data Target,
1057 tunables: &dyn Tunables,
1058 features: &Features,
1059 ) -> Result<
1060 (
1061 ModuleInfo,
1062 Object<'data>,
1063 usize,
1064 Box<dyn crate::types::symbols::SymbolRegistry>,
1065 ),
1066 CompileError,
1067 > {
1068 use crate::types::symbols::{ModuleMetadataSymbolRegistry, SymbolRegistry};
1069
1070 fn to_compile_error(err: impl std::error::Error) -> CompileError {
1071 CompileError::Codegen(format!("{err}"))
1072 }
1073
1074 let target_triple = target.triple();
1075 let (mut metadata, module_translation, function_body_inputs) =
1076 Self::metadata(compiler, data, metadata_prefix, target, tunables, features)
1077 .map_err(to_compile_error)?;
1078
1079 let mut metadata_builder =
1097 ObjectMetadataBuilder::new(&metadata, target_triple).map_err(to_compile_error)?;
1098
1099 let (_compile_info, symbol_registry) = metadata.split();
1100
1101 let compilation: crate::types::function::Compilation = compiler.compile_module(
1102 target,
1103 &metadata.compile_info,
1104 module_translation.as_ref().unwrap(),
1105 function_body_inputs,
1106 None,
1107 )?;
1108 let mut obj = get_object_for_target(target_triple).map_err(to_compile_error)?;
1109
1110 let object_name = ModuleMetadataSymbolRegistry {
1111 prefix: metadata_prefix.unwrap_or_default().to_string(),
1112 }
1113 .symbol_to_name(crate::types::symbols::Symbol::Metadata);
1114
1115 let default_align = match target_triple.architecture {
1116 target_lexicon::Architecture::Aarch64(_) => {
1117 if matches!(
1118 target_triple.operating_system,
1119 target_lexicon::OperatingSystem::Darwin(_)
1120 ) {
1121 8
1122 } else {
1123 4
1124 }
1125 }
1126 _ => 1,
1127 };
1128
1129 let offset = emit_data(
1132 &mut obj,
1133 object_name.as_bytes(),
1134 metadata_builder.placeholder_data(),
1135 std::cmp::max(8, default_align),
1136 )
1137 .map_err(to_compile_error)?;
1138 metadata_builder.set_section_offset(offset);
1139
1140 emit_compilation(
1141 &mut obj,
1142 compilation,
1143 &symbol_registry,
1144 target_triple,
1145 &metadata_builder,
1146 )
1147 .map_err(to_compile_error)?;
1148 Ok((
1149 Arc::try_unwrap(metadata.compile_info.module).unwrap(),
1150 obj,
1151 metadata_builder.placeholder_data().len(),
1152 Box::new(symbol_registry),
1153 ))
1154 }
1155
1156 #[cfg(not(feature = "static-artifact-load"))]
1161 pub unsafe fn deserialize_object(
1162 _engine: &Engine,
1163 _bytes: OwnedBuffer,
1164 ) -> Result<Self, DeserializeError> {
1165 Err(DeserializeError::Compiler(
1166 CompileError::UnsupportedFeature("static load is not compiled in".to_string()),
1167 ))
1168 }
1169
1170 fn get_byte_slice(input: &[u8], start: usize, end: usize) -> Result<&[u8], DeserializeError> {
1171 if (start == end && input.len() > start)
1172 || (start < end && input.len() > start && input.len() >= end)
1173 {
1174 Ok(&input[start..end])
1175 } else {
1176 Err(DeserializeError::InvalidByteLength {
1177 expected: end - start,
1178 got: input.len(),
1179 })
1180 }
1181 }
1182
1183 #[cfg(feature = "static-artifact-load")]
1188 pub unsafe fn deserialize_object(
1189 engine: &Engine,
1190 bytes: OwnedBuffer,
1191 ) -> Result<Self, DeserializeError> {
1192 unsafe {
1193 let bytes = bytes.as_slice();
1194 let metadata_len = MetadataHeader::parse(bytes)?;
1195 let metadata_slice = Self::get_byte_slice(bytes, MetadataHeader::LEN, bytes.len())?;
1196 let metadata_slice = Self::get_byte_slice(metadata_slice, 0, metadata_len)?;
1197 let metadata: ModuleMetadata = ModuleMetadata::deserialize(metadata_slice)?;
1198
1199 const WORD_SIZE: usize = mem::size_of::<usize>();
1200 let mut byte_buffer = [0u8; WORD_SIZE];
1201
1202 let mut cur_offset = MetadataHeader::LEN + metadata_len;
1203
1204 let byte_buffer_slice =
1205 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1206 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1207 cur_offset += WORD_SIZE;
1208
1209 let num_finished_functions = usize::from_ne_bytes(byte_buffer);
1210 let mut finished_functions: PrimaryMap<LocalFunctionIndex, FunctionBodyPtr> =
1211 PrimaryMap::new();
1212
1213 let engine_inner = engine.inner();
1214 let signature_registry = engine_inner.signatures();
1215
1216 for _i in 0..num_finished_functions {
1218 let byte_buffer_slice =
1219 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1220 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1221 let fp = FunctionBodyPtr(usize::from_ne_bytes(byte_buffer) as _);
1222 cur_offset += WORD_SIZE;
1223
1224 finished_functions.push(fp);
1226 }
1227
1228 let signatures = {
1230 metadata
1231 .compile_info
1232 .module
1233 .signatures
1234 .values()
1235 .map(|sig| signature_registry.register(sig))
1236 .collect::<PrimaryMap<_, _>>()
1237 };
1238
1239 let mut finished_function_call_trampolines = PrimaryMap::new();
1241
1242 let byte_buffer_slice =
1243 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1244 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1245 cur_offset += WORD_SIZE;
1246 let num_function_trampolines = usize::from_ne_bytes(byte_buffer);
1247 for _ in 0..num_function_trampolines {
1248 let byte_buffer_slice =
1249 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1250 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1251 cur_offset += WORD_SIZE;
1252 let trampoline_ptr_bytes = usize::from_ne_bytes(byte_buffer);
1253 let trampoline = mem::transmute::<usize, VMTrampoline>(trampoline_ptr_bytes);
1254 finished_function_call_trampolines.push(trampoline);
1255 }
1257
1258 let mut finished_dynamic_function_trampolines = PrimaryMap::new();
1260 let byte_buffer_slice =
1261 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1262 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1263 cur_offset += WORD_SIZE;
1264 let num_dynamic_trampoline_functions = usize::from_ne_bytes(byte_buffer);
1265 for _i in 0..num_dynamic_trampoline_functions {
1266 let byte_buffer_slice =
1267 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1268 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1269 let fp = FunctionBodyPtr(usize::from_ne_bytes(byte_buffer) as _);
1270 cur_offset += WORD_SIZE;
1271
1272 finished_dynamic_function_trampolines.push(fp);
1275 }
1276
1277 let artifact = ArtifactBuild::from_serializable(SerializableModule {
1278 compilation: SerializableCompilation::default(),
1279 compile_info: metadata.compile_info,
1280 data_initializers: metadata.data_initializers,
1281 cpu_features: metadata.cpu_features,
1282 });
1283
1284 let finished_function_lengths = finished_functions
1285 .values()
1286 .map(|_| 0)
1287 .collect::<PrimaryMap<LocalFunctionIndex, usize>>()
1288 .into_boxed_slice();
1289
1290 Ok(Self {
1291 id: Default::default(),
1292 artifact: ArtifactBuildVariant::Plain(artifact),
1293 allocated: Some(AllocatedArtifact {
1294 frame_info_registered: false,
1295 frame_info_registration: None,
1296 finished_functions: finished_functions.into_boxed_slice(),
1297 finished_function_call_trampolines: finished_function_call_trampolines
1298 .into_boxed_slice(),
1299 finished_dynamic_function_trampolines: finished_dynamic_function_trampolines
1300 .into_boxed_slice(),
1301 signatures: signatures.into_boxed_slice(),
1302 finished_function_lengths,
1303 }),
1304 })
1305 }
1306 }
1307}