comet/
marking.rs

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}