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 fn visit(&mut self, this: *const u8, descriptor: TraceDescriptor) {
11 let _ = this;
12 let _ = descriptor;
13 }
14 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 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 pub fn trace_ref<T: TraceTrait>(&mut self, object: &T) {
42 <T as TraceTrait>::trace(object, self);
43 }
44 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 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}