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