makepad_stitch/
store.rs

1use {
2    crate::{
3        aliasable_box::AliasableBox,
4        data::DataEntity,
5        elem::ElemEntity,
6        engine::Engine,
7        extern_::ExternEntity,
8        func::{FuncEntity, FuncType},
9        global::GlobalEntity,
10        mem::MemEntity,
11        table::TableEntity,
12    },
13    std::{
14        collections::HashMap,
15        fmt,
16        hash::{Hash, Hasher},
17        ptr::NonNull,
18    },
19};
20
21/// A Wasm store.
22#[derive(Debug)]
23pub struct Store {
24    engine: Engine,
25    id: StoreId,
26    types: FuncTypeInterner,
27    funcs: Vec<AliasableBox<FuncEntity>>,
28    tables: Vec<AliasableBox<TableEntity>>,
29    mems: Vec<AliasableBox<MemEntity>>,
30    globals: Vec<AliasableBox<GlobalEntity>>,
31    elems: Vec<AliasableBox<ElemEntity>>,
32    datas: Vec<AliasableBox<DataEntity>>,
33    externs: Vec<AliasableBox<ExternEntity>>,
34}
35
36impl Store {
37    pub fn new(engine: Engine) -> Self {
38        let id = StoreId::new();
39        Self {
40            engine,
41            id,
42            types: FuncTypeInterner::new(id),
43            funcs: Vec::new(),
44            tables: Vec::new(),
45            mems: Vec::new(),
46            globals: Vec::new(),
47            elems: Vec::new(),
48            datas: Vec::new(),
49            externs: Vec::new(),
50        }
51    }
52
53    pub fn engine(&self) -> &Engine {
54        &self.engine
55    }
56
57    pub(crate) fn id(&self) -> StoreId {
58        self.id
59    }
60
61    pub(crate) fn resolve_type(&self, type_: InternedFuncType) -> &FuncType {
62        self.types.resolve(type_)
63    }
64
65    pub(crate) fn get_or_intern_type(&mut self, type_: &FuncType) -> InternedFuncType {
66        self.types.get_or_intern(type_)
67    }
68
69    /// Inserts the given [`FuncEntity`] into this [`Store`].
70    ///
71    /// Returns a [`Handle`] to the inserted [`FuncEntity`].
72    pub(crate) fn insert_func(&mut self, func: FuncEntity) -> Handle<FuncEntity> {
73        let func = AliasableBox::from_box(Box::new(func));
74        let handle = unsafe { Handle::from_unguarded(AliasableBox::as_raw(&func), self.id) };
75        self.funcs.push(func);
76        handle
77    }
78
79    /// Inserts the given [`TableEntity`] into this [`Store`].
80    ///
81    /// Returns a [`Handle`] to the inserted [`TableEntity`].
82    pub(crate) fn insert_table(&mut self, table: TableEntity) -> Handle<TableEntity> {
83        let table = AliasableBox::from_box(Box::new(table));
84        let handle = unsafe { Handle::from_unguarded(AliasableBox::as_raw(&table), self.id) };
85        self.tables.push(table);
86        handle
87    }
88
89    /// Inserts the given [`MemEntity`] into this [`Store`].
90    ///
91    /// Returns a [`Handle`] to the inserted [`MemEntity`].
92    pub(crate) fn insert_mem(&mut self, mem: MemEntity) -> Handle<MemEntity> {
93        let mem = AliasableBox::from_box(Box::new(mem));
94        let handle = unsafe { Handle::from_unguarded(AliasableBox::as_raw(&mem), self.id) };
95        self.mems.push(mem);
96        handle
97    }
98
99    /// Inserts the given [`GlobalEntity`] into this [`Store`].
100    ///
101    /// Returns a [`Handle`] to the inserted [`GlobalEntity`].
102    pub(crate) fn insert_global(&mut self, global: GlobalEntity) -> Handle<GlobalEntity> {
103        let global = AliasableBox::from_box(Box::new(global));
104        let handle = unsafe { Handle::from_unguarded(AliasableBox::as_raw(&global), self.id) };
105        self.globals.push(global);
106        handle
107    }
108
109    /// Inserts the given [`ElemEntity`] into this [`Store`].
110    ///
111    /// Returns a [`Handle`] to the inserted [`ElemEntity`].
112    pub(crate) fn insert_elem(&mut self, elem: ElemEntity) -> Handle<ElemEntity> {
113        let elem = AliasableBox::from_box(Box::new(elem));
114        let handle = unsafe { Handle::from_unguarded(AliasableBox::as_raw(&elem), self.id) };
115        self.elems.push(elem);
116        handle
117    }
118
119    /// Inserts the given [`DataEntity`] into this [`Store`].
120    ///
121    /// Returns a [`Handle`] to the inserted [`DataEntity`].
122    pub(crate) fn insert_data(&mut self, data: DataEntity) -> Handle<DataEntity> {
123        let data = AliasableBox::from_box(Box::new(data));
124        let handle = unsafe { Handle::from_unguarded(AliasableBox::as_raw(&data), self.id) };
125        self.datas.push(data);
126        handle
127    }
128
129    /// Inserts the given [`ExternEntity`] into this [`Store`].
130    ///
131    /// Returns a [`Handle`] to the inserted [`ExternEntity`].
132    pub(crate) fn insert_extern(&mut self, extern_: ExternEntity) -> Handle<ExternEntity> {
133        let mut extern_ = AliasableBox::from_box(Box::new(extern_));
134        let handle =
135            unsafe { Handle::from_unguarded(NonNull::new_unchecked(&mut *extern_), self.id) };
136        self.externs.push(extern_);
137        handle
138    }
139}
140
141/// A unique identifier for a [`Store`].
142#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
143pub struct StoreId(usize);
144
145impl StoreId {
146    pub(crate) fn new() -> Self {
147        use std::sync::atomic::{AtomicUsize, Ordering};
148
149        static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
150
151        Self(
152            NEXT_ID
153                .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |id| id.checked_add(1))
154                .unwrap(),
155        )
156    }
157}
158
159#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
160pub(crate) struct InternedFuncType {
161    type_: UnguardedInternedFuncType,
162    store_id: StoreId,
163}
164
165impl InternedFuncType {
166    pub(crate) unsafe fn from_unguarded(
167        type_: UnguardedInternedFuncType,
168        store_id: StoreId,
169    ) -> Self {
170        Self { type_, store_id }
171    }
172
173    pub(crate) fn to_unguarded(self, store_id: StoreId) -> UnguardedInternedFuncType {
174        assert_eq!(store_id, self.store_id);
175        self.type_
176    }
177}
178
179#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
180pub(crate) struct UnguardedInternedFuncType(usize);
181
182pub(crate) struct Handle<T> {
183    unguarded: UnguardedHandle<T>,
184    store_id: StoreId,
185}
186
187impl<T> Handle<T> {
188    pub(crate) fn as_ref(self, store: &Store) -> &T {
189        assert_eq!(store.id, self.store_id, "store mismatch");
190        unsafe { self.unguarded.as_ref() }
191    }
192
193    pub(crate) fn as_mut(mut self, store: &mut Store) -> &mut T {
194        assert_eq!(store.id, self.store_id, "store mismatch");
195        unsafe { self.unguarded.as_mut() }
196    }
197
198    pub(crate) unsafe fn from_unguarded(unguarded: UnguardedHandle<T>, store_id: StoreId) -> Self {
199        Self {
200            unguarded,
201            store_id,
202        }
203    }
204
205    pub(crate) fn to_unguarded(self, store_id: StoreId) -> UnguardedHandle<T> {
206        assert_eq!(store_id, self.store_id);
207        self.unguarded
208    }
209}
210
211impl<T> Clone for Handle<T> {
212    fn clone(&self) -> Self {
213        *self
214    }
215}
216
217impl<T> Copy for Handle<T> {}
218
219impl<T> fmt::Debug for Handle<T> {
220    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
221        f.debug_struct("Handle")
222            .field("handle", &self.unguarded)
223            .field("store_id", &self.store_id)
224            .finish()
225    }
226}
227
228impl<T> Eq for Handle<T> {}
229
230impl<T> Hash for Handle<T> {
231    fn hash<H>(&self, state: &mut H)
232    where
233        H: Hasher,
234    {
235        self.unguarded.hash(state);
236        self.store_id.hash(state);
237    }
238}
239
240impl<T> PartialEq for Handle<T> {
241    fn eq(&self, other: &Self) -> bool {
242        if self.unguarded != other.unguarded {
243            return false;
244        }
245        if self.store_id != other.store_id {
246            return false;
247        }
248        true
249    }
250}
251
252pub(crate) type UnguardedHandle<T> = NonNull<T>;
253
254#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
255pub(crate) struct HandlePair<T, U>(pub(crate) Handle<T>, pub(crate) Handle<U>);
256
257impl<T, U> HandlePair<T, U> {
258    pub(crate) fn as_mut_pair(mut self, store: &Store) -> (&mut T, &mut U) {
259        assert_eq!(store.id(), self.0.store_id, "store mismatch");
260        assert_eq!(store.id(), self.1.store_id, "store mismatch");
261        assert_ne!(
262            self.0.unguarded.as_ptr() as usize,
263            self.1.unguarded.as_ptr() as usize,
264            "overlapping handles"
265        );
266        unsafe { (self.0.unguarded.as_mut(), self.1.unguarded.as_mut()) }
267    }
268}
269
270#[derive(Debug)]
271struct FuncTypeInterner {
272    store_id: StoreId,
273    types: Vec<FuncType>,
274    interned_types: HashMap<FuncType, UnguardedInternedFuncType>,
275}
276
277impl FuncTypeInterner {
278    fn new(store_id: StoreId) -> Self {
279        Self {
280            store_id,
281            types: Vec::new(),
282            interned_types: HashMap::new(),
283        }
284    }
285
286    fn resolve(&self, type_: InternedFuncType) -> &FuncType {
287        unsafe { self.resolve_unguarded(type_.to_unguarded(self.store_id)) }
288    }
289
290    /// An unguarded version of `FuncInterner::resolve`.
291    unsafe fn resolve_unguarded(&self, type_: UnguardedInternedFuncType) -> &FuncType {
292        &self.types[type_.0]
293    }
294
295    fn get_or_intern(&mut self, type_: &FuncType) -> InternedFuncType {
296        InternedFuncType {
297            type_: self.get_or_intern_unguarded(type_),
298            store_id: self.store_id,
299        }
300    }
301
302    /// An unguarded version of `FuncInterner::get_or_intern`.
303    fn get_or_intern_unguarded(&mut self, type_: &FuncType) -> UnguardedInternedFuncType {
304        match self.interned_types.get(type_).copied() {
305            Some(type_) => type_,
306            None => {
307                let interned_type = UnguardedInternedFuncType(self.types.len());
308                self.types.push(type_.clone());
309                self.interned_types.insert(type_.clone(), interned_type);
310                interned_type
311            }
312        }
313    }
314}