Skip to main content

rune/runtime/
vm_diagnostics.rs

1use core::ptr::NonNull;
2
3use crate::hash::Hash;
4use crate::runtime::{RuntimeContext, VmError};
5use crate::Diagnostics;
6
7/// A trait for runtime diagnostics in the virtual machine.
8pub trait VmDiagnostics {
9    /// Mark that a function has been used.
10    ///
11    /// This is called for every native function which is being called, so any
12    /// filtering of interesting hashes has to be performed here. The `context`
13    /// in which the function was called is provided for that purpose, see for
14    /// example [`RuntimeContext::deprecation`].
15    fn function_used(
16        &mut self,
17        context: &RuntimeContext,
18        hash: Hash,
19        at: usize,
20    ) -> Result<(), VmError>;
21
22    /// Returns the vtable for this diagnostics object.
23    #[doc(hidden)]
24    fn vtable(&self) -> &'static VmDiagnosticsObjVtable;
25}
26
27impl VmDiagnostics for Diagnostics {
28    #[inline]
29    fn function_used(
30        &mut self,
31        context: &RuntimeContext,
32        hash: Hash,
33        at: usize,
34    ) -> Result<(), VmError> {
35        // Only functions which have actually been marked as deprecated are of
36        // interest, since recording every function call would be prohibitively
37        // expensive.
38        if context.deprecation(&hash).is_some() {
39            self.runtime_used_deprecated(at, hash)?;
40        }
41
42        Ok(())
43    }
44
45    #[inline]
46    fn vtable(&self) -> &'static VmDiagnosticsObjVtable {
47        fn function_used_impl<T>(
48            ptr: NonNull<()>,
49            context: &RuntimeContext,
50            hash: Hash,
51            at: usize,
52        ) -> Result<(), VmError>
53        where
54            T: VmDiagnostics,
55        {
56            unsafe { VmDiagnostics::function_used(ptr.cast::<T>().as_mut(), context, hash, at) }
57        }
58
59        &VmDiagnosticsObjVtable {
60            function_used: function_used_impl::<Self>,
61        }
62    }
63}
64
65#[derive(Debug)]
66pub struct VmDiagnosticsObjVtable {
67    function_used: unsafe fn(
68        NonNull<()>,
69        context: &RuntimeContext,
70        hash: Hash,
71        at: usize,
72    ) -> Result<(), VmError>,
73}
74
75#[repr(C)]
76#[derive(Debug, Clone, Copy)]
77pub(crate) struct VmDiagnosticsObj {
78    ptr: NonNull<()>,
79    vtable: &'static VmDiagnosticsObjVtable,
80}
81
82impl VmDiagnosticsObj {
83    #[inline]
84    pub(crate) fn new(trait_obj: &mut dyn VmDiagnostics) -> Self {
85        let vtable = trait_obj.vtable();
86
87        Self {
88            ptr: unsafe { NonNull::new_unchecked(trait_obj as *mut _ as *mut ()) },
89            vtable,
90        }
91    }
92
93    #[inline]
94    pub(crate) fn function_used(
95        &mut self,
96        context: &RuntimeContext,
97        hash: Hash,
98        at: usize,
99    ) -> Result<(), VmError> {
100        unsafe { (self.vtable.function_used)(self.ptr, context, hash, at) }
101    }
102}