use crate::{
hash_map::HashMap,
type_registry::TypeRegistry,
vm::{SendSyncPtr, VMFuncRef},
};
use wasmtime_core::{
alloc::PanicOnOom,
slab::{Id, Slab},
};
use wasmtime_environ::VMSharedTypeIndex;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct FuncRefTableId(Id);
impl FuncRefTableId {
pub fn into_raw(self) -> u32 {
self.0.into_raw()
}
pub fn from_raw(raw: u32) -> Self {
Self(Id::from_raw(raw))
}
}
#[derive(Default)]
pub struct FuncRefTable {
interned: HashMap<Option<SendSyncPtr<VMFuncRef>>, FuncRefTableId>,
slab: Slab<Option<SendSyncPtr<VMFuncRef>>>,
}
impl FuncRefTable {
pub unsafe fn intern(&mut self, func_ref: Option<SendSyncPtr<VMFuncRef>>) -> FuncRefTableId {
*self.interned.entry(func_ref).or_insert_with(|| {
FuncRefTableId(self.slab.alloc(func_ref).panic_on_oom())
})
}
pub fn get_typed(
&self,
types: &TypeRegistry,
id: FuncRefTableId,
expected_ty: VMSharedTypeIndex,
) -> Option<SendSyncPtr<VMFuncRef>> {
let f = self.slab.get(id.0).copied().expect("bad FuncRefTableId");
if let Some(f) = f {
let actual_ty = unsafe { f.as_ref().type_index };
assert!(types.is_subtype(actual_ty, expected_ty));
}
f
}
pub fn get_untyped(&self, id: FuncRefTableId) -> Option<SendSyncPtr<VMFuncRef>> {
self.slab.get(id.0).copied().expect("bad FuncRefTableId")
}
}