wasmer/backend/sys/entities/
global.rs

1//! Data types, functions and traits for `sys` runtime's `Global` implementation.
2
3use crate::{
4    error::RuntimeError,
5    store::{AsStoreMut, AsStoreRef},
6    value::Value,
7    vm::{VMExtern, VMExternGlobal},
8};
9use wasmer_types::{GlobalType, Mutability};
10use wasmer_vm::{StoreHandle, VMGlobal};
11
12#[derive(Debug, Clone)]
13#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
14/// A WebAssembly `global` in the `sys` runtime.
15pub struct Global {
16    handle: StoreHandle<VMGlobal>,
17}
18
19impl Global {
20    /// Create a `Global` with the initial value [`Value`] and the provided [`Mutability`].
21    pub(crate) fn from_value(
22        store: &mut impl AsStoreMut,
23        val: Value,
24        mutability: Mutability,
25    ) -> Result<Self, RuntimeError> {
26        if !val.is_from_store(store) {
27            return Err(RuntimeError::new("cross-`Store` values are not supported"));
28        }
29        let global = VMGlobal::new(GlobalType {
30            mutability,
31            ty: val.ty(),
32        });
33        unsafe {
34            global.vmglobal().as_mut().val = val.as_raw(store);
35        }
36
37        Ok(Self {
38            handle: StoreHandle::new(store.objects_mut().as_sys_mut(), global),
39        })
40    }
41
42    pub(crate) fn ty(&self, store: &impl AsStoreRef) -> GlobalType {
43        *self
44            .handle
45            .get(store.as_store_ref().objects().as_sys())
46            .ty()
47    }
48
49    pub(crate) fn get(&self, store: &mut impl AsStoreMut) -> Value {
50        unsafe {
51            let raw = self
52                .handle
53                .get(store.as_store_ref().objects().as_sys())
54                .vmglobal()
55                .as_ref()
56                .val;
57            let ty = self
58                .handle
59                .get(store.as_store_ref().objects().as_sys())
60                .ty()
61                .ty;
62            Value::from_raw(store, ty, raw)
63        }
64    }
65
66    pub(crate) fn set(&self, store: &mut impl AsStoreMut, val: Value) -> Result<(), RuntimeError> {
67        if !val.is_from_store(store) {
68            return Err(RuntimeError::new("cross-`Store` values are not supported"));
69        }
70        if self.ty(store).mutability != Mutability::Var {
71            return Err(RuntimeError::new("Attempted to set an immutable global"));
72        }
73        if val.ty() != self.ty(store).ty {
74            return Err(RuntimeError::new(format!(
75                "Attempted to operate on a global of type {expected} as a global of type {found}",
76                expected = self.ty(store).ty,
77                found = val.ty(),
78            )));
79        }
80        unsafe {
81            self.handle
82                .get_mut(store.as_store_mut().objects_mut().as_sys_mut())
83                .vmglobal()
84                .as_mut()
85                .val = val.as_raw(store);
86        }
87        Ok(())
88    }
89
90    pub(crate) fn from_vm_extern(store: &mut impl AsStoreMut, vm_extern: VMExternGlobal) -> Self {
91        Self {
92            handle: unsafe {
93                StoreHandle::from_internal(
94                    store.as_store_ref().objects().id(),
95                    vm_extern.into_sys(),
96                )
97            },
98        }
99    }
100
101    pub(crate) fn is_from_store(&self, store: &impl AsStoreRef) -> bool {
102        self.handle.store_id() == store.as_store_ref().objects().id()
103    }
104
105    pub(crate) fn to_vm_extern(&self) -> VMExtern {
106        VMExtern::Sys(wasmer_vm::VMExtern::Global(self.handle.internal_handle()))
107    }
108}
109
110impl std::cmp::PartialEq for Global {
111    fn eq(&self, other: &Self) -> bool {
112        self.handle == other.handle
113    }
114}
115
116impl std::cmp::Eq for Global {}