mmtk/plan/tracing/gc_work/
mod.rs1pub(crate) mod closure;
2pub(crate) mod root;
3pub(crate) mod weakref;
4
5use std::marker::PhantomData;
6
7use crate::{
8 plan::{
9 tracing::{gc_work::closure::ProcessNodes, Trace},
10 VectorObjectQueue,
11 },
12 scheduler::{GCWorker, WorkBucketStage},
13 util::ObjectReference,
14 vm::{ObjectTracer, ObjectTracerContext},
15};
16
17#[derive(Clone)]
21pub(crate) struct DefaultObjectTracerContext<T: Trace> {
22 stage: WorkBucketStage,
23 phantom_data: PhantomData<T>,
24}
25
26impl<T: Trace> DefaultObjectTracerContext<T> {
27 pub fn new(stage: WorkBucketStage) -> Self {
28 Self {
29 stage,
30 phantom_data: PhantomData,
31 }
32 }
33}
34
35impl<T: Trace> ObjectTracerContext<T::VM> for DefaultObjectTracerContext<T> {
36 type TracerType<'w> = DefaultObjectTracer<'w, T>;
37
38 fn with_tracer<'w, R, F>(&self, worker: &'w mut GCWorker<T::VM>, func: F) -> R
39 where
40 F: FnOnce(&mut Self::TracerType<'w>) -> R,
41 {
42 let mmtk = worker.mmtk;
43
44 let mut tracer = DefaultObjectTracer::new(worker, T::from_mmtk(mmtk), self.stage);
46
47 let result = func(&mut tracer);
49
50 tracer.flush_if_not_empty();
52
53 result
54 }
55}
56
57pub(crate) struct DefaultObjectTracer<'w, T: Trace> {
60 worker: &'w mut GCWorker<T::VM>,
61 trace: T,
62 queue: VectorObjectQueue,
63 stage: WorkBucketStage,
64}
65
66impl<T: Trace> ObjectTracer for DefaultObjectTracer<'_, T> {
67 fn trace_object(&mut self, object: ObjectReference) -> ObjectReference {
70 let result = self
71 .trace
72 .trace_object(self.worker, object, &mut self.queue);
73 self.flush_if_full();
74 result
75 }
76}
77
78impl<'w, T: Trace> DefaultObjectTracer<'w, T> {
79 fn new(worker: &'w mut GCWorker<T::VM>, trace: T, stage: WorkBucketStage) -> Self {
80 Self {
81 worker,
82 trace,
83 queue: VectorObjectQueue::new(),
84 stage,
85 }
86 }
87
88 fn flush_if_full(&mut self) {
89 if self.queue.is_full() {
90 self.flush();
91 }
92 }
93
94 pub fn flush_if_not_empty(&mut self) {
95 if !self.queue.is_empty() {
96 self.flush();
97 }
98 }
99
100 fn flush(&mut self) {
101 let next_nodes = self.queue.take();
102 assert!(!next_nodes.is_empty());
103 let work_packet = ProcessNodes::<T>::new(next_nodes, self.stage);
104 self.worker.scheduler().work_buckets[self.stage].add(work_packet);
105 }
106}