near_vm_vm/
func_data_registry.rs1use crate::vmcontext::VMCallerCheckedAnyfunc;
8use parking_lot::Mutex;
9use std::collections::HashMap;
10
11#[derive(Debug)]
13pub struct FuncDataRegistry {
14    inner: Mutex<Inner>,
20}
21
22unsafe impl Send for FuncDataRegistry {}
24unsafe impl Sync for FuncDataRegistry {}
25
26#[repr(transparent)]
28#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
29pub struct VMFuncRef(pub(crate) *const VMCallerCheckedAnyfunc);
30
31impl near_vm_types::NativeWasmType for VMFuncRef {
32    const WASM_TYPE: near_vm_types::Type = near_vm_types::Type::FuncRef;
33    type Abi = Self;
34
35    #[inline]
36    fn from_abi(abi: Self::Abi) -> Self {
37        abi
38    }
39
40    #[inline]
41    fn into_abi(self) -> Self::Abi {
42        self
43    }
44
45    #[inline]
46    fn to_binary(self) -> i128 {
47        self.0 as _
48    }
49
50    #[inline]
51    fn from_binary(bits: i128) -> Self {
52        Self(bits as _)
54    }
55}
56
57impl VMFuncRef {
58    pub fn is_null(&self) -> bool {
61        self.0.is_null()
62    }
63
64    pub const fn null() -> Self {
66        Self(std::ptr::null())
67    }
68}
69
70impl std::ops::Deref for VMFuncRef {
71    type Target = *const VMCallerCheckedAnyfunc;
72
73    fn deref(&self) -> &Self::Target {
74        &self.0
75    }
76}
77
78impl std::ops::DerefMut for VMFuncRef {
79    fn deref_mut(&mut self) -> &mut Self::Target {
80        &mut self.0
81    }
82}
83
84unsafe impl Send for VMFuncRef {}
87unsafe impl Sync for VMFuncRef {}
88
89#[derive(Debug, Default)]
90struct Inner {
91    func_data: Vec<VMCallerCheckedAnyfunc>,
92    anyfunc_to_index: HashMap<VMCallerCheckedAnyfunc, usize>,
93}
94
95impl FuncDataRegistry {
96    pub fn new() -> Self {
98        Self { inner: Default::default() }
99    }
100
101    pub fn register(&self, anyfunc: VMCallerCheckedAnyfunc) -> VMFuncRef {
103        let mut inner = self.inner.lock();
104        let data = if let Some(&idx) = inner.anyfunc_to_index.get(&anyfunc) {
105            &inner.func_data[idx]
106        } else {
107            let idx = inner.func_data.len();
108            inner.func_data.push(anyfunc);
109            inner.anyfunc_to_index.insert(anyfunc, idx);
110            &inner.func_data[idx]
111        };
112        VMFuncRef(data)
113    }
114}