wasmer/entities/store/store_ref.rs
1use std::ops::{Deref, DerefMut};
2
3use super::{StoreObjects, inner::StoreInner};
4use crate::entities::engine::{AsEngineRef, Engine, EngineRef};
5#[cfg(feature = "experimental-async")]
6use crate::{AsStoreAsync, StoreAsync};
7use wasmer_types::{ExternType, OnCalledAction};
8//use wasmer_vm::{StoreObjects, TrapHandlerFn};
9
10#[cfg(feature = "sys")]
11use wasmer_vm::TrapHandlerFn;
12
13/// A temporary handle to a [`crate::Store`].
14#[derive(Debug)]
15pub struct StoreRef<'a> {
16 pub(crate) inner: &'a StoreInner,
17}
18
19impl<'a> StoreRef<'a> {
20 pub(crate) fn objects(&self) -> &'a StoreObjects {
21 &self.inner.objects
22 }
23
24 /// Returns the [`Engine`].
25 pub fn engine(&self) -> &Engine {
26 self.inner.store.engine()
27 }
28
29 /// Checks whether two stores are identical. A store is considered
30 /// equal to another store if both have the same engine.
31 pub fn same(a: &Self, b: &Self) -> bool {
32 StoreObjects::same(&a.inner.objects, &b.inner.objects)
33 }
34
35 /// The signal handler
36 #[cfg(feature = "sys")]
37 #[inline]
38 pub fn signal_handler(&self) -> Option<*const TrapHandlerFn<'static>> {
39 use crate::backend::sys::entities::store::NativeStoreExt;
40 self.inner.store.as_sys().signal_handler()
41 }
42}
43
44/// A temporary handle to a [`crate::Store`].
45pub struct StoreMut<'a> {
46 pub(crate) inner: &'a mut StoreInner,
47}
48
49impl StoreMut<'_> {
50 /// Returns the [`Engine`].
51 pub fn engine(&self) -> &Engine {
52 self.inner.store.engine()
53 }
54
55 /// Checks whether two stores are identical. A store is considered
56 /// equal to another store if both have the same engine.
57 pub fn same(a: &Self, b: &Self) -> bool {
58 StoreObjects::same(&a.inner.objects, &b.inner.objects)
59 }
60
61 #[allow(unused)]
62 pub(crate) fn as_raw(&self) -> *mut StoreInner {
63 self.inner as *const StoreInner as *mut StoreInner
64 }
65
66 #[allow(unused)]
67 pub(crate) unsafe fn from_raw(raw: *mut StoreInner) -> Self {
68 Self {
69 inner: unsafe { &mut *raw },
70 }
71 }
72
73 #[allow(unused)]
74 pub(crate) fn engine_and_objects_mut(&mut self) -> (&Engine, &mut StoreObjects) {
75 (self.inner.store.engine(), &mut self.inner.objects)
76 }
77
78 /// Parks this borrow of the store for the duration of `f`, lending the
79 /// store to code that runs inside `f` without reaching it through Rust:
80 /// [`Store::with_current`](crate::Store::with_current) hands the store back to any frame `f` reaches,
81 /// however many foreign frames deep.
82 ///
83 /// This is how host code lends the store across an FFI boundary. An
84 /// embedded engine that calls back into the host — a JS engine's allocator
85 /// hook, say — cannot be handed a Rust reference through its own C frames,
86 /// and cannot be given one out of band either, because the imported
87 /// function it was called from is still holding the only borrow. Parking
88 /// that borrow, which the `&mut self` receiver here makes unreachable for
89 /// exactly as long as `f` runs, is what makes lending it sound rather than
90 /// aliasing.
91 ///
92 /// Parks nest, and a store nobody parked stays unlendable:
93 /// [`Store::with_current`](crate::Store::with_current) returns `None`
94 /// unless every borrow on this thread's stack has been parked this way.
95 ///
96 /// ```
97 /// use wasmer::{AsStoreMut, FunctionEnvMut, Store};
98 ///
99 /// // A host function lending its store to code it calls into.
100 /// fn host_call(mut env: FunctionEnvMut<'_, ()>) {
101 /// // `env` holds the store, so nobody else may have it.
102 /// assert!(Store::with_current(|_| ()).is_none());
103 ///
104 /// env.as_store_mut().parked(|| {
105 /// // ...but code reached from here can pick it back up.
106 /// assert!(Store::with_current(|_| ()).is_some());
107 /// });
108 /// }
109 /// ```
110 pub fn parked<R>(&mut self, f: impl FnOnce() -> R) -> R {
111 // This is the same thing `Function::call` does before entering Wasm:
112 // install this borrow as the store executing on the thread, so that
113 // code which reaches the store through the context — rather than
114 // through a reference it was handed — picks up a borrow derived from
115 // *this* one. The new entry starts unborrowed, which is what makes the
116 // store lendable for as long as it is on top.
117 let ptr: *mut StoreInner = &mut *self.inner;
118 // SAFETY: `ptr` comes from `&mut *self.inner`, which `&mut self` keeps
119 // alive and unreachable for every frame on this thread until `f`
120 // returns and the guard is dropped.
121 let _guard = unsafe { super::StoreContext::install(ptr) };
122 f()
123 }
124
125 // TODO: OnCalledAction is needed for asyncify. It will be refactored with https://github.com/wasmerio/wasmer/issues/3451
126 /// Sets the unwind callback which will be invoked when the call finishes
127 pub fn on_called<F>(&mut self, callback: F)
128 where
129 F: FnOnce(StoreMut<'_>) -> Result<OnCalledAction, Box<dyn std::error::Error + Send + Sync>>
130 + Send
131 + Sync
132 + 'static,
133 {
134 self.inner.on_called.replace(Box::new(callback));
135 }
136}
137
138/// Helper trait for a value that is convertible to a [`StoreRef`].
139pub trait AsStoreRef {
140 /// Returns a `StoreRef` pointing to the underlying context.
141 fn as_store_ref(&self) -> StoreRef<'_>;
142
143 /// Returns a [`StoreAsync`] if the current
144 /// context is asynchronous. The store will be locked since
145 /// it's already active in the current context, but can be used
146 /// to spawn new coroutines via
147 /// [`Function::call_async`](crate::Function::call_async).
148 #[cfg(feature = "experimental-async")]
149 fn as_store_async(&self) -> Option<impl AsStoreAsync + 'static> {
150 let id = self.as_store_ref().inner.objects.id();
151 StoreAsync::from_context(id)
152 }
153}
154
155/// Helper trait for a value that is convertible to a [`StoreMut`].
156pub trait AsStoreMut: AsStoreRef {
157 /// Returns a `StoreMut` pointing to the underlying context.
158 fn as_store_mut(&mut self) -> StoreMut<'_>;
159
160 /// Returns the ObjectMutable
161 fn objects_mut(&mut self) -> &mut StoreObjects;
162}
163
164impl AsStoreRef for StoreRef<'_> {
165 fn as_store_ref(&self) -> StoreRef<'_> {
166 StoreRef { inner: self.inner }
167 }
168}
169
170impl AsEngineRef for StoreRef<'_> {
171 fn as_engine_ref(&self) -> EngineRef<'_> {
172 self.inner.store.as_engine_ref()
173 }
174}
175
176impl AsStoreRef for StoreMut<'_> {
177 fn as_store_ref(&self) -> StoreRef<'_> {
178 StoreRef { inner: self.inner }
179 }
180}
181impl AsStoreMut for StoreMut<'_> {
182 fn as_store_mut(&mut self) -> StoreMut<'_> {
183 StoreMut { inner: self.inner }
184 }
185
186 fn objects_mut(&mut self) -> &mut StoreObjects {
187 &mut self.inner.objects
188 }
189}
190
191impl<P> AsStoreRef for P
192where
193 P: Deref,
194 P::Target: AsStoreRef,
195{
196 fn as_store_ref(&self) -> StoreRef<'_> {
197 (**self).as_store_ref()
198 }
199}
200
201impl<P> AsStoreMut for P
202where
203 P: DerefMut,
204 P::Target: AsStoreMut,
205{
206 fn as_store_mut(&mut self) -> StoreMut<'_> {
207 (**self).as_store_mut()
208 }
209
210 fn objects_mut(&mut self) -> &mut StoreObjects {
211 (**self).objects_mut()
212 }
213}
214
215impl AsEngineRef for StoreMut<'_> {
216 fn as_engine_ref(&self) -> EngineRef<'_> {
217 self.inner.store.as_engine_ref()
218 }
219}