comet/
visitor.rs

1use crate::{
2    gc_info_table::GC_TABLE,
3    gcref::{GcRef, UntypedGcRef},
4    heap::Heap,
5    internal::trace_trait::{TraceDescriptor, TraceTrait},
6};
7
8pub trait VisitorTrait {
9    /// Visits object with provided [TraceDescriptor]. 
10    fn visit(&mut self, this: *const u8, descriptor: TraceDescriptor) {
11        let _ = this;
12        let _ = descriptor;
13    }
14    /// Visits objects in `from` to `to` range conservatively. This function will read gc info index from
15    /// each object that is found in memory range and obtain TraceDescriptor from that.
16    fn visit_conservative(&mut self, from: *const *const u8, to: *const *const u8);
17    
18    fn heap(&self) -> *mut Heap;
19}
20
21#[repr(C)]
22pub struct Visitor {
23    pub(crate) vis: *mut dyn VisitorTrait,
24}
25
26impl Visitor {
27    pub(crate) fn heap(&self) -> *mut Heap {
28        unsafe { (*self.vis).heap() }
29    }
30    /// Trace method for raw pointers. Prefer the versions for managed pointers.
31    pub unsafe fn trace<T: TraceTrait>(&mut self, t: *const T) {
32        if t.is_null() {
33            return;
34        }
35
36        (*self.vis).visit(t.cast(), <T as TraceTrait>::get_trace_descriptor(t.cast()))
37    }
38
39    /// Trace method for inlined objects that are not allocated themselves but
40    /// otherwise follow managed heap layout and have a trace() method.
41    pub fn trace_ref<T: TraceTrait>(&mut self, object: &T) {
42        <T as TraceTrait>::trace(object, self);
43    }
44    /// Traces typed gc reference. 
45    pub fn trace_gcref<T: TraceTrait>(&mut self, object: GcRef<T>) {
46        unsafe {
47            self.trace(object.downcast().get() as *mut T);
48        }
49    }
50    /// Traces untyped gc reference.
51    pub fn trace_untyped(&mut self, object: UntypedGcRef) {
52        unsafe {
53            let header = &*object.header.as_ptr();
54            let gc_info = GC_TABLE.get_gc_info(header.get_gc_info_index());
55            (*self.vis).visit(
56                header.payload(),
57                TraceDescriptor {
58                    base_object_payload: header.payload(),
59                    callback: gc_info.trace,
60                },
61            )
62        }
63    }
64
65    pub fn trace_conservatively(&mut self, from: *const u8, to: *const u8) {
66        unsafe {
67            (*self.vis).visit_conservative(from.cast(), to.cast());
68        }
69    }
70}