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 offset_expr: a.offset_expr(),
692 },
693 }
694 }
695}
696
697impl DataInitializerLocationLike for DataInitializerLocationVariant<'_> {
698 fn memory_index(&self) -> MemoryIndex {
699 match self {
700 Self::Plain(plain) => plain.memory_index(),
701 Self::Archived(archived) => archived.memory_index(),
702 }
703 }
704
705 fn offset_expr(&self) -> wasmer_types::InitExpr {
706 match self {
707 Self::Plain(plain) => plain.offset_expr(),
708 Self::Archived(archived) => archived.offset_expr(),
709 }
710 }
711}
712
713impl Artifact {
714 fn internal_register_frame_info(&mut self) -> Result<(), DeserializeError> {
715 if self
716 .allocated
717 .as_ref()
718 .expect("It must be allocated")
719 .frame_info_registered
720 {
721 return Ok(()); }
723
724 let finished_function_extents = self
725 .allocated
726 .as_ref()
727 .expect("It must be allocated")
728 .finished_functions
729 .values()
730 .copied()
731 .zip(
732 self.allocated
733 .as_ref()
734 .expect("It must be allocated")
735 .finished_function_lengths
736 .values()
737 .copied(),
738 )
739 .map(|(ptr, length)| FunctionExtent { ptr, length })
740 .collect::<PrimaryMap<LocalFunctionIndex, _>>()
741 .into_boxed_slice();
742
743 let frame_info_registration = &mut self
744 .allocated
745 .as_mut()
746 .expect("It must be allocated")
747 .frame_info_registration;
748
749 *frame_info_registration = register_frame_info(
750 self.artifact.create_module_info(),
751 &finished_function_extents,
752 match &self.artifact {
753 ArtifactBuildVariant::Plain(p) => {
754 FrameInfosVariant::Owned(p.get_frame_info_ref().clone())
755 }
756 ArtifactBuildVariant::Archived(a) => FrameInfosVariant::Archived(a.clone()),
757 },
758 );
759
760 self.allocated
761 .as_mut()
762 .expect("It must be allocated")
763 .frame_info_registered = true;
764
765 Ok(())
766 }
767
768 fn internal_take_frame_info_registration(&mut self) -> Option<GlobalFrameInfoRegistration> {
769 let frame_info_registration = &mut self
770 .allocated
771 .as_mut()
772 .expect("It must be allocated")
773 .frame_info_registration;
774
775 frame_info_registration.take()
776 }
777
778 pub fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> {
781 &self
782 .allocated
783 .as_ref()
784 .expect("It must be allocated")
785 .finished_functions
786 }
787
788 pub fn finished_function_call_trampolines(&self) -> &BoxedSlice<SignatureIndex, VMTrampoline> {
791 &self
792 .allocated
793 .as_ref()
794 .expect("It must be allocated")
795 .finished_function_call_trampolines
796 }
797
798 pub fn finished_dynamic_function_trampolines(
801 &self,
802 ) -> &BoxedSlice<FunctionIndex, FunctionBodyPtr> {
803 &self
804 .allocated
805 .as_ref()
806 .expect("It must be allocated")
807 .finished_dynamic_function_trampolines
808 }
809
810 pub fn signatures(&self) -> &BoxedSlice<SignatureIndex, VMSharedSignatureIndex> {
812 &self
813 .allocated
814 .as_ref()
815 .expect("It must be allocated")
816 .signatures
817 }
818
819 #[allow(clippy::result_large_err)]
821 pub fn preinstantiate(&self) -> Result<(), InstantiationError> {
822 Ok(())
823 }
824
825 #[allow(clippy::result_large_err)]
831 pub unsafe fn instantiate(
832 &self,
833 tunables: &dyn Tunables,
834 imports: &[VMExtern],
835 context: &mut StoreObjects,
836 ) -> Result<VMInstance, InstantiationError> {
837 unsafe {
838 let host_cpu_features = CpuFeature::for_host();
841 if !host_cpu_features.is_superset(self.cpu_features()) {
842 return Err(InstantiationError::CpuFeature(format!(
843 "{:?}",
844 self.cpu_features().difference(host_cpu_features)
845 )));
846 }
847
848 self.preinstantiate()?;
849
850 let module = self.create_module_info();
851
852 let tags = resolve_tags(&module, imports, context).map_err(InstantiationError::Link)?;
853
854 let imports = resolve_imports(
855 &module,
856 imports,
857 context,
858 self.finished_dynamic_function_trampolines(),
859 self.memory_styles(),
860 self.table_styles(),
861 )
862 .map_err(InstantiationError::Link)?;
863
864 let (allocator, memory_definition_locations, table_definition_locations) =
868 InstanceAllocator::new(&module);
869 let finished_memories = tunables
870 .create_memories(
871 context,
872 &module,
873 self.memory_styles(),
874 &memory_definition_locations,
875 )
876 .map_err(InstantiationError::Link)?
877 .into_boxed_slice();
878 let finished_tables = tunables
879 .create_tables(
880 context,
881 &module,
882 self.table_styles(),
883 &table_definition_locations,
884 )
885 .map_err(InstantiationError::Link)?
886 .into_boxed_slice();
887 let finished_globals = tunables
888 .create_globals(context, &module)
889 .map_err(InstantiationError::Link)?
890 .into_boxed_slice();
891
892 let handle = VMInstance::new(
893 allocator,
894 module,
895 context,
896 self.finished_functions().clone(),
897 self.finished_function_call_trampolines().clone(),
898 finished_memories,
899 finished_tables,
900 finished_globals,
901 tags,
902 imports,
903 self.signatures().clone(),
904 )
905 .map_err(InstantiationError::Start)?;
906 Ok(handle)
907 }
908 }
909
910 #[allow(clippy::result_large_err)]
916 pub unsafe fn finish_instantiation(
917 &self,
918 config: &VMConfig,
919 trap_handler: Option<*const TrapHandlerFn<'static>>,
920 handle: &mut VMInstance,
921 ) -> Result<(), InstantiationError> {
922 unsafe {
923 let data_initializers = self
924 .data_initializers()
925 .map(|init| DataInitializer {
926 location: init.location().clone_to_plain(),
927 data: init.data(),
928 })
929 .collect::<Vec<_>>();
930 handle
931 .finish_instantiation(config, trap_handler, &data_initializers)
932 .map_err(InstantiationError::Start)
933 }
934 }
935
936 #[allow(clippy::type_complexity)]
937 #[cfg(feature = "static-artifact-create")]
938 pub fn generate_metadata<'data>(
940 data: &'data [u8],
941 compiler: &dyn Compiler,
942 tunables: &dyn Tunables,
943 features: &Features,
944 ) -> Result<
945 (
946 CompileModuleInfo,
947 PrimaryMap<LocalFunctionIndex, FunctionBodyData<'data>>,
948 Vec<DataInitializer<'data>>,
949 Option<ModuleTranslationState>,
950 ),
951 CompileError,
952 > {
953 let environ = ModuleEnvironment::new();
954 let translation = environ.translate(data).map_err(CompileError::Wasm)?;
955
956 use crate::translator::ModuleMiddlewareChain;
958 let mut module = translation.module;
959 let middlewares = compiler.get_middlewares();
960 middlewares
961 .apply_on_module_info(&mut module)
962 .map_err(|e| CompileError::MiddlewareError(e.to_string()))?;
963
964 let memory_styles: PrimaryMap<MemoryIndex, MemoryStyle> = module
965 .memories
966 .values()
967 .map(|memory_type| tunables.memory_style(memory_type))
968 .collect();
969 let table_styles: PrimaryMap<TableIndex, TableStyle> = module
970 .tables
971 .values()
972 .map(|table_type| tunables.table_style(table_type))
973 .collect();
974
975 let compile_info = CompileModuleInfo {
976 module: Arc::new(module),
977 features: features.clone(),
978 memory_styles,
979 table_styles,
980 };
981 Ok((
982 compile_info,
983 translation.function_body_inputs,
984 translation.data_initializers,
985 translation.module_translation_state,
986 ))
987 }
988
989 #[cfg(feature = "static-artifact-create")]
991 #[allow(clippy::type_complexity)]
992 pub fn metadata<'a>(
993 compiler: &dyn Compiler,
994 data: &'a [u8],
995 metadata_prefix: Option<&str>,
996 target: &Target,
997 tunables: &dyn Tunables,
998 features: &Features,
999 ) -> Result<
1000 (
1001 ModuleMetadata,
1002 Option<ModuleTranslationState>,
1003 PrimaryMap<LocalFunctionIndex, FunctionBodyData<'a>>,
1004 ),
1005 CompileError,
1006 > {
1007 #[allow(dead_code)]
1008 let (compile_info, function_body_inputs, data_initializers, module_translation) =
1009 Self::generate_metadata(data, compiler, tunables, features)?;
1010
1011 let data_initializers = data_initializers
1012 .iter()
1013 .map(OwnedDataInitializer::new)
1014 .collect::<Vec<_>>()
1015 .into_boxed_slice();
1016
1017 let function_body_lengths = function_body_inputs
1021 .keys()
1022 .map(|_function_body| 0u64)
1023 .collect::<PrimaryMap<LocalFunctionIndex, u64>>();
1024
1025 let metadata = ModuleMetadata {
1026 compile_info,
1027 prefix: metadata_prefix.map(|s| s.to_string()).unwrap_or_default(),
1028 data_initializers,
1029 function_body_lengths,
1030 cpu_features: target.cpu_features().as_u64(),
1031 };
1032
1033 Ok((metadata, module_translation, function_body_inputs))
1034 }
1035
1036 #[cfg(feature = "static-artifact-create")]
1044 pub fn generate_object<'data>(
1045 compiler: &dyn Compiler,
1046 data: &[u8],
1047 metadata_prefix: Option<&str>,
1048 target: &'data Target,
1049 tunables: &dyn Tunables,
1050 features: &Features,
1051 ) -> Result<
1052 (
1053 ModuleInfo,
1054 Object<'data>,
1055 usize,
1056 Box<dyn crate::types::symbols::SymbolRegistry>,
1057 ),
1058 CompileError,
1059 > {
1060 use crate::types::symbols::{ModuleMetadataSymbolRegistry, SymbolRegistry};
1061
1062 fn to_compile_error(err: impl std::error::Error) -> CompileError {
1063 CompileError::Codegen(format!("{err}"))
1064 }
1065
1066 let target_triple = target.triple();
1067 let (mut metadata, module_translation, function_body_inputs) =
1068 Self::metadata(compiler, data, metadata_prefix, target, tunables, features)
1069 .map_err(to_compile_error)?;
1070
1071 let mut metadata_builder =
1089 ObjectMetadataBuilder::new(&metadata, target_triple).map_err(to_compile_error)?;
1090
1091 let (_compile_info, symbol_registry) = metadata.split();
1092
1093 let compilation: crate::types::function::Compilation = compiler.compile_module(
1094 target,
1095 &metadata.compile_info,
1096 module_translation.as_ref().unwrap(),
1097 function_body_inputs,
1098 None,
1099 )?;
1100 let mut obj = get_object_for_target(target_triple).map_err(to_compile_error)?;
1101
1102 let object_name = ModuleMetadataSymbolRegistry {
1103 prefix: metadata_prefix.unwrap_or_default().to_string(),
1104 }
1105 .symbol_to_name(crate::types::symbols::Symbol::Metadata);
1106
1107 let default_align = match target_triple.architecture {
1108 target_lexicon::Architecture::Aarch64(_) => {
1109 if matches!(
1110 target_triple.operating_system,
1111 target_lexicon::OperatingSystem::Darwin(_)
1112 ) {
1113 8
1114 } else {
1115 4
1116 }
1117 }
1118 _ => 1,
1119 };
1120
1121 let offset = emit_data(
1124 &mut obj,
1125 object_name.as_bytes(),
1126 metadata_builder.placeholder_data(),
1127 std::cmp::max(8, default_align),
1128 )
1129 .map_err(to_compile_error)?;
1130 metadata_builder.set_section_offset(offset);
1131
1132 emit_compilation(
1133 &mut obj,
1134 compilation,
1135 &symbol_registry,
1136 target_triple,
1137 &metadata_builder,
1138 )
1139 .map_err(to_compile_error)?;
1140 Ok((
1141 Arc::try_unwrap(metadata.compile_info.module).unwrap(),
1142 obj,
1143 metadata_builder.placeholder_data().len(),
1144 Box::new(symbol_registry),
1145 ))
1146 }
1147
1148 #[cfg(not(feature = "static-artifact-load"))]
1153 pub unsafe fn deserialize_object(
1154 _engine: &Engine,
1155 _bytes: OwnedBuffer,
1156 ) -> Result<Self, DeserializeError> {
1157 Err(DeserializeError::Compiler(
1158 CompileError::UnsupportedFeature("static load is not compiled in".to_string()),
1159 ))
1160 }
1161
1162 fn get_byte_slice(input: &[u8], start: usize, end: usize) -> Result<&[u8], DeserializeError> {
1163 if (start == end && input.len() > start)
1164 || (start < end && input.len() > start && input.len() >= end)
1165 {
1166 Ok(&input[start..end])
1167 } else {
1168 Err(DeserializeError::InvalidByteLength {
1169 expected: end - start,
1170 got: input.len(),
1171 })
1172 }
1173 }
1174
1175 #[cfg(feature = "static-artifact-load")]
1180 pub unsafe fn deserialize_object(
1181 engine: &Engine,
1182 bytes: OwnedBuffer,
1183 ) -> Result<Self, DeserializeError> {
1184 unsafe {
1185 let bytes = bytes.as_slice();
1186 let metadata_len = MetadataHeader::parse(bytes)?;
1187 let metadata_slice = Self::get_byte_slice(bytes, MetadataHeader::LEN, bytes.len())?;
1188 let metadata_slice = Self::get_byte_slice(metadata_slice, 0, metadata_len)?;
1189 let metadata: ModuleMetadata = ModuleMetadata::deserialize(metadata_slice)?;
1190
1191 const WORD_SIZE: usize = mem::size_of::<usize>();
1192 let mut byte_buffer = [0u8; WORD_SIZE];
1193
1194 let mut cur_offset = MetadataHeader::LEN + metadata_len;
1195
1196 let byte_buffer_slice =
1197 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1198 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1199 cur_offset += WORD_SIZE;
1200
1201 let num_finished_functions = usize::from_ne_bytes(byte_buffer);
1202 let mut finished_functions: PrimaryMap<LocalFunctionIndex, FunctionBodyPtr> =
1203 PrimaryMap::new();
1204
1205 let engine_inner = engine.inner();
1206 let signature_registry = engine_inner.signatures();
1207
1208 for _i in 0..num_finished_functions {
1210 let byte_buffer_slice =
1211 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1212 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1213 let fp = FunctionBodyPtr(usize::from_ne_bytes(byte_buffer) as _);
1214 cur_offset += WORD_SIZE;
1215
1216 finished_functions.push(fp);
1218 }
1219
1220 let signatures = {
1222 metadata
1223 .compile_info
1224 .module
1225 .signatures
1226 .values()
1227 .map(|sig| signature_registry.register(sig))
1228 .collect::<PrimaryMap<_, _>>()
1229 };
1230
1231 let mut finished_function_call_trampolines = PrimaryMap::new();
1233
1234 let byte_buffer_slice =
1235 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1236 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1237 cur_offset += WORD_SIZE;
1238 let num_function_trampolines = usize::from_ne_bytes(byte_buffer);
1239 for _ in 0..num_function_trampolines {
1240 let byte_buffer_slice =
1241 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 trampoline_ptr_bytes = usize::from_ne_bytes(byte_buffer);
1245 let trampoline = mem::transmute::<usize, VMTrampoline>(trampoline_ptr_bytes);
1246 finished_function_call_trampolines.push(trampoline);
1247 }
1249
1250 let mut finished_dynamic_function_trampolines = PrimaryMap::new();
1252 let byte_buffer_slice =
1253 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1254 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1255 cur_offset += WORD_SIZE;
1256 let num_dynamic_trampoline_functions = usize::from_ne_bytes(byte_buffer);
1257 for _i in 0..num_dynamic_trampoline_functions {
1258 let byte_buffer_slice =
1259 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1260 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1261 let fp = FunctionBodyPtr(usize::from_ne_bytes(byte_buffer) as _);
1262 cur_offset += WORD_SIZE;
1263
1264 finished_dynamic_function_trampolines.push(fp);
1267 }
1268
1269 let artifact = ArtifactBuild::from_serializable(SerializableModule {
1270 compilation: SerializableCompilation::default(),
1271 compile_info: metadata.compile_info,
1272 data_initializers: metadata.data_initializers,
1273 cpu_features: metadata.cpu_features,
1274 });
1275
1276 let finished_function_lengths = finished_functions
1277 .values()
1278 .map(|_| 0)
1279 .collect::<PrimaryMap<LocalFunctionIndex, usize>>()
1280 .into_boxed_slice();
1281
1282 Ok(Self {
1283 id: Default::default(),
1284 artifact: ArtifactBuildVariant::Plain(artifact),
1285 allocated: Some(AllocatedArtifact {
1286 frame_info_registered: false,
1287 frame_info_registration: None,
1288 finished_functions: finished_functions.into_boxed_slice(),
1289 finished_function_call_trampolines: finished_function_call_trampolines
1290 .into_boxed_slice(),
1291 finished_dynamic_function_trampolines: finished_dynamic_function_trampolines
1292 .into_boxed_slice(),
1293 signatures: signatures.into_boxed_slice(),
1294 finished_function_lengths,
1295 }),
1296 })
1297 }
1298 }
1299}