wasmtime/runtime/vm/gc/
host_data.rs1use crate::prelude::*;
17use core::any::Any;
18use wasmtime_core::{
19 alloc::PanicOnOom,
20 slab::{Id, Slab},
21};
22
23#[derive(Default)]
25pub struct ExternRefHostDataTable {
26 slab: Slab<Box<dyn Any + Send + Sync>>,
27}
28
29#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
31#[repr(transparent)]
32pub struct ExternRefHostDataId(Id);
33
34fn deref_box<T: ?Sized>(b: &Box<T>) -> &T {
35 &**b
36}
37
38fn deref_box_mut<T: ?Sized>(b: &mut Box<T>) -> &mut T {
39 &mut **b
40}
41
42impl ExternRefHostDataTable {
43 pub fn alloc(&mut self, value: Box<dyn Any + Send + Sync>) -> ExternRefHostDataId {
45 let id = self.slab.alloc(value).panic_on_oom();
47 let id = ExternRefHostDataId(id);
48 log::trace!("allocated new externref host data: {id:?}");
49 id
50 }
51
52 pub fn dealloc(&mut self, id: ExternRefHostDataId) -> Box<dyn Any + Send + Sync> {
54 log::trace!("deallocated externref host data: {id:?}");
55 self.slab.dealloc(id.0)
56 }
57
58 pub fn get(&self, id: ExternRefHostDataId) -> &(dyn Any + Send + Sync) {
60 let data: &Box<dyn Any + Send + Sync> = self.slab.get(id.0).unwrap();
61 deref_box(data)
62 }
63
64 pub fn get_mut(&mut self, id: ExternRefHostDataId) -> &mut (dyn Any + Send + Sync) {
66 let data: &mut Box<dyn Any + Send + Sync> = self.slab.get_mut(id.0).unwrap();
67 deref_box_mut(data)
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn correct_dyn_object() {
77 let mut table = ExternRefHostDataTable::default();
78
79 let x = 42_u32;
80 let id = table.alloc(Box::new(x));
81 assert!(table.get(id).is::<u32>());
82 assert_eq!(*table.get(id).downcast_ref::<u32>().unwrap(), 42);
83 assert!(table.get_mut(id).is::<u32>());
84 assert_eq!(*table.get_mut(id).downcast_ref::<u32>().unwrap(), 42);
85 }
86}