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