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_types::VMOffsets;
46use wasmer_vm::{
47 FunctionBodyPtr, InstanceAllocator, MemoryStyle, StoreObjects, TableStyle, TrapHandlerFn,
48 VMConfig, VMExtern, VMInstance, VMSignatureHash, VMTrampoline,
49};
50
51#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
52pub struct AllocatedArtifact {
53 frame_info_registered: bool,
58 frame_info_registration: Option<GlobalFrameInfoRegistration>,
62 finished_functions: BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
63
64 #[cfg_attr(feature = "artifact-size", loupe(skip))]
65 finished_function_call_trampolines: BoxedSlice<SignatureIndex, VMTrampoline>,
66 finished_dynamic_function_trampolines: BoxedSlice<FunctionIndex, FunctionBodyPtr>,
67 signatures: BoxedSlice<SignatureIndex, VMSignatureHash>,
68 finished_function_lengths: BoxedSlice<LocalFunctionIndex, usize>,
69
70 #[cfg_attr(feature = "artifact-size", loupe(skip))]
83 vm_offsets: VMOffsets,
84}
85
86impl AllocatedArtifact {
87 fn function_extents(&self) -> PrimaryMap<LocalFunctionIndex, FunctionExtent> {
88 assert_eq!(
89 self.finished_functions.len(),
90 self.finished_function_lengths.len(),
91 "finished_functions and finished_function_lengths must have equal length"
92 );
93 self.finished_functions
94 .iter()
95 .map(|(index, &ptr)| {
96 let length = self.finished_function_lengths[index];
97 FunctionExtent { ptr, length }
98 })
99 .collect()
100 }
101}
102
103#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
104#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
105#[repr(transparent)]
106pub struct ArtifactId {
108 id: usize,
109}
110
111impl ArtifactId {
112 pub fn id(&self) -> String {
114 format!("{}", self.id)
115 }
116}
117
118impl Clone for ArtifactId {
119 fn clone(&self) -> Self {
120 Self::default()
121 }
122}
123
124impl Default for ArtifactId {
125 fn default() -> Self {
126 static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
127 Self {
128 id: NEXT_ID.fetch_add(1, SeqCst),
129 }
130 }
131}
132
133#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
135pub struct Artifact {
136 id: ArtifactId,
137 artifact: ArtifactBuildVariant,
138 allocated: Option<AllocatedArtifact>,
141}
142
143#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
147#[allow(clippy::large_enum_variant)]
148pub enum ArtifactBuildVariant {
149 Plain(ArtifactBuild),
150 Archived(ArtifactBuildFromArchive),
151}
152
153impl Artifact {
154 #[cfg(feature = "compiler")]
156 pub fn new(
157 engine: &Engine,
158 data: &[u8],
159 tunables: &dyn Tunables,
160 progress_callback: Option<CompilationProgressCallback>,
161 ) -> Result<Self, CompileError> {
162 let mut inner_engine = engine.inner_mut();
163 let environ = ModuleEnvironment::new();
164 let translation = environ.translate(data).map_err(CompileError::Wasm)?;
165 let module = translation.module;
166 let memory_styles: PrimaryMap<MemoryIndex, MemoryStyle> = module
167 .memories
168 .values()
169 .map(|memory_type| tunables.memory_style(memory_type))
170 .collect();
171 let table_styles: PrimaryMap<TableIndex, TableStyle> = module
172 .tables
173 .values()
174 .map(|table_type| tunables.table_style(table_type))
175 .collect();
176
177 let artifact = ArtifactBuild::new(
178 &mut inner_engine,
179 data,
180 engine.target(),
181 memory_styles,
182 table_styles,
183 progress_callback.as_ref(),
184 )?;
185
186 Self::from_parts(
187 &mut inner_engine,
188 ArtifactBuildVariant::Plain(artifact),
189 engine.target(),
190 )
191 .map_err(|e| match e {
192 DeserializeError::Compiler(c) => c,
193
194 _ => unreachable!(),
203 })
204 }
205
206 pub fn allocated(&self) -> bool {
210 self.allocated.is_some()
211 }
212
213 pub fn id(&self) -> &ArtifactId {
219 &self.id
220 }
221
222 #[cfg(not(feature = "compiler"))]
224 pub fn new(_engine: &Engine, _data: &[u8]) -> Result<Self, CompileError> {
225 Err(CompileError::Codegen(
226 "Compilation is not enabled in the engine".to_string(),
227 ))
228 }
229
230 pub unsafe fn deserialize(
239 engine: &Engine,
240 bytes: OwnedBuffer,
241 ) -> Result<Self, DeserializeError> {
242 unsafe {
243 if !ArtifactBuild::is_deserializable(bytes.as_ref()) {
244 let static_artifact = Self::deserialize_object(engine, bytes);
245 match static_artifact {
246 Ok(v) => {
247 return Ok(v);
248 }
249 Err(e) => {
250 return Err(DeserializeError::Incompatible(format!(
251 "The provided bytes are not a Wasmer engine artifact: {e}"
252 )));
253 }
254 }
255 }
256
257 let artifact = ArtifactBuildFromArchive::try_new(bytes, |bytes| {
258 let bytes =
259 Self::get_byte_slice(bytes, ArtifactBuild::MAGIC_HEADER.len(), bytes.len())?;
260
261 let metadata_len = MetadataHeader::parse(bytes)?;
262 let metadata_slice = Self::get_byte_slice(bytes, MetadataHeader::LEN, bytes.len())?;
263 let metadata_slice = Self::get_byte_slice(metadata_slice, 0, metadata_len)?;
264
265 SerializableModule::archive_from_slice_checked(metadata_slice)
266 })?;
267
268 let mut inner_engine = engine.inner_mut();
269 Self::from_parts(
270 &mut inner_engine,
271 ArtifactBuildVariant::Archived(artifact),
272 engine.target(),
273 )
274 }
275 }
276
277 pub unsafe fn deserialize_unchecked(
286 engine: &Engine,
287 bytes: OwnedBuffer,
288 ) -> Result<Self, DeserializeError> {
289 unsafe {
290 if !ArtifactBuild::is_deserializable(bytes.as_ref()) {
291 let static_artifact = Self::deserialize_object(engine, bytes);
292 match static_artifact {
293 Ok(v) => {
294 return Ok(v);
295 }
296 Err(e) => {
297 return Err(DeserializeError::Incompatible(format!(
298 "The provided bytes are not a Wasmer engine artifact: {e}"
299 )));
300 }
301 }
302 }
303
304 let artifact = ArtifactBuildFromArchive::try_new(bytes, |bytes| {
305 let bytes =
306 Self::get_byte_slice(bytes, ArtifactBuild::MAGIC_HEADER.len(), bytes.len())?;
307
308 let metadata_len = MetadataHeader::parse(bytes)?;
309 let metadata_slice = Self::get_byte_slice(bytes, MetadataHeader::LEN, bytes.len())?;
310 let metadata_slice = Self::get_byte_slice(metadata_slice, 0, metadata_len)?;
311
312 SerializableModule::archive_from_slice(metadata_slice)
313 })?;
314
315 let mut inner_engine = engine.inner_mut();
316 Self::from_parts(
317 &mut inner_engine,
318 ArtifactBuildVariant::Archived(artifact),
319 engine.target(),
320 )
321 }
322 }
323
324 pub fn from_parts(
326 engine_inner: &mut EngineInner,
327 artifact: ArtifactBuildVariant,
328 target: &Target,
329 ) -> Result<Self, DeserializeError> {
330 if !target.is_native() {
331 return Ok(Self {
332 id: Default::default(),
333 artifact,
334 allocated: None,
335 });
336 } else {
337 let cpu_features = artifact.cpu_features();
339 if !target.cpu_features().is_superset(cpu_features) {
340 return Err(DeserializeError::Incompatible(format!(
341 "Some CPU Features needed for the artifact are missing: {:?}",
342 cpu_features.difference(*target.cpu_features())
343 )));
344 }
345 }
346 let module_info = artifact.module_info();
347 let (
348 finished_functions,
349 finished_function_call_trampolines,
350 finished_dynamic_function_trampolines,
351 custom_sections,
352 ) = match &artifact {
353 ArtifactBuildVariant::Plain(p) => engine_inner.allocate(
354 module_info,
355 p.get_function_bodies_ref().values(),
356 p.get_function_call_trampolines_ref().values(),
357 p.get_dynamic_function_trampolines_ref().values(),
358 p.get_custom_sections_ref().values(),
359 )?,
360 ArtifactBuildVariant::Archived(a) => engine_inner.allocate(
361 module_info,
362 a.get_function_bodies_ref().values(),
363 a.get_function_call_trampolines_ref().values(),
364 a.get_dynamic_function_trampolines_ref().values(),
365 a.get_custom_sections_ref().values(),
366 )?,
367 };
368
369 let get_got_address: Box<dyn Fn(RelocationTarget) -> Option<usize>> = match &artifact {
370 ArtifactBuildVariant::Plain(p) => {
371 if let Some(got) = p.get_got_ref().index {
372 let relocs: Vec<_> = p.get_custom_section_relocations_ref()[got]
373 .iter()
374 .map(|v| (v.reloc_target, v.offset))
375 .collect();
376 let got_base = custom_sections[got].0 as usize;
377 Box::new(move |t: RelocationTarget| {
378 relocs
379 .iter()
380 .find(|(v, _)| v == &t)
381 .map(|(_, o)| got_base + (*o as usize))
382 })
383 } else {
384 Box::new(|_: RelocationTarget| None)
385 }
386 }
387
388 ArtifactBuildVariant::Archived(p) => {
389 if let Some(got) = p.get_got_ref().index {
390 let relocs: Vec<_> = p.get_custom_section_relocations_ref()[got]
391 .iter()
392 .map(|v| (v.reloc_target(), v.offset))
393 .collect();
394 let got_base = custom_sections[got].0 as usize;
395 Box::new(move |t: RelocationTarget| {
396 relocs
397 .iter()
398 .find(|(v, _)| v == &t)
399 .map(|(_, o)| got_base + (o.to_native() as usize))
400 })
401 } else {
402 Box::new(|_: RelocationTarget| None)
403 }
404 }
405 };
406
407 match &artifact {
408 ArtifactBuildVariant::Plain(p) => link_module(
409 module_info,
410 &finished_functions,
411 &finished_dynamic_function_trampolines,
412 p.get_function_relocations()
413 .iter()
414 .map(|(k, v)| (k, v.iter())),
415 &custom_sections,
416 p.get_custom_section_relocations_ref()
417 .iter()
418 .map(|(k, v)| (k, v.iter())),
419 p.get_libcall_trampolines(),
420 p.get_libcall_trampoline_len(),
421 &get_got_address,
422 ),
423 ArtifactBuildVariant::Archived(a) => link_module(
424 module_info,
425 &finished_functions,
426 &finished_dynamic_function_trampolines,
427 a.get_function_relocations()
428 .iter()
429 .map(|(k, v)| (k, v.iter())),
430 &custom_sections,
431 a.get_custom_section_relocations_ref()
432 .iter()
433 .map(|(k, v)| (k, v.iter())),
434 a.get_libcall_trampolines(),
435 a.get_libcall_trampoline_len(),
436 &get_got_address,
437 ),
438 };
439
440 let signatures = {
442 let signature_registry = engine_inner.signatures();
443 module_info
444 .signatures
445 .values()
446 .zip(module_info.signature_hashes.values())
447 .map(|(sig, sig_hash)| signature_registry.register(sig, *sig_hash))
448 .collect::<PrimaryMap<_, _>>()
449 };
450
451 #[allow(unused_variables)]
452 let eh_frame = match &artifact {
453 ArtifactBuildVariant::Plain(p) => p.get_unwind_info().eh_frame.map(|v| unsafe {
454 std::slice::from_raw_parts(
455 *custom_sections[v],
456 p.get_custom_sections_ref()[v].bytes.len(),
457 )
458 }),
459 ArtifactBuildVariant::Archived(a) => a.get_unwind_info().eh_frame.map(|v| unsafe {
460 std::slice::from_raw_parts(
461 *custom_sections[v],
462 a.get_custom_sections_ref()[v].bytes.len(),
463 )
464 }),
465 };
466 #[allow(unused_variables)]
467 let compact_unwind = match &artifact {
468 ArtifactBuildVariant::Plain(p) => p.get_unwind_info().compact_unwind.map(|v| unsafe {
469 std::slice::from_raw_parts(
470 *custom_sections[v],
471 p.get_custom_sections_ref()[v].bytes.len(),
472 )
473 }),
474 ArtifactBuildVariant::Archived(a) => {
475 a.get_unwind_info().compact_unwind.map(|v| unsafe {
476 std::slice::from_raw_parts(
477 *custom_sections[v],
478 a.get_custom_sections_ref()[v].bytes.len(),
479 )
480 })
481 }
482 };
483
484 #[cfg(all(not(target_arch = "wasm32"), feature = "compiler"))]
485 {
486 engine_inner.register_perfmap(&finished_functions, module_info)?;
487 }
488
489 engine_inner.publish_compiled_code();
491
492 #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
493 if let Some(compact_unwind) = compact_unwind {
494 engine_inner.publish_compact_unwind(
495 compact_unwind,
496 get_got_address(RelocationTarget::LibCall(wasmer_vm::LibCall::EHPersonality)),
497 )?;
498 }
499 #[cfg(not(any(
500 target_arch = "wasm32",
501 all(target_os = "macos", target_arch = "aarch64")
502 )))]
503 engine_inner.publish_eh_frame(eh_frame)?;
504
505 drop(get_got_address);
506
507 let finished_function_lengths = finished_functions
508 .values()
509 .map(|extent| extent.length)
510 .collect::<PrimaryMap<LocalFunctionIndex, usize>>()
511 .into_boxed_slice();
512 let finished_functions = finished_functions
513 .values()
514 .map(|extent| extent.ptr)
515 .collect::<PrimaryMap<LocalFunctionIndex, FunctionBodyPtr>>()
516 .into_boxed_slice();
517 let finished_function_call_trampolines =
518 finished_function_call_trampolines.into_boxed_slice();
519 let finished_dynamic_function_trampolines =
520 finished_dynamic_function_trampolines.into_boxed_slice();
521 let signatures = signatures.into_boxed_slice();
522
523 let vm_offsets = VMOffsets::new(std::mem::size_of::<usize>() as u8, module_info);
524
525 let mut artifact = Self {
526 id: Default::default(),
527 artifact,
528 allocated: Some(AllocatedArtifact {
529 frame_info_registered: false,
530 frame_info_registration: None,
531 finished_functions,
532 finished_function_call_trampolines,
533 finished_dynamic_function_trampolines,
534 signatures,
535 finished_function_lengths,
536 vm_offsets,
537 }),
538 };
539
540 artifact
541 .internal_register_frame_info()
542 .map_err(|e| DeserializeError::CorruptedBinary(format!("{e:?}")))?;
543 if let Some(frame_info) = artifact.internal_take_frame_info_registration() {
544 engine_inner.register_frame_info(frame_info);
545 }
546
547 Ok(artifact)
548 }
549
550 pub fn is_deserializable(bytes: &[u8]) -> bool {
552 ArtifactBuild::is_deserializable(bytes)
553 }
554}
555
556impl PartialEq for Artifact {
557 fn eq(&self, other: &Self) -> bool {
558 self.id == other.id
559 }
560}
561impl Eq for Artifact {}
562
563impl std::fmt::Debug for Artifact {
564 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
565 f.debug_struct("Artifact")
566 .field("artifact_id", &self.id)
567 .field("module_info", &self.module_info())
568 .finish()
569 }
570}
571
572impl<'a> ArtifactCreate<'a> for Artifact {
573 type OwnedDataInitializer = <ArtifactBuildVariant as ArtifactCreate<'a>>::OwnedDataInitializer;
574 type OwnedDataInitializerIterator =
575 <ArtifactBuildVariant as ArtifactCreate<'a>>::OwnedDataInitializerIterator;
576
577 fn set_module_info_name(&mut self, name: String) -> bool {
578 self.artifact.set_module_info_name(name)
579 }
580
581 fn create_module_info(&self) -> Arc<ModuleInfo> {
582 self.artifact.create_module_info()
583 }
584
585 fn module_info(&self) -> &ModuleInfo {
586 self.artifact.module_info()
587 }
588
589 fn features(&self) -> &Features {
590 self.artifact.features()
591 }
592
593 fn cpu_features(&self) -> EnumSet<CpuFeature> {
594 self.artifact.cpu_features()
595 }
596
597 fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
598 self.artifact.data_initializers()
599 }
600
601 fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
602 self.artifact.memory_styles()
603 }
604
605 fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
606 self.artifact.table_styles()
607 }
608
609 fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
610 self.artifact.serialize()
611 }
612}
613
614impl<'a> ArtifactCreate<'a> for ArtifactBuildVariant {
615 type OwnedDataInitializer = OwnedDataInitializerVariant<'a>;
616 type OwnedDataInitializerIterator = IntoIter<Self::OwnedDataInitializer>;
617
618 fn create_module_info(&self) -> Arc<ModuleInfo> {
619 match self {
620 Self::Plain(artifact) => artifact.create_module_info(),
621 Self::Archived(artifact) => artifact.create_module_info(),
622 }
623 }
624
625 fn set_module_info_name(&mut self, name: String) -> bool {
626 match self {
627 Self::Plain(artifact) => artifact.set_module_info_name(name),
628 Self::Archived(artifact) => artifact.set_module_info_name(name),
629 }
630 }
631
632 fn module_info(&self) -> &ModuleInfo {
633 match self {
634 Self::Plain(artifact) => artifact.module_info(),
635 Self::Archived(artifact) => artifact.module_info(),
636 }
637 }
638
639 fn features(&self) -> &Features {
640 match self {
641 Self::Plain(artifact) => artifact.features(),
642 Self::Archived(artifact) => artifact.features(),
643 }
644 }
645
646 fn cpu_features(&self) -> EnumSet<CpuFeature> {
647 match self {
648 Self::Plain(artifact) => artifact.cpu_features(),
649 Self::Archived(artifact) => artifact.cpu_features(),
650 }
651 }
652
653 fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
654 match self {
655 Self::Plain(artifact) => artifact.memory_styles(),
656 Self::Archived(artifact) => artifact.memory_styles(),
657 }
658 }
659
660 fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
661 match self {
662 Self::Plain(artifact) => artifact.table_styles(),
663 Self::Archived(artifact) => artifact.table_styles(),
664 }
665 }
666
667 fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
668 match self {
669 Self::Plain(artifact) => artifact
670 .data_initializers()
671 .map(OwnedDataInitializerVariant::Plain)
672 .collect::<Vec<_>>()
673 .into_iter(),
674 Self::Archived(artifact) => artifact
675 .data_initializers()
676 .map(OwnedDataInitializerVariant::Archived)
677 .collect::<Vec<_>>()
678 .into_iter(),
679 }
680 }
681
682 fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
683 match self {
684 Self::Plain(artifact) => artifact.serialize(),
685 Self::Archived(artifact) => artifact.serialize(),
686 }
687 }
688}
689
690#[derive(Clone, Copy)]
691pub enum OwnedDataInitializerVariant<'a> {
692 Plain(&'a OwnedDataInitializer),
693 Archived(&'a ArchivedOwnedDataInitializer),
694}
695
696impl<'a> DataInitializerLike<'a> for OwnedDataInitializerVariant<'a> {
697 type Location = DataInitializerLocationVariant<'a>;
698
699 fn location(&self) -> Self::Location {
700 match self {
701 Self::Plain(plain) => DataInitializerLocationVariant::Plain(plain.location()),
702 Self::Archived(archived) => {
703 DataInitializerLocationVariant::Archived(archived.location())
704 }
705 }
706 }
707
708 fn data(&self) -> &'a [u8] {
709 match self {
710 Self::Plain(plain) => plain.data(),
711 Self::Archived(archived) => archived.data(),
712 }
713 }
714}
715
716#[derive(Clone, Copy)]
717pub enum DataInitializerLocationVariant<'a> {
718 Plain(&'a DataInitializerLocation),
719 Archived(&'a ArchivedDataInitializerLocation),
720}
721
722impl DataInitializerLocationVariant<'_> {
723 pub fn clone_to_plain(&self) -> DataInitializerLocation {
724 match self {
725 Self::Plain(p) => (*p).clone(),
726 Self::Archived(a) => DataInitializerLocation {
727 memory_index: a.memory_index(),
728 offset_expr: a.offset_expr(),
729 },
730 }
731 }
732}
733
734impl DataInitializerLocationLike for DataInitializerLocationVariant<'_> {
735 fn memory_index(&self) -> MemoryIndex {
736 match self {
737 Self::Plain(plain) => plain.memory_index(),
738 Self::Archived(archived) => archived.memory_index(),
739 }
740 }
741
742 fn offset_expr(&self) -> wasmer_types::InitExpr {
743 match self {
744 Self::Plain(plain) => plain.offset_expr(),
745 Self::Archived(archived) => archived.offset_expr(),
746 }
747 }
748}
749
750impl Artifact {
751 fn internal_register_frame_info(&mut self) -> Result<(), DeserializeError> {
752 if self
753 .allocated
754 .as_ref()
755 .expect("It must be allocated")
756 .frame_info_registered
757 {
758 return Ok(()); }
760
761 let finished_function_extents = self
762 .allocated
763 .as_ref()
764 .expect("It must be allocated")
765 .function_extents()
766 .into_boxed_slice();
767
768 let frame_info_registration = &mut self
769 .allocated
770 .as_mut()
771 .expect("It must be allocated")
772 .frame_info_registration;
773
774 *frame_info_registration = register_frame_info(
775 self.artifact.create_module_info(),
776 &finished_function_extents,
777 match &self.artifact {
778 ArtifactBuildVariant::Plain(p) => {
779 FrameInfosVariant::Owned(p.get_frame_info_ref().clone())
780 }
781 ArtifactBuildVariant::Archived(a) => FrameInfosVariant::Archived(a.clone()),
782 },
783 );
784
785 self.allocated
786 .as_mut()
787 .expect("It must be allocated")
788 .frame_info_registered = true;
789
790 Ok(())
791 }
792
793 fn internal_take_frame_info_registration(&mut self) -> Option<GlobalFrameInfoRegistration> {
794 let frame_info_registration = &mut self
795 .allocated
796 .as_mut()
797 .expect("It must be allocated")
798 .frame_info_registration;
799
800 frame_info_registration.take()
801 }
802
803 pub fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> {
806 &self
807 .allocated
808 .as_ref()
809 .expect("It must be allocated")
810 .finished_functions
811 }
812
813 pub fn finished_function_extents(
825 &self,
826 ) -> Option<Vec<(LocalFunctionIndex, FunctionExtent)>> {
827 let allocated = self.allocated.as_ref()?;
828 Some(allocated.function_extents().into_iter().collect())
829 }
830
831 pub fn finished_function_call_trampolines(&self) -> &BoxedSlice<SignatureIndex, VMTrampoline> {
834 &self
835 .allocated
836 .as_ref()
837 .expect("It must be allocated")
838 .finished_function_call_trampolines
839 }
840
841 pub fn finished_dynamic_function_trampolines(
844 &self,
845 ) -> &BoxedSlice<FunctionIndex, FunctionBodyPtr> {
846 &self
847 .allocated
848 .as_ref()
849 .expect("It must be allocated")
850 .finished_dynamic_function_trampolines
851 }
852
853 pub fn signatures(&self) -> &BoxedSlice<SignatureIndex, VMSignatureHash> {
855 &self
856 .allocated
857 .as_ref()
858 .expect("It must be allocated")
859 .signatures
860 }
861
862 #[allow(clippy::result_large_err)]
864 pub fn preinstantiate(&self) -> Result<(), InstantiationError> {
865 Ok(())
866 }
867
868 #[allow(clippy::result_large_err)]
874 pub unsafe fn instantiate(
875 &self,
876 tunables: &dyn Tunables,
877 imports: &[VMExtern],
878 context: &mut StoreObjects,
879 ) -> Result<VMInstance, InstantiationError> {
880 unsafe {
881 let host_cpu_features = CpuFeature::for_host();
884 if !host_cpu_features.is_superset(self.cpu_features()) {
885 return Err(InstantiationError::CpuFeature(format!(
886 "{:?}",
887 self.cpu_features().difference(host_cpu_features)
888 )));
889 }
890
891 self.preinstantiate()?;
892
893 let module = self.create_module_info();
894
895 let tags = resolve_tags(&module, imports, context).map_err(InstantiationError::Link)?;
896
897 let imports = resolve_imports(
898 &module,
899 imports,
900 context,
901 self.finished_dynamic_function_trampolines(),
902 self.memory_styles(),
903 self.table_styles(),
904 )
905 .map_err(InstantiationError::Link)?;
906
907 let cached_offsets = self
911 .allocated
912 .as_ref()
913 .map(|a| a.vm_offsets.clone())
914 .expect("Artifact::instantiate called on a non-host artifact");
915
916 let (
917 allocator,
918 memory_definition_locations,
919 table_definition_locations,
920 global_definition_locations,
921 ) = InstanceAllocator::new_with_offsets(cached_offsets, &module);
922 let finished_memories = tunables
923 .create_memories(
924 context,
925 &module,
926 self.memory_styles(),
927 &memory_definition_locations,
928 )
929 .map_err(InstantiationError::Link)?
930 .into_boxed_slice();
931 let finished_tables = tunables
932 .create_tables(
933 context,
934 &module,
935 self.table_styles(),
936 &table_definition_locations,
937 )
938 .map_err(InstantiationError::Link)?
939 .into_boxed_slice();
940 let finished_globals = tunables
941 .create_globals(context, &module, &global_definition_locations)
942 .map_err(InstantiationError::Link)?
943 .into_boxed_slice();
944
945 let handle = VMInstance::new(
946 allocator,
947 module,
948 context,
949 self.finished_functions().clone(),
950 self.finished_function_call_trampolines().clone(),
951 finished_memories,
952 finished_tables,
953 finished_globals,
954 tags,
955 imports,
956 self.signatures().clone(),
957 )
958 .map_err(InstantiationError::Start)?;
959 Ok(handle)
960 }
961 }
962
963 #[allow(clippy::result_large_err)]
969 pub unsafe fn finish_instantiation(
970 &self,
971 config: &VMConfig,
972 trap_handler: Option<*const TrapHandlerFn<'static>>,
973 handle: &mut VMInstance,
974 ) -> Result<(), InstantiationError> {
975 unsafe {
976 let data_initializers = self
977 .data_initializers()
978 .map(|init| DataInitializer {
979 location: init.location().clone_to_plain(),
980 data: init.data(),
981 })
982 .collect::<Vec<_>>();
983 handle
984 .finish_instantiation(config, trap_handler, &data_initializers)
985 .map_err(InstantiationError::Start)
986 }
987 }
988
989 #[allow(clippy::type_complexity)]
990 #[cfg(feature = "static-artifact-create")]
991 pub fn generate_metadata<'data>(
993 data: &'data [u8],
994 compiler: &dyn Compiler,
995 tunables: &dyn Tunables,
996 features: &Features,
997 ) -> Result<
998 (
999 CompileModuleInfo,
1000 PrimaryMap<LocalFunctionIndex, FunctionBodyData<'data>>,
1001 Vec<DataInitializer<'data>>,
1002 Option<ModuleTranslationState>,
1003 ),
1004 CompileError,
1005 > {
1006 let environ = ModuleEnvironment::new();
1007 let translation = environ.translate(data).map_err(CompileError::Wasm)?;
1008
1009 use crate::translator::ModuleMiddlewareChain;
1011 let mut module = translation.module;
1012 let middlewares = compiler.get_middlewares();
1013 middlewares
1014 .apply_on_module_info(&mut module)
1015 .map_err(|e| CompileError::MiddlewareError(e.to_string()))?;
1016
1017 let memory_styles: PrimaryMap<MemoryIndex, MemoryStyle> = module
1018 .memories
1019 .values()
1020 .map(|memory_type| tunables.memory_style(memory_type))
1021 .collect();
1022 let table_styles: PrimaryMap<TableIndex, TableStyle> = module
1023 .tables
1024 .values()
1025 .map(|table_type| tunables.table_style(table_type))
1026 .collect();
1027
1028 let compile_info = CompileModuleInfo {
1029 module: Arc::new(module),
1030 features: features.clone(),
1031 memory_styles,
1032 table_styles,
1033 };
1034 Ok((
1035 compile_info,
1036 translation.function_body_inputs,
1037 translation.data_initializers,
1038 translation.module_translation_state,
1039 ))
1040 }
1041
1042 #[cfg(feature = "static-artifact-create")]
1044 #[allow(clippy::type_complexity)]
1045 pub fn metadata<'a>(
1046 compiler: &dyn Compiler,
1047 data: &'a [u8],
1048 metadata_prefix: Option<&str>,
1049 target: &Target,
1050 tunables: &dyn Tunables,
1051 features: &Features,
1052 ) -> Result<
1053 (
1054 ModuleMetadata,
1055 Option<ModuleTranslationState>,
1056 PrimaryMap<LocalFunctionIndex, FunctionBodyData<'a>>,
1057 ),
1058 CompileError,
1059 > {
1060 #[allow(dead_code)]
1061 let (compile_info, function_body_inputs, data_initializers, module_translation) =
1062 Self::generate_metadata(data, compiler, tunables, features)?;
1063
1064 let data_initializers = data_initializers
1065 .iter()
1066 .map(OwnedDataInitializer::new)
1067 .collect::<Vec<_>>()
1068 .into_boxed_slice();
1069
1070 let function_body_lengths = function_body_inputs
1074 .keys()
1075 .map(|_function_body| 0u64)
1076 .collect::<PrimaryMap<LocalFunctionIndex, u64>>();
1077
1078 let metadata = ModuleMetadata {
1079 compile_info,
1080 prefix: metadata_prefix.map(|s| s.to_string()).unwrap_or_default(),
1081 data_initializers,
1082 function_body_lengths,
1083 cpu_features: target.cpu_features().as_u64(),
1084 };
1085
1086 Ok((metadata, module_translation, function_body_inputs))
1087 }
1088
1089 #[cfg(feature = "static-artifact-create")]
1097 pub fn generate_object<'data>(
1098 compiler: &dyn Compiler,
1099 data: &[u8],
1100 metadata_prefix: Option<&str>,
1101 target: &'data Target,
1102 tunables: &dyn Tunables,
1103 features: &Features,
1104 ) -> Result<
1105 (
1106 ModuleInfo,
1107 Object<'data>,
1108 usize,
1109 Box<dyn crate::types::symbols::SymbolRegistry>,
1110 ),
1111 CompileError,
1112 > {
1113 use crate::types::symbols::{ModuleMetadataSymbolRegistry, SymbolRegistry};
1114
1115 fn to_compile_error(err: impl std::error::Error) -> CompileError {
1116 CompileError::Codegen(format!("{err}"))
1117 }
1118
1119 let target_triple = target.triple();
1120 let (mut metadata, module_translation, function_body_inputs) =
1121 Self::metadata(compiler, data, metadata_prefix, target, tunables, features)
1122 .map_err(to_compile_error)?;
1123
1124 let mut metadata_builder =
1142 ObjectMetadataBuilder::new(&metadata, target_triple).map_err(to_compile_error)?;
1143
1144 let (_compile_info, symbol_registry) = metadata.split();
1145
1146 let compilation: crate::types::function::Compilation = compiler.compile_module(
1147 target,
1148 &metadata.compile_info,
1149 module_translation.as_ref().unwrap(),
1150 function_body_inputs,
1151 None,
1152 )?;
1153 let mut obj = get_object_for_target(target_triple).map_err(to_compile_error)?;
1154
1155 let object_name = ModuleMetadataSymbolRegistry {
1156 prefix: metadata_prefix.unwrap_or_default().to_string(),
1157 }
1158 .symbol_to_name(crate::types::symbols::Symbol::Metadata);
1159
1160 let default_align = match target_triple.architecture {
1161 target_lexicon::Architecture::Aarch64(_) => {
1162 if matches!(
1163 target_triple.operating_system,
1164 target_lexicon::OperatingSystem::Darwin(_)
1165 ) {
1166 8
1167 } else {
1168 4
1169 }
1170 }
1171 _ => 1,
1172 };
1173
1174 let offset = emit_data(
1177 &mut obj,
1178 object_name.as_bytes(),
1179 metadata_builder.placeholder_data(),
1180 std::cmp::max(8, default_align),
1181 )
1182 .map_err(to_compile_error)?;
1183 metadata_builder.set_section_offset(offset);
1184
1185 emit_compilation(
1186 &mut obj,
1187 compilation,
1188 &symbol_registry,
1189 target_triple,
1190 &metadata_builder,
1191 )
1192 .map_err(to_compile_error)?;
1193 Ok((
1194 Arc::try_unwrap(metadata.compile_info.module).unwrap(),
1195 obj,
1196 metadata_builder.placeholder_data().len(),
1197 Box::new(symbol_registry),
1198 ))
1199 }
1200
1201 #[cfg(not(feature = "static-artifact-load"))]
1206 pub unsafe fn deserialize_object(
1207 _engine: &Engine,
1208 _bytes: OwnedBuffer,
1209 ) -> Result<Self, DeserializeError> {
1210 Err(DeserializeError::Compiler(
1211 CompileError::UnsupportedFeature("static load is not compiled in".to_string()),
1212 ))
1213 }
1214
1215 fn get_byte_slice(input: &[u8], start: usize, end: usize) -> Result<&[u8], DeserializeError> {
1216 if (start == end && input.len() > start)
1217 || (start < end && input.len() > start && input.len() >= end)
1218 {
1219 Ok(&input[start..end])
1220 } else {
1221 Err(DeserializeError::InvalidByteLength {
1222 expected: end - start,
1223 got: input.len(),
1224 })
1225 }
1226 }
1227
1228 #[cfg(feature = "static-artifact-load")]
1233 pub unsafe fn deserialize_object(
1234 engine: &Engine,
1235 bytes: OwnedBuffer,
1236 ) -> Result<Self, DeserializeError> {
1237 unsafe {
1238 let bytes = bytes.as_slice();
1239 let metadata_len = MetadataHeader::parse(bytes)?;
1240 let metadata_slice = Self::get_byte_slice(bytes, MetadataHeader::LEN, bytes.len())?;
1241 let metadata_slice = Self::get_byte_slice(metadata_slice, 0, metadata_len)?;
1242 let metadata: ModuleMetadata = ModuleMetadata::deserialize(metadata_slice)?;
1243
1244 const WORD_SIZE: usize = mem::size_of::<usize>();
1245 let mut byte_buffer = [0u8; WORD_SIZE];
1246
1247 let mut cur_offset = MetadataHeader::LEN + metadata_len;
1248
1249 let byte_buffer_slice =
1250 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1251 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1252 cur_offset += WORD_SIZE;
1253
1254 let num_finished_functions = usize::from_ne_bytes(byte_buffer);
1255 let mut finished_functions: PrimaryMap<LocalFunctionIndex, FunctionBodyPtr> =
1256 PrimaryMap::new();
1257
1258 let engine_inner = engine.inner();
1259 let signature_registry = engine_inner.signatures();
1260
1261 for _i in 0..num_finished_functions {
1263 let byte_buffer_slice =
1264 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1265 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1266 let fp = FunctionBodyPtr(usize::from_ne_bytes(byte_buffer) as _);
1267 cur_offset += WORD_SIZE;
1268
1269 finished_functions.push(fp);
1271 }
1272
1273 let signatures = {
1275 let module = &metadata.compile_info.module;
1276 module
1277 .signatures
1278 .values()
1279 .zip(module.signature_hashes.values())
1280 .map(|(sig, sig_hash)| signature_registry.register(sig, *sig_hash))
1281 .collect::<PrimaryMap<_, _>>()
1282 };
1283
1284 let mut finished_function_call_trampolines = PrimaryMap::new();
1286
1287 let byte_buffer_slice =
1288 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1289 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1290 cur_offset += WORD_SIZE;
1291 let num_function_trampolines = usize::from_ne_bytes(byte_buffer);
1292 for _ in 0..num_function_trampolines {
1293 let byte_buffer_slice =
1294 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1295 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1296 cur_offset += WORD_SIZE;
1297 let trampoline_ptr_bytes = usize::from_ne_bytes(byte_buffer);
1298 let trampoline = mem::transmute::<usize, VMTrampoline>(trampoline_ptr_bytes);
1299 finished_function_call_trampolines.push(trampoline);
1300 }
1302
1303 let mut finished_dynamic_function_trampolines = PrimaryMap::new();
1305 let byte_buffer_slice =
1306 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1307 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1308 cur_offset += WORD_SIZE;
1309 let num_dynamic_trampoline_functions = usize::from_ne_bytes(byte_buffer);
1310 for _i in 0..num_dynamic_trampoline_functions {
1311 let byte_buffer_slice =
1312 Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1313 byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1314 let fp = FunctionBodyPtr(usize::from_ne_bytes(byte_buffer) as _);
1315 cur_offset += WORD_SIZE;
1316
1317 finished_dynamic_function_trampolines.push(fp);
1320 }
1321
1322 let artifact = ArtifactBuild::from_serializable(SerializableModule {
1323 compilation: SerializableCompilation::default(),
1324 compile_info: metadata.compile_info,
1325 data_initializers: metadata.data_initializers,
1326 cpu_features: metadata.cpu_features,
1327 });
1328
1329 let finished_function_lengths = finished_functions
1330 .values()
1331 .map(|_| 0)
1332 .collect::<PrimaryMap<LocalFunctionIndex, usize>>()
1333 .into_boxed_slice();
1334
1335 let artifact_variant = ArtifactBuildVariant::Plain(artifact);
1338 let vm_offsets = VMOffsets::new(
1339 std::mem::size_of::<usize>() as u8,
1340 artifact_variant.module_info(),
1341 );
1342
1343 Ok(Self {
1344 id: Default::default(),
1345 artifact: artifact_variant,
1346 allocated: Some(AllocatedArtifact {
1347 frame_info_registered: false,
1348 frame_info_registration: None,
1349 finished_functions: finished_functions.into_boxed_slice(),
1350 finished_function_call_trampolines: finished_function_call_trampolines
1351 .into_boxed_slice(),
1352 finished_dynamic_function_trampolines: finished_dynamic_function_trampolines
1353 .into_boxed_slice(),
1354 signatures: signatures.into_boxed_slice(),
1355 finished_function_lengths,
1356 vm_offsets,
1357 }),
1358 })
1359 }
1360 }
1361}