Skip to main content

wasmer/backend/sys/entities/
instance.rs

1//! Data types, functions and traits for `sys` runtime's `Instance` implementation.
2
3use crate::{
4    Extern, error::InstantiationError, exports::Exports, imports::Imports, module::Module,
5    store::AsStoreMut,
6};
7use wasmer_vm::{StoreHandle, VMInstance};
8
9use super::store::Store;
10
11#[derive(Clone, PartialEq, Eq)]
12/// A WebAssembly `instance` in the `sys` runtime.
13pub struct Instance {
14    _handle: StoreHandle<VMInstance>,
15}
16
17impl From<wasmer_compiler::InstantiationError> for InstantiationError {
18    fn from(other: wasmer_compiler::InstantiationError) -> Self {
19        match other {
20            wasmer_compiler::InstantiationError::Link(e) => Self::Link(e.into()),
21            wasmer_compiler::InstantiationError::Start(e) => Self::Start(e.into()),
22            wasmer_compiler::InstantiationError::CpuFeature(e) => Self::CpuFeature(e),
23        }
24    }
25}
26
27impl Instance {
28    #[allow(clippy::result_large_err)]
29    pub(crate) fn new(
30        store: &mut impl AsStoreMut,
31        module: &Module,
32        imports: &Imports,
33    ) -> Result<(Self, Exports), InstantiationError> {
34        let externs = imports
35            .imports_for_module(module)
36            .map_err(InstantiationError::Link)?;
37        let mut handle = module.as_sys().instantiate(store, &externs)?;
38        let exports = Self::get_exports(store, module, handle.as_sys_mut());
39
40        let instance = Self {
41            _handle: StoreHandle::new(store.objects_mut().as_sys_mut(), handle.into_sys()),
42        };
43
44        Ok((instance, exports))
45    }
46
47    #[allow(clippy::result_large_err)]
48    pub(crate) fn new_by_index(
49        store: &mut impl AsStoreMut,
50        module: &Module,
51        externs: &[Extern],
52    ) -> Result<(Self, Exports), InstantiationError> {
53        let externs = externs.to_vec();
54        let mut handle = module.as_sys().instantiate(store, &externs)?;
55        let exports = Self::get_exports(store, module, handle.as_sys_mut());
56        let instance = Self {
57            _handle: StoreHandle::new(
58                store.as_store_mut().objects_mut().as_sys_mut(),
59                handle.into_sys(),
60            ),
61        };
62
63        Ok((instance, exports))
64    }
65
66    fn get_exports(
67        store: &mut impl AsStoreMut,
68        module: &Module,
69        handle: &mut VMInstance,
70    ) -> Exports {
71        module
72            .exports()
73            .map(|export| {
74                let name = export.name().to_string();
75                let export = handle.lookup(&name).expect("export");
76                let extern_ = Extern::from_vm_extern(store, crate::vm::VMExtern::Sys(export));
77                (name, extern_)
78            })
79            .collect::<Exports>()
80    }
81}
82
83impl crate::BackendInstance {
84    /// Consume [`self`] into a [`crate::backend::sys::instance::Instance`].
85    pub(crate) fn into_sys(self) -> crate::backend::sys::instance::Instance {
86        match self {
87            Self::Sys(s) => s,
88            _ => panic!("Not a `sys` instance"),
89        }
90    }
91}
92
93#[cfg(test)]
94mod send_test {
95    use super::*;
96
97    // Only here to statically ensure that `Instance` is `Send`.
98    // Will fail to compile otherwise.
99    #[allow(dead_code)]
100    fn instance_is_send(inst: Instance) {
101        fn is_send(t: impl Send) {
102            let _ = t;
103        }
104
105        is_send(inst);
106    }
107}