1use crate::{
2 VMExternObj, VMFunction, VMFunctionEnvironment, VMGlobal, VMInstance, VMMemory, VMTable,
3};
4use core::slice::Iter;
5use std::{cell::UnsafeCell, fmt, marker::PhantomData, num::NonZeroUsize, ptr::NonNull};
6use wasmer_types::StoreId;
7
8pub trait StoreObject: Sized {
11 fn list(ctx: &StoreObjects) -> &Vec<Self>;
12 fn list_mut(ctx: &mut StoreObjects) -> &mut Vec<Self>;
13}
14macro_rules! impl_context_object {
15 ($($field:ident => $ty:ty,)*) => {
16 $(
17 impl StoreObject for $ty {
18 fn list(ctx: &StoreObjects) -> &Vec<Self> {
19 &ctx.$field
20 }
21 fn list_mut(ctx: &mut StoreObjects) -> &mut Vec<Self> {
22 &mut ctx.$field
23 }
24 }
25 )*
26 };
27}
28impl_context_object! {
29 functions => VMFunction,
30 tables => VMTable,
31 globals => VMGlobal,
32 instances => VMInstance,
33 memories => VMMemory,
34 extern_objs => VMExternObj,
35 function_environments => VMFunctionEnvironment,
36}
37
38#[derive(Debug, Default)]
40pub struct StoreObjects {
41 id: StoreId,
42 memories: Vec<VMMemory>,
43 tables: Vec<VMTable>,
44 globals: Vec<VMGlobal>,
45 functions: Vec<VMFunction>,
46 instances: Vec<VMInstance>,
47 extern_objs: Vec<VMExternObj>,
48 function_environments: Vec<VMFunctionEnvironment>,
49}
50
51impl StoreObjects {
52 pub fn id(&self) -> StoreId {
54 self.id
55 }
56
57 pub fn set_id(&mut self, id: StoreId) {
59 self.id = id;
60 }
61
62 pub fn get_2_mut<T: StoreObject>(
66 &mut self,
67 a: InternalStoreHandle<T>,
68 b: InternalStoreHandle<T>,
69 ) -> (&mut T, &mut T) {
70 assert_ne!(a.index(), b.index());
71 let list = T::list_mut(self);
72 if a.index() < b.index() {
73 let (low, high) = list.split_at_mut(b.index());
74 (&mut low[a.index()], &mut high[0])
75 } else {
76 let (low, high) = list.split_at_mut(a.index());
77 (&mut high[0], &mut low[a.index()])
78 }
79 }
80
81 pub fn iter_globals(&self) -> Iter<VMGlobal> {
83 self.globals.iter()
84 }
85
86 pub fn as_u128_globals(&self) -> Vec<u128> {
88 self.iter_globals()
89 .map(|v| unsafe { v.vmglobal().as_ref().val.u128 })
90 .collect()
91 }
92
93 pub fn set_global_unchecked(&self, idx: usize, val: u128) {
97 assert!(idx < self.globals.len());
98 unsafe {
99 self.globals[idx].vmglobal().as_mut().val.u128 = val;
100 }
101 }
102}
103
104#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
109pub struct StoreHandle<T> {
110 id: StoreId,
111 internal: InternalStoreHandle<T>,
112}
113
114impl<T> Clone for StoreHandle<T> {
115 fn clone(&self) -> Self {
116 Self {
117 id: self.id,
118 internal: self.internal,
119 }
120 }
121}
122
123impl<T> std::hash::Hash for StoreHandle<T> {
124 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
125 self.id.hash(state);
126 self.internal.idx.hash(state);
127 }
128}
129
130impl<T: StoreObject> fmt::Debug for StoreHandle<T> {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 f.debug_struct("StoreHandle")
133 .field("id", &self.id)
134 .field("internal", &self.internal.index())
135 .finish()
136 }
137}
138
139impl<T: StoreObject> PartialEq for StoreHandle<T> {
140 fn eq(&self, other: &Self) -> bool {
141 self.id == other.id && self.internal == other.internal
142 }
143}
144
145impl<T: StoreObject> Eq for StoreHandle<T> {}
146
147impl<T: StoreObject> StoreHandle<T> {
148 pub fn new(ctx: &mut StoreObjects, val: T) -> Self {
150 Self {
151 id: ctx.id,
152 internal: InternalStoreHandle::new(ctx, val),
153 }
154 }
155
156 pub fn get<'a>(&self, ctx: &'a StoreObjects) -> &'a T {
158 assert_eq!(self.id, ctx.id, "object used with the wrong context");
159 self.internal.get(ctx)
160 }
161
162 pub fn get_mut<'a>(&self, ctx: &'a mut StoreObjects) -> &'a mut T {
164 assert_eq!(self.id, ctx.id, "object used with the wrong context");
165 self.internal.get_mut(ctx)
166 }
167
168 pub fn internal_handle(&self) -> InternalStoreHandle<T> {
170 self.internal
171 }
172
173 pub fn store_id(&self) -> StoreId {
175 self.id
176 }
177
178 pub fn set_store_id(&mut self, id: StoreId) {
180 self.id = id;
181 }
182
183 pub unsafe fn from_internal(id: StoreId, internal: InternalStoreHandle<T>) -> Self {
188 Self { id, internal }
189 }
190}
191
192#[repr(transparent)]
197pub struct InternalStoreHandle<T> {
198 idx: NonZeroUsize,
200 marker: PhantomData<fn() -> T>,
201}
202
203#[cfg(feature = "artifact-size")]
204impl<T> loupe::MemoryUsage for InternalStoreHandle<T> {
205 fn size_of_val(&self, _tracker: &mut dyn loupe::MemoryUsageTracker) -> usize {
206 std::mem::size_of_val(&self)
207 }
208}
209
210impl<T> Clone for InternalStoreHandle<T> {
211 fn clone(&self) -> Self {
212 *self
213 }
214}
215impl<T> Copy for InternalStoreHandle<T> {}
216
217impl<T> fmt::Debug for InternalStoreHandle<T> {
218 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219 f.debug_struct("InternalStoreHandle")
220 .field("idx", &self.idx)
221 .finish()
222 }
223}
224impl<T> PartialEq for InternalStoreHandle<T> {
225 fn eq(&self, other: &Self) -> bool {
226 self.idx == other.idx
227 }
228}
229impl<T> Eq for InternalStoreHandle<T> {}
230
231impl<T: StoreObject> InternalStoreHandle<T> {
232 pub fn new(ctx: &mut StoreObjects, val: T) -> Self {
234 let list = T::list_mut(ctx);
235 let idx = NonZeroUsize::new(list.len() + 1).unwrap();
236 list.push(val);
237 Self {
238 idx,
239 marker: PhantomData,
240 }
241 }
242
243 pub fn get<'a>(&self, ctx: &'a StoreObjects) -> &'a T {
245 &T::list(ctx)[self.idx.get() - 1]
246 }
247
248 pub fn get_mut<'a>(&self, ctx: &'a mut StoreObjects) -> &'a mut T {
250 &mut T::list_mut(ctx)[self.idx.get() - 1]
251 }
252
253 pub(crate) fn index(&self) -> usize {
254 self.idx.get()
255 }
256
257 pub(crate) fn from_index(idx: usize) -> Option<Self> {
258 NonZeroUsize::new(idx).map(|idx| Self {
259 idx,
260 marker: PhantomData,
261 })
262 }
263}
264
265pub enum MaybeInstanceOwned<T> {
269 Host(Box<UnsafeCell<T>>),
271
272 Instance(NonNull<T>),
274}
275
276impl<T> MaybeInstanceOwned<T> {
277 pub fn as_ptr(&self) -> NonNull<T> {
279 match self {
280 Self::Host(p) => unsafe { NonNull::new_unchecked(p.get()) },
281 Self::Instance(p) => *p,
282 }
283 }
284}
285
286impl<T> std::fmt::Debug for MaybeInstanceOwned<T>
287where
288 T: std::fmt::Debug,
289{
290 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
291 match self {
292 Self::Host(p) => {
293 write!(f, "host(")?;
294 p.as_ref().fmt(f)?;
295 write!(f, ")")
296 }
297 Self::Instance(p) => {
298 write!(f, "instance(")?;
299 unsafe { p.as_ref().fmt(f)? };
300 write!(f, ")")
301 }
302 }
303 }
304}