wasmer_vm/
artifact.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use crate::{InstanceHandle, Resolver, Tunables, VMLocalFunction, VMSharedSignatureIndex};
use std::{any::Any, collections::BTreeMap, sync::Arc};
use wasmer_types::{
    entity::BoxedSlice, ElemIndex, FunctionIndex, GlobalInit, GlobalType, ImportCounts,
    InstanceConfig, LocalFunctionIndex, OwnedDataInitializer, OwnedTableInitializer,
};

mod private {
    pub struct Internal(pub(super) ());
}

/// [`Artifact`]s that can be instantiated.
pub trait Instantiatable: Artifact {
    /// The errors that can occur when instantiating.
    type Error: std::error::Error + Send + Sync;

    /// Crate an `Instance` from this `Artifact`.
    ///
    /// # Safety
    ///
    /// See [`InstanceHandle::new`].
    unsafe fn instantiate(
        self: Arc<Self>,
        tunables: &dyn Tunables,
        resolver: &dyn Resolver,
        host_state: Box<dyn Any>,
        config: InstanceConfig,
    ) -> Result<InstanceHandle, Self::Error>;
}

/// A predecesor of a full module Instance.
///
/// This type represents parts of a compiled WASM module ([`Executable`](crate::Executable)) that
/// are pre-allocated in within some Engine's store.
///
/// Some other operations such as linking, relocating and similar may also be performed during
/// constructon of the Artifact, making this type particularly well suited for caching in-memory.
pub trait Artifact: Send + Sync {
    /// Internal: support for downcasting `Executable`s.
    #[doc(hidden)]
    fn type_id(&self, _: private::Internal) -> std::any::TypeId
    where
        Self: 'static,
    {
        std::any::TypeId::of::<Self>()
    }

    /// The information about offsets into the VM context table.
    fn offsets(&self) -> &crate::VMOffsets;

    /// The count of imported entities.
    fn import_counts(&self) -> &ImportCounts;

    /// The locally defined functions.
    ///
    /// These are published and ready to call.
    fn functions(&self) -> &BoxedSlice<LocalFunctionIndex, VMLocalFunction>;

    /// Passive table elements.
    fn passive_elements(&self) -> &BTreeMap<ElemIndex, Box<[FunctionIndex]>>;

    /// Table initializers.
    fn element_segments(&self) -> &[OwnedTableInitializer];

    /// Memory initializers.
    /// TODO: consider making it an iterator of `DataInitializer`s instead?
    fn data_segments(&self) -> &[OwnedDataInitializer];

    /// Passive table elements.
    fn globals(&self) -> &[(GlobalType, GlobalInit)];

    /// The function index to the start function.
    fn start_function(&self) -> Option<FunctionIndex>;

    /// Function by export name.
    fn export_field(&self, name: &str) -> Option<wasmer_types::ExportIndex>;

    /// Mapping between module SignatureIndex and VMSharedSignatureIndex.
    fn signatures(&self) -> &[VMSharedSignatureIndex];

    /// Obtain the function signature for either the import or local definition.
    fn function_signature(&self, index: FunctionIndex) -> Option<VMSharedSignatureIndex>;
}

impl dyn Artifact {
    /// Downcast a dynamic Executable object to a concrete implementation of the trait.
    pub fn downcast_arc<T: Artifact + 'static>(self: Arc<Self>) -> Result<Arc<T>, Arc<Self>> {
        if std::any::TypeId::of::<T>() == Artifact::type_id(&*self, private::Internal(())) {
            // SAFETY: err, its probably sound, we effectively construct a transmute here.
            unsafe {
                let ptr = Arc::into_raw(self).cast::<T>();
                Ok(Arc::from_raw(ptr))
            }
        } else {
            Err(self)
        }
    }
}