1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use crate::{
gc_info_table::GC_TABLE,
gcref::{GcRef, UntypedGcRef},
heap::Heap,
internal::trace_trait::{TraceDescriptor, TraceTrait},
};
pub trait VisitorTrait {
fn visit(&mut self, this: *const u8, descriptor: TraceDescriptor) {
let _ = this;
let _ = descriptor;
}
fn visit_conservative(&mut self, from: *const *const u8, to: *const *const u8);
fn heap(&self) -> *mut Heap;
}
#[repr(C)]
pub struct Visitor {
pub(crate) vis: *mut dyn VisitorTrait,
}
impl Visitor {
pub(crate) fn heap(&self) -> *mut Heap {
unsafe { (*self.vis).heap() }
}
pub unsafe fn trace<T: TraceTrait>(&mut self, t: *const T) {
if t.is_null() {
return;
}
(*self.vis).visit(t.cast(), <T as TraceTrait>::get_trace_descriptor(t.cast()))
}
pub fn trace_ref<T: TraceTrait>(&mut self, object: &T) {
<T as TraceTrait>::trace(object, self);
}
pub fn trace_gcref<T: TraceTrait>(&mut self, object: GcRef<T>) {
unsafe {
self.trace(object.downcast().get() as *mut T);
}
}
pub fn trace_untyped(&mut self, object: UntypedGcRef) {
unsafe {
let header = &*object.header.as_ptr();
let gc_info = GC_TABLE.get_gc_info(header.get_gc_info_index());
(*self.vis).visit(
header.payload(),
TraceDescriptor {
base_object_payload: header.payload(),
callback: gc_info.trace,
},
)
}
}
pub fn trace_conservatively(&mut self, from: *const u8, to: *const u8) {
unsafe {
(*self.vis).visit_conservative(from.cast(), to.cast());
}
}
}