1use crate::{
2 gc_info_table::GC_TABLE,
3 gc_size,
4 global_allocator::GlobalAllocator,
5 header::CellState,
6 header::HeapObjectHeader,
7 heap::Heap,
8 internal::{gc_info::GCInfoIndex, trace_trait::TraceDescriptor},
9 visitor::{Visitor, VisitorTrait},
10};
11
12pub struct MarkingVisitor {
13 worklist: Vec<TraceDescriptor>,
14 heap: *mut GlobalAllocator,
15 h: *mut Heap,
16 bytes_visited: usize,
17}
18#[inline]
19unsafe fn trace_desc(ptr: *mut HeapObjectHeader) -> TraceDescriptor {
20 TraceDescriptor {
21 base_object_payload: (*ptr).payload(),
22 callback: GC_TABLE.get_gc_info((*ptr).get_gc_info_index()).trace,
23 }
24}
25impl VisitorTrait for MarkingVisitor {
26 fn heap(&self) -> *mut Heap {
27 self.h
28 }
29 fn visit(
30 &mut self,
31 this: *const u8,
32 descriptor: crate::internal::trace_trait::TraceDescriptor,
33 ) {
34 unsafe {
35 let header = HeapObjectHeader::from_object(this);
36 let res = (*self.h).test_and_set_marked(header);
37
38 if !res {
39 (*header).force_set_state(CellState::PossiblyGrey);
40 self.bytes_visited += gc_size(header);
41 self.worklist.push(descriptor);
42 }
43 }
44 }
45
46 fn visit_conservative(&mut self, from: *const *const u8, to: *const *const u8) {
47 let mut scan = from;
48 let end = to;
49
50 while scan < end {
51 unsafe {
52 let pointer = scan.read();
53
54 if (*self.heap).block_allocator.is_in_space(pointer) {
55 let cell = pointer;
56 if cell as usize % 8 == 0 && (*self.heap).live_bitmap.has_address(cell) {
57 if (*self.heap).live_bitmap.test(cell)
58 && (*cell.cast::<HeapObjectHeader>()).get_gc_info_index()
59 != GCInfoIndex(0)
60 {
61 let hdr = cell.cast::<HeapObjectHeader>();
62
63 self.visit((*hdr).payload(), trace_desc(hdr as _));
64 }
65 }
66 } else {
67 let hdr = (*self.heap).large_space.contains(pointer);
68
69 if !hdr.is_null() {
70 self.visit((*hdr).payload(), trace_desc(hdr));
71 }
72 }
73 scan = scan.add(1);
74 }
75 }
76 }
77}
78
79pub struct SynchronousMarking<'a> {
80 heap: &'a mut Heap,
81}
82
83impl<'a> SynchronousMarking<'a> {
84 pub fn new(heap: &'a mut Heap) -> Self {
85 Self { heap }
86 }
87 pub fn run(&mut self) -> usize {
88 let mut vis = MarkingVisitor {
89 worklist: vec![],
90 heap: &mut self.heap.global,
91 bytes_visited: 0,
92 h: self.heap as *mut _,
93 };
94
95 let mut constraints = std::mem::replace(&mut self.heap.constraints, vec![]);
96 for c in constraints.iter_mut() {
97 c.execute(&mut Visitor { vis: &mut vis })
98 }
99 self.heap.constraints = constraints;
100 while let Some(desc) = vis.worklist.pop() {
101 unsafe {
102 let hdr = HeapObjectHeader::from_object(desc.base_object_payload);
103
104 assert!((*hdr).set_state(CellState::PossiblyGrey, CellState::PossiblyBlack));
105 (desc.callback)(&mut Visitor { vis: &mut vis }, desc.base_object_payload);
106 }
107 }
108 vis.bytes_visited
109 }
110}