wasmer/entities/global/
inner.rs

1use crate::{
2    ExportError, Exportable, Extern,
3    error::RuntimeError,
4    macros::backend::{gen_rt_ty, match_rt},
5    store::{AsStoreMut, AsStoreRef, StoreMut, StoreRef},
6    value::Value,
7    vm::{VMExtern, VMExternGlobal},
8};
9use wasmer_types::{GlobalType, Mutability};
10
11/// A WebAssembly `global` instance.
12///
13/// A global instance is the runtime representation of a global variable.
14/// It consists of an individual value and a flag indicating whether it is mutable.
15///
16/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#global-instances>
17gen_rt_ty!(Global
18    @cfg feature = "artifact-size" => derive(loupe::MemoryUsage)
19    @derives Debug, Clone, PartialEq, Eq, derive_more::From
20);
21
22impl BackendGlobal {
23    /// Create a new global with the initial [`Value`].
24    ///
25    /// # Example
26    ///
27    /// ```
28    /// # use wasmer::{Global, Mutability, Store, Value};
29    /// # let mut store = Store::default();
30    /// #
31    /// let g = Global::new(&mut store, Value::I32(1));
32    ///
33    /// assert_eq!(g.get(&mut store), Value::I32(1));
34    /// assert_eq!(g.ty(&mut store).mutability, Mutability::Const);
35    /// ```
36    #[inline]
37    pub fn new(store: &mut impl AsStoreMut, val: Value) -> Self {
38        Self::from_value(store, val, Mutability::Const).unwrap()
39    }
40
41    /// Create a mutable global with the initial [`Value`].
42    ///
43    /// # Example
44    ///
45    /// ```
46    /// # use wasmer::{Global, Mutability, Store, Value};
47    /// # let mut store = Store::default();
48    /// #
49    /// let g = Global::new_mut(&mut store, Value::I32(1));
50    ///
51    /// assert_eq!(g.get(&mut store), Value::I32(1));
52    /// assert_eq!(g.ty(&mut store).mutability, Mutability::Var);
53    /// ```
54    #[inline]
55    pub fn new_mut(store: &mut impl AsStoreMut, val: Value) -> Self {
56        Self::from_value(store, val, Mutability::Var).unwrap()
57    }
58
59    /// Create a global with the initial [`Value`] and the provided [`Mutability`].
60    #[inline]
61    pub(crate) fn from_value(
62        store: &mut impl AsStoreMut,
63        val: Value,
64        mutability: Mutability,
65    ) -> Result<Self, RuntimeError> {
66        match &store.as_store_mut().inner.store {
67            #[cfg(feature = "sys")]
68            crate::BackendStore::Sys(_) => Ok(Self::Sys(
69                crate::backend::sys::global::Global::from_value(store, val, mutability)?,
70            )),
71            #[cfg(feature = "wamr")]
72            crate::BackendStore::Wamr(_) => Ok(Self::Wamr(
73                crate::backend::wamr::global::Global::from_value(store, val, mutability)?,
74            )),
75
76            #[cfg(feature = "wasmi")]
77            crate::BackendStore::Wasmi(_) => Ok(Self::Wasmi(
78                crate::backend::wasmi::global::Global::from_value(store, val, mutability)?,
79            )),
80            #[cfg(feature = "v8")]
81            crate::BackendStore::V8(_) => Ok(Self::V8(
82                crate::backend::v8::global::Global::from_value(store, val, mutability)?,
83            )),
84            #[cfg(feature = "js")]
85            crate::BackendStore::Js(_) => Ok(Self::Js(
86                crate::backend::js::global::Global::from_value(store, val, mutability)?,
87            )),
88            #[cfg(feature = "jsc")]
89            crate::BackendStore::Jsc(_) => Ok(Self::Jsc(
90                crate::backend::jsc::global::Global::from_value(store, val, mutability)?,
91            )),
92        }
93    }
94
95    /// Returns the [`GlobalType`] of the global.
96    ///
97    /// # Example
98    ///
99    /// ```
100    /// # use wasmer::{Global, Mutability, Store, Type, Value, GlobalType};
101    /// # let mut store = Store::default();
102    /// #
103    /// let c = Global::new(&mut store, Value::I32(1));
104    /// let v = Global::new_mut(&mut store, Value::I64(1));
105    ///
106    /// assert_eq!(c.ty(&mut store), GlobalType::new(Type::I32, Mutability::Const));
107    /// assert_eq!(v.ty(&mut store), GlobalType::new(Type::I64, Mutability::Var));
108    /// ```
109    #[inline]
110    pub fn ty(&self, store: &impl AsStoreRef) -> GlobalType {
111        match_rt!(on self => g {
112            g.ty(store)
113        })
114    }
115
116    /// Retrieves the current value [`Value`] that the global has.
117    ///
118    /// # Example
119    ///
120    /// ```
121    /// # use wasmer::{Global, Store, Value};
122    /// # let mut store = Store::default();
123    /// #
124    /// let g = Global::new(&mut store, Value::I32(1));
125    ///
126    /// assert_eq!(g.get(&mut store), Value::I32(1));
127    /// ```
128    #[inline]
129    pub fn get(&self, store: &mut impl AsStoreMut) -> Value {
130        match_rt!(on self => g {
131            g.get(store)
132        })
133    }
134
135    /// Sets a custom [`Value`] to the runtime global.
136    ///
137    /// # Example
138    ///
139    /// ```
140    /// # use wasmer::{Global, Store, Value};
141    /// # let mut store = Store::default();
142    /// #
143    /// let g = Global::new_mut(&mut store, Value::I32(1));
144    ///
145    /// assert_eq!(g.get(&mut store), Value::I32(1));
146    ///
147    /// g.set(&mut store, Value::I32(2));
148    ///
149    /// assert_eq!(g.get(&mut store), Value::I32(2));
150    /// ```
151    ///
152    /// # Errors
153    ///
154    /// Trying to mutate a immutable global will raise an error:
155    ///
156    /// ```should_panic
157    /// # use wasmer::{Global, Store, Value};
158    /// # let mut store = Store::default();
159    /// #
160    /// let g = Global::new(&mut store, Value::I32(1));
161    ///
162    /// g.set(&mut store, Value::I32(2)).unwrap();
163    /// ```
164    ///
165    /// Trying to set a value of a incompatible type will raise an error:
166    ///
167    /// ```should_panic
168    /// # use wasmer::{Global, Store, Value};
169    /// # let mut store = Store::default();
170    /// #
171    /// let g = Global::new(&mut store, Value::I32(1));
172    ///
173    /// // This results in an error: `RuntimeError`.
174    /// g.set(&mut store, Value::I64(2)).unwrap();
175    /// ```
176    #[inline]
177    pub fn set(&self, store: &mut impl AsStoreMut, val: Value) -> Result<(), RuntimeError> {
178        match_rt!(on self => s {
179            s.set(store, val)
180        })
181    }
182
183    #[inline]
184    pub(crate) fn from_vm_extern(store: &mut impl AsStoreMut, vm_extern: VMExternGlobal) -> Self {
185        match &store.as_store_mut().inner.store {
186            #[cfg(feature = "sys")]
187            crate::BackendStore::Sys(_) => Self::Sys(
188                crate::backend::sys::global::Global::from_vm_extern(store, vm_extern),
189            ),
190            #[cfg(feature = "wamr")]
191            crate::BackendStore::Wamr(_) => Self::Wamr(
192                crate::backend::wamr::global::Global::from_vm_extern(store, vm_extern),
193            ),
194            #[cfg(feature = "wasmi")]
195            crate::BackendStore::Wasmi(_) => Self::Wasmi(
196                crate::backend::wasmi::global::Global::from_vm_extern(store, vm_extern),
197            ),
198            #[cfg(feature = "v8")]
199            crate::BackendStore::V8(_) => Self::V8(
200                crate::backend::v8::global::Global::from_vm_extern(store, vm_extern),
201            ),
202            #[cfg(feature = "js")]
203            crate::BackendStore::Js(_) => Self::Js(
204                crate::backend::js::global::Global::from_vm_extern(store, vm_extern),
205            ),
206            #[cfg(feature = "jsc")]
207            crate::BackendStore::Jsc(_) => Self::Jsc(
208                crate::backend::jsc::global::Global::from_vm_extern(store, vm_extern),
209            ),
210        }
211    }
212
213    /// Checks whether this global can be used with the given context.
214    #[inline]
215    pub fn is_from_store(&self, store: &impl AsStoreRef) -> bool {
216        match_rt!(on self => s {
217            s.is_from_store(store)
218        })
219    }
220
221    /// Create a [`VMExtern`] from self.
222    #[inline]
223    pub(crate) fn to_vm_extern(&self) -> VMExtern {
224        match_rt!(on self => s {
225            s.to_vm_extern()
226        })
227    }
228}