wasmer_compiler/engine/
artifact.rs

1//! Define `Artifact`, based on `ArtifactBuild`
2//! to allow compiling and instantiating to be done as separate steps.
3
4use 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    // This shows if the frame info has been registered already or not.
54    // Because the 'GlobalFrameInfoRegistration' ownership can be transferred to EngineInner
55    // this bool is needed to track the status, as 'frame_info_registration' will be None
56    // after the ownership is transferred.
57    frame_info_registered: bool,
58    // frame_info_registered is not staying there but transferred to CodeMemory from EngineInner
59    // using 'Artifact::take_frame_info_registration' method
60    // so the GloabelFrameInfo and MMap stays in sync and get dropped at the same time
61    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    /// Precomputed `VMOffsets` for this artifact's module, cloned by
71    /// `Artifact::instantiate` instead of recomputing on every call.
72    ///
73    /// Safe to cache because `VMOffsets::new(pointer_size, module_info)`
74    /// is deterministic, `module_info` is immutable after compile (the
75    /// only mutable field `name` is not a `VMOffsets` input), and the
76    /// host's pointer size is a runtime constant.
77    ///
78    /// Built once in `from_parts` and in the deserialization path
79    /// (`deserialize_object_native`); `VMOffsets::new` was ~9% of
80    /// `Instance::new` time on profile traces of a per-request wasm
81    /// host calling `Module::instantiate` in a tight loop.
82    #[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)]
106/// A unique identifier for an Artifact.
107pub struct ArtifactId {
108    id: usize,
109}
110
111impl ArtifactId {
112    /// Format this identifier as a string.
113    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/// A compiled wasm module, ready to be instantiated.
134#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
135pub struct Artifact {
136    id: ArtifactId,
137    artifact: ArtifactBuildVariant,
138    // The artifact will only be allocated in memory in case we can execute it
139    // (that means, if the target != host then this will be None).
140    allocated: Option<AllocatedArtifact>,
141}
142
143/// Artifacts may be created as the result of the compilation of a wasm
144/// module, corresponding to `ArtifactBuildVariant::Plain`, or loaded
145/// from an archive, corresponding to `ArtifactBuildVariant::Archived`.
146#[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    /// Compile a data buffer into a `ArtifactBuild`, which may then be instantiated.
155    #[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            // `from_parts` only ever returns `CompileError`s when an
195            // `ArtifactBuildVariant::Plain` is passed in. Other cases
196            // of `DeserializeError` can only happen when an
197            // `ArtifactBuildVariant::Archived` is passed in. We don't
198            // wish to change the return type of this method because
199            // a. it makes no sense and b. it would be a breaking change,
200            // hence this match block and the other cases being
201            // unreachable.
202            _ => unreachable!(),
203        })
204    }
205
206    /// This indicates if the Artifact is allocated and can be run by the current
207    /// host. In case it can't be run (for example, if the artifact is cross compiled to
208    /// other architecture), it will return false.
209    pub fn allocated(&self) -> bool {
210        self.allocated.is_some()
211    }
212
213    /// A unique identifier for this object.
214    ///
215    /// This exists to allow us to compare two Artifacts for equality. Otherwise,
216    /// comparing two trait objects unsafely relies on implementation details
217    /// of trait representation.
218    pub fn id(&self) -> &ArtifactId {
219        &self.id
220    }
221
222    /// Compile a data buffer into a `ArtifactBuild`, which may then be instantiated.
223    #[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    /// Deserialize a serialized artifact.
231    ///
232    /// # Safety
233    /// This function loads executable code into memory.
234    /// You must trust the loaded bytes to be valid for the chosen engine and
235    /// for the host CPU architecture.
236    /// In contrast to [`Self::deserialize_unchecked`] the artifact layout is
237    /// validated, which increases safety.
238    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    /// Deserialize a serialized artifact.
278    ///
279    /// NOTE: You should prefer [`Self::deserialize`].
280    ///
281    /// # Safety
282    /// See [`Self::deserialize`].
283    /// In contrast to the above, this function skips artifact layout validation,
284    /// which increases the risk of loading invalid artifacts.
285    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    /// Construct a `ArtifactBuild` from component parts.
325    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            // check if cpu features are compatible before anything else
338            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        // Compute indices into the shared signature table.
441        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        // Make all code compiled thus far executable.
490        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    /// Check if the provided bytes look like a serialized `ArtifactBuild`.
551    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(()); // already done
759        }
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    /// Returns the functions allocated in memory or this `Artifact`
804    /// ready to be run.
805    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    /// Returns the start address and byte length of each locally-defined
814    /// function body in this artifact.
815    ///
816    /// Returns `None` for cross-compiled artifacts (where the artifact has not
817    /// been allocated into the host process).
818    ///
819    /// # Security
820    ///
821    /// The returned addresses are host-process pointers. They are not stable
822    /// across runs and must not be forwarded to untrusted parties, as they
823    /// reveal ASLR layout information.
824    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    /// Returns the function call trampolines allocated in memory of this
832    /// `Artifact`, ready to be run.
833    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    /// Returns the dynamic function trampolines allocated in memory
842    /// of this `Artifact`, ready to be run.
843    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    /// Returns the associated VM signatures for this `Artifact`.
854    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    /// Do preinstantiation logic that is executed before instantiating
863    #[allow(clippy::result_large_err)]
864    pub fn preinstantiate(&self) -> Result<(), InstantiationError> {
865        Ok(())
866    }
867
868    /// Crate an `Instance` from this `Artifact`.
869    ///
870    /// # Safety
871    ///
872    /// See [`VMInstance::new`].
873    #[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            // Validate the CPU features this module was compiled with against the
882            // host CPU features.
883            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            // Get pointers to where metadata about local memories should live in VM memory.
908            // Get pointers to where metadata about local tables should live in VM memory.
909
910            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    /// Finishes the instantiation of a just created `VMInstance`.
964    ///
965    /// # Safety
966    ///
967    /// See [`VMInstance::finish_instantiation`].
968    #[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    /// Generate a compilation
992    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        // We try to apply the middleware first
1010        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    /// Generate the metadata object for the module
1043    #[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        // TODO: we currently supply all-zero function body lengths.
1071        // We don't know the lengths until they're compiled, yet we have to
1072        // supply the metadata as an input to the compile.
1073        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    /// Compile a module into an object file, which can be statically linked against.
1090    ///
1091    /// The `metadata_prefix` is an optional prefix for the object name to make the
1092    /// function names in the object file unique. When set, the function names will
1093    /// be `wasmer_function_{prefix}_{id}` and the object metadata will be addressable
1094    /// using `WASMER_METADATA_{prefix}_LENGTH` and `WASMER_METADATA_{prefix}_DATA`.
1095    ///
1096    #[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        /*
1125        In the C file we need:
1126        - imports
1127        - exports
1128
1129        to construct an api::Module which is a Store (can be passed in via argument) and an
1130        Arc<dyn Artifact> which means this struct which includes:
1131        - CompileModuleInfo
1132        - Features
1133        - ModuleInfo
1134        - MemoryIndex -> MemoryStyle
1135        - TableIndex -> TableStyle
1136        - LocalFunctionIndex -> FunctionBodyPtr // finished functions
1137        - FunctionIndex -> FunctionBodyPtr // finished dynamic function trampolines
1138        - SignatureIndex -> VMSignatureHash // signatures
1139         */
1140
1141        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        // MetadataHeader::parse requires that metadata must be aligned
1175        // by 8 bytes.
1176        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    /// Deserialize a ArtifactBuild from an object file
1202    ///
1203    /// # Safety
1204    /// The object must be a valid static object generated by wasmer.
1205    #[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    /// Deserialize a ArtifactBuild from an object file
1229    ///
1230    /// # Safety
1231    /// The object must be a valid static object generated by wasmer.
1232    #[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            // read finished functions in order now...
1262            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                // TODO: we can read back the length here if we serialize it. This will improve debug output.
1270                finished_functions.push(fp);
1271            }
1272
1273            // We register all the signatures
1274            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            // read trampolines in order
1285            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                // TODO: we can read back the length here if we serialize it. This will improve debug output.
1301            }
1302
1303            // read dynamic function trampolines in order now...
1304            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                // TODO: we can read back the length here if we serialize it. This will improve debug output.
1318
1319                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            // Variant is built first so its module_info is available for
1336            // the cached VMOffsets before it is moved into Self.
1337            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}