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