linera_wasmer/
store.rs

1use crate::engine::{AsEngineRef, Engine, EngineRef};
2use derivative::Derivative;
3use std::{
4    fmt,
5    ops::{Deref, DerefMut},
6};
7#[cfg(feature = "sys")]
8pub use wasmer_compiler::Tunables;
9pub use wasmer_types::{OnCalledAction, StoreId};
10#[cfg(feature = "sys")]
11use wasmer_vm::init_traps;
12#[cfg(feature = "sys")]
13pub use wasmer_vm::TrapHandlerFn;
14
15#[cfg(feature = "sys")]
16pub use wasmer_vm::{StoreHandle, StoreObjects};
17
18#[cfg(feature = "js")]
19pub use crate::js::store::{StoreHandle, StoreObjects};
20
21#[cfg(feature = "jsc")]
22pub use crate::jsc::store::{StoreHandle, StoreObjects};
23
24/// Call handler for a store.
25// TODO: better documentation!
26pub type OnCalledHandler = Box<
27    dyn FnOnce(StoreMut<'_>) -> Result<OnCalledAction, Box<dyn std::error::Error + Send + Sync>>,
28>;
29
30/// We require the context to have a fixed memory address for its lifetime since
31/// various bits of the VM have raw pointers that point back to it. Hence we
32/// wrap the actual context in a box.
33#[derive(Derivative)]
34#[derivative(Debug)]
35pub(crate) struct StoreInner {
36    pub(crate) objects: StoreObjects,
37    #[derivative(Debug = "ignore")]
38    pub(crate) engine: Engine,
39    #[cfg(feature = "sys")]
40    #[derivative(Debug = "ignore")]
41    pub(crate) trap_handler: Option<Box<TrapHandlerFn<'static>>>,
42    #[derivative(Debug = "ignore")]
43    pub(crate) on_called: Option<OnCalledHandler>,
44}
45
46/// The store represents all global state that can be manipulated by
47/// WebAssembly programs. It consists of the runtime representation
48/// of all instances of functions, tables, memories, and globals that
49/// have been allocated during the lifetime of the abstract machine.
50///
51/// The `Store` holds the engine (that is —amongst many things— used to compile
52/// the Wasm bytes into a valid module artifact).
53///
54/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#store>
55pub struct Store {
56    pub(crate) inner: Box<StoreInner>,
57}
58
59impl Store {
60    /// Creates a new `Store` with a specific [`Engine`].
61    pub fn new(engine: impl Into<Engine>) -> Self {
62        // Make sure the signal handlers are installed.
63        // This is required for handling traps.
64        #[cfg(feature = "sys")]
65        init_traps();
66
67        Self {
68            inner: Box::new(StoreInner {
69                objects: Default::default(),
70                engine: engine.into(),
71                #[cfg(feature = "sys")]
72                trap_handler: None,
73                on_called: None,
74            }),
75        }
76    }
77
78    #[cfg(feature = "sys")]
79    /// Set the trap handler in this store.
80    pub fn set_trap_handler(&mut self, handler: Option<Box<TrapHandlerFn<'static>>>) {
81        self.inner.trap_handler = handler;
82    }
83
84    /// Returns the [`Engine`].
85    pub fn engine(&self) -> &Engine {
86        &self.inner.engine
87    }
88
89    /// Returns mutable reference to [`Engine`]
90    pub fn engine_mut(&mut self) -> &mut Engine {
91        &mut self.inner.engine
92    }
93
94    /// Checks whether two stores are identical. A store is considered
95    /// equal to another store if both have the same engine.
96    pub fn same(a: &Self, b: &Self) -> bool {
97        a.id() == b.id()
98    }
99
100    /// Returns the ID of this store
101    pub fn id(&self) -> StoreId {
102        self.inner.objects.id()
103    }
104}
105
106impl PartialEq for Store {
107    fn eq(&self, other: &Self) -> bool {
108        Self::same(self, other)
109    }
110}
111
112// This is required to be able to set the trap_handler in the
113// Store.
114unsafe impl Send for Store {}
115unsafe impl Sync for Store {}
116
117impl Default for Store {
118    fn default() -> Self {
119        Self::new(Engine::default())
120    }
121}
122
123impl AsStoreRef for Store {
124    fn as_store_ref(&self) -> StoreRef<'_> {
125        StoreRef { inner: &self.inner }
126    }
127}
128impl AsStoreMut for Store {
129    fn as_store_mut(&mut self) -> StoreMut<'_> {
130        StoreMut {
131            inner: &mut self.inner,
132        }
133    }
134    fn objects_mut(&mut self) -> &mut StoreObjects {
135        &mut self.inner.objects
136    }
137}
138
139impl AsEngineRef for Store {
140    fn as_engine_ref(&self) -> EngineRef<'_> {
141        EngineRef::new(&self.inner.engine)
142    }
143}
144
145impl AsEngineRef for StoreRef<'_> {
146    fn as_engine_ref(&self) -> EngineRef<'_> {
147        EngineRef::new(&self.inner.engine)
148    }
149}
150
151impl AsEngineRef for StoreMut<'_> {
152    fn as_engine_ref(&self) -> EngineRef<'_> {
153        EngineRef::new(&self.inner.engine)
154    }
155}
156
157impl fmt::Debug for Store {
158    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
159        f.debug_struct("Store").finish()
160    }
161}
162
163/// A temporary handle to a [`Store`].
164#[derive(Debug)]
165pub struct StoreRef<'a> {
166    pub(crate) inner: &'a StoreInner,
167}
168
169impl<'a> StoreRef<'a> {
170    pub(crate) fn objects(&self) -> &'a StoreObjects {
171        &self.inner.objects
172    }
173
174    /// Returns the [`Engine`].
175    pub fn engine(&self) -> &Engine {
176        &self.inner.engine
177    }
178
179    /// Checks whether two stores are identical. A store is considered
180    /// equal to another store if both have the same engine.
181    pub fn same(a: &Self, b: &Self) -> bool {
182        a.inner.objects.id() == b.inner.objects.id()
183    }
184
185    /// The signal handler
186    #[cfg(feature = "sys")]
187    #[inline]
188    pub fn signal_handler(&self) -> Option<*const TrapHandlerFn<'static>> {
189        self.inner
190            .trap_handler
191            .as_ref()
192            .map(|handler| handler.as_ref() as *const _)
193    }
194}
195
196/// A temporary handle to a [`Store`].
197pub struct StoreMut<'a> {
198    pub(crate) inner: &'a mut StoreInner,
199}
200
201impl<'a> StoreMut<'a> {
202    /// Returns the [`Engine`].
203    pub fn engine(&self) -> &Engine {
204        &self.inner.engine
205    }
206
207    /// Checks whether two stores are identical. A store is considered
208    /// equal to another store if both have the same engine.
209    pub fn same(a: &Self, b: &Self) -> bool {
210        a.inner.objects.id() == b.inner.objects.id()
211    }
212
213    #[allow(unused)]
214    pub(crate) fn engine_and_objects_mut(&mut self) -> (&Engine, &mut StoreObjects) {
215        (&self.inner.engine, &mut self.inner.objects)
216    }
217
218    pub(crate) fn as_raw(&self) -> *mut StoreInner {
219        self.inner as *const StoreInner as *mut StoreInner
220    }
221
222    pub(crate) unsafe fn from_raw(raw: *mut StoreInner) -> Self {
223        Self { inner: &mut *raw }
224    }
225
226    // TODO: OnCalledAction is needed for asyncify. It will be refactored with https://github.com/wasmerio/wasmer/issues/3451
227    /// Sets the unwind callback which will be invoked when the call finishes
228    pub fn on_called<F>(&mut self, callback: F)
229    where
230        F: FnOnce(StoreMut<'_>) -> Result<OnCalledAction, Box<dyn std::error::Error + Send + Sync>>
231            + Send
232            + Sync
233            + 'static,
234    {
235        self.inner.on_called.replace(Box::new(callback));
236    }
237}
238
239/// Helper trait for a value that is convertible to a [`StoreRef`].
240pub trait AsStoreRef {
241    /// Returns a `StoreRef` pointing to the underlying context.
242    fn as_store_ref(&self) -> StoreRef<'_>;
243}
244
245/// Helper trait for a value that is convertible to a [`StoreMut`].
246pub trait AsStoreMut: AsStoreRef {
247    /// Returns a `StoreMut` pointing to the underlying context.
248    fn as_store_mut(&mut self) -> StoreMut<'_>;
249
250    /// Returns the ObjectMutable
251    fn objects_mut(&mut self) -> &mut StoreObjects;
252}
253
254impl AsStoreRef for StoreRef<'_> {
255    fn as_store_ref(&self) -> StoreRef<'_> {
256        StoreRef { inner: self.inner }
257    }
258}
259
260impl AsStoreRef for StoreMut<'_> {
261    fn as_store_ref(&self) -> StoreRef<'_> {
262        StoreRef { inner: self.inner }
263    }
264}
265impl AsStoreMut for StoreMut<'_> {
266    fn as_store_mut(&mut self) -> StoreMut<'_> {
267        StoreMut { inner: self.inner }
268    }
269    fn objects_mut(&mut self) -> &mut StoreObjects {
270        &mut self.inner.objects
271    }
272}
273
274impl<P> AsStoreRef for P
275where
276    P: Deref,
277    P::Target: AsStoreRef,
278{
279    fn as_store_ref(&self) -> StoreRef<'_> {
280        (**self).as_store_ref()
281    }
282}
283
284impl<P> AsStoreMut for P
285where
286    P: DerefMut,
287    P::Target: AsStoreMut,
288{
289    fn as_store_mut(&mut self) -> StoreMut<'_> {
290        (**self).as_store_mut()
291    }
292
293    fn objects_mut(&mut self) -> &mut StoreObjects {
294        (**self).objects_mut()
295    }
296}