wasmer/entities/store/mod.rs
1//! Defines the [`Store`] data type and various useful traits and data types to interact with a
2//! store.
3
4/// Defines the [`AsStoreAsync`] trait and its supporting types.
5#[cfg(feature = "experimental-async")]
6mod async_;
7#[cfg(feature = "experimental-async")]
8pub use async_::*;
9
10/// Defines the [`StoreContext`] type.
11mod context;
12
13/// Defines the [`StoreInner`] data type.
14mod inner;
15
16/// Create temporary handles to engines.
17mod store_ref;
18
19/// Single-threaded async-aware RwLock.
20#[cfg(feature = "experimental-async")]
21mod local_rwlock;
22#[cfg(feature = "experimental-async")]
23pub(crate) use local_rwlock::*;
24
25use std::{
26 boxed::Box,
27 ops::{Deref, DerefMut},
28};
29
30pub use store_ref::*;
31
32mod obj;
33pub use obj::*;
34
35use crate::{AsEngineRef, BackendEngine, Engine, EngineRef};
36pub(crate) use context::*;
37pub(crate) use inner::*;
38use wasmer_types::StoreId;
39
40#[cfg(feature = "sys")]
41use wasmer_vm::TrapHandlerFn;
42
43/// The store represents all global state that can be manipulated by
44/// WebAssembly programs. It consists of the runtime representation
45/// of all instances of functions, tables, memories, and globals that
46/// have been allocated during the lifetime of the abstract machine.
47///
48/// The [`Store`] is tied to the underlying [`Engine`] that is — among many things — used to
49/// compile the Wasm bytes into a valid module artifact.
50///
51/// For more informations, check out the [related WebAssembly specification]
52/// [related WebAssembly specification]: <https://webassembly.github.io/spec/core/exec/runtime.html#store>
53pub struct Store {
54 pub(crate) inner: Box<StoreInner>,
55}
56
57impl Store {
58 /// Creates a new `Store` with a specific [`Engine`].
59 pub fn new(engine: impl Into<Engine>) -> Self {
60 let engine: Engine = engine.into();
61
62 let store = match engine.be {
63 #[cfg(feature = "sys")]
64 BackendEngine::Sys(_) => {
65 BackendStore::Sys(crate::backend::sys::entities::store::Store::new(engine))
66 }
67 #[cfg(feature = "v8")]
68 BackendEngine::V8(_) => {
69 BackendStore::V8(crate::backend::v8::entities::store::Store::new(engine))
70 }
71 #[cfg(feature = "js")]
72 BackendEngine::Js(_) => {
73 BackendStore::Js(crate::backend::js::entities::store::Store::new(engine))
74 }
75 };
76
77 Self {
78 inner: Box::new(StoreInner {
79 objects: StoreObjects::from_store_ref(&store),
80 on_called: None,
81 store,
82 }),
83 }
84 }
85
86 #[cfg(feature = "sys")]
87 /// Set the [`TrapHandlerFn`] for this store.
88 ///
89 /// # Note
90 ///
91 /// Not every implementor allows changing the trap handler. In those store that
92 /// don't allow it, this function has no effect.
93 pub fn set_trap_handler(&mut self, handler: Option<Box<TrapHandlerFn<'static>>>) {
94 use crate::backend::sys::entities::store::NativeStoreExt;
95 #[allow(irrefutable_let_patterns)]
96 if let BackendStore::Sys(ref mut s) = self.inner.store {
97 s.set_trap_handler(handler)
98 }
99 }
100
101 /// Returns the [`Engine`].
102 pub fn engine(&self) -> &Engine {
103 self.inner.store.engine()
104 }
105
106 /// Returns mutable reference to [`Engine`].
107 pub fn engine_mut(&mut self) -> &mut Engine {
108 self.inner.store.engine_mut()
109 }
110
111 /// Checks whether two stores are identical. A store is considered
112 /// equal to another store if both have the same engine.
113 pub fn same(a: &Self, b: &Self) -> bool {
114 a.id() == b.id()
115 }
116
117 /// Returns the ID of this store
118 pub fn id(&self) -> StoreId {
119 self.inner.objects.id()
120 }
121
122 /// Builds an [`Interrupter`] for this store. Calling [`Interrupter::interrupt`]
123 /// will cause running WASM code to terminate immediately with a
124 /// [`HostInterrupt`](crate::backend::sys::vm::TrapCode::HostInterrupt) trap.
125 ///
126 /// Best effort is made to ensure interrupts are handled. However, there is no
127 /// guarantee; under rare circumstances, it is possible for the interrupt to be
128 /// missed. One such case is when the target thread is about to call WASM code
129 /// but has not yet made the call.
130 ///
131 /// To make sure the code is interrupted, the target thread should notify
132 /// the signalling thread that it has finished running in some way, and
133 /// the signalling thread must wait for that notification and retry the
134 /// interrupt if the notification is not received after some time. Embedders
135 /// are expected to implement this logic.
136 ///
137 /// If an interrupt is delivered while an imported function is running,
138 /// the interrupt will simply be stored and processed only when the
139 /// imported function returns control to WASM code. No effort is made
140 /// to interrupt running imported functions. Embedders are expected to
141 /// implement support for interruption of long-running or blocking
142 /// imported functions separately.
143 #[cfg(all(unix, feature = "experimental-host-interrupt"))]
144 pub fn interrupter(&self) -> Interrupter {
145 self.inner.objects.interrupter()
146 }
147
148 #[cfg(feature = "experimental-async")]
149 /// Transforms this store into a [`StoreAsync`] which can be used
150 /// to invoke [`Function::call_async`](crate::Function::call_async).
151 pub fn into_async(self) -> StoreAsync {
152 StoreAsync {
153 id: self.id(),
154 inner: LocalRwLock::new(self.inner),
155 }
156 }
157}
158
159impl PartialEq for Store {
160 fn eq(&self, other: &Self) -> bool {
161 Self::same(self, other)
162 }
163}
164
165// This is required to be able to set the trap_handler in the
166// Store.
167unsafe impl Send for Store {}
168unsafe impl Sync for Store {}
169
170impl Default for Store {
171 fn default() -> Self {
172 Self::new(Engine::default())
173 }
174}
175
176impl std::fmt::Debug for Store {
177 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
178 f.debug_struct("Store").finish()
179 }
180}
181
182impl AsEngineRef for Store {
183 fn as_engine_ref(&self) -> EngineRef<'_> {
184 self.inner.store.as_engine_ref()
185 }
186
187 fn maybe_as_store(&self) -> Option<StoreRef<'_>> {
188 Some(self.as_store_ref())
189 }
190}
191
192impl AsStoreRef for Store {
193 fn as_store_ref(&self) -> StoreRef<'_> {
194 StoreRef { inner: &self.inner }
195 }
196}
197impl AsStoreMut for Store {
198 fn as_store_mut(&mut self) -> StoreMut<'_> {
199 StoreMut {
200 inner: &mut self.inner,
201 }
202 }
203
204 fn objects_mut(&mut self) -> &mut StoreObjects {
205 &mut self.inner.objects
206 }
207}