mmtk/plan/lxr/gc_work/
mod.rs

1use super::global::LXR;
2use crate::plan::tracing::UnsupportedTrace;
3use crate::plan::VectorObjectQueue;
4use crate::scheduler::gc_work::RootKind;
5use crate::scheduler::{GCWorker, WorkBucketStage};
6use crate::util::ObjectReference;
7use crate::vm::{RootsWorkFactory, VMBinding};
8use crate::{Plan, MMTK};
9use std::marker::PhantomData;
10
11pub mod mature_evac;
12pub mod mature_sweeping;
13pub mod nursery_sweeping;
14pub mod prepare;
15pub mod rc;
16pub mod tracing;
17
18use rc::CollectRoots;
19
20/// Common base fields shared by LXR's custom root/closure work packets.
21///
22/// This used to be `crate::scheduler::gc_work::ProcessEdgesBase`. After upstream replaced
23/// `ProcessEdgesWork` with the stateless `Trace` API, LXR keeps its own work-packet based
24/// closures, so this helper lives locally in the LXR plan.
25pub struct ProcessEdgesBase<VM: VMBinding> {
26    pub slots: Vec<VM::VMSlot>,
27    pub nodes: VectorObjectQueue,
28    mmtk: &'static MMTK<VM>,
29    // Use raw pointer for fast pointer dereferencing, instead of using `Option<&'static mut GCWorker<VM>>`.
30    // Because a copying gc will dereference this pointer at least once for every object copy.
31    worker: *mut GCWorker<VM>,
32    pub roots: bool,
33    pub root_kind: Option<RootKind>,
34    pub bucket: WorkBucketStage,
35}
36
37unsafe impl<VM: VMBinding> Send for ProcessEdgesBase<VM> {}
38
39impl<VM: VMBinding> ProcessEdgesBase<VM> {
40    pub fn new(
41        slots: Vec<VM::VMSlot>,
42        roots: bool,
43        mmtk: &'static MMTK<VM>,
44        bucket: WorkBucketStage,
45    ) -> Self {
46        #[cfg(feature = "extreme_assertions")]
47        if crate::util::slot_logger::should_check_duplicate_slots(mmtk.get_plan()) {
48            for slot in &slots {
49                // log slot, panic if already logged
50                mmtk.slot_logger.log_slot(*slot);
51            }
52        }
53        Self {
54            slots,
55            nodes: VectorObjectQueue::new(),
56            mmtk,
57            worker: std::ptr::null_mut(),
58            roots,
59            root_kind: if roots { Some(RootKind::Strong) } else { None },
60            bucket,
61        }
62    }
63
64    pub fn set_worker(&mut self, worker: &mut GCWorker<VM>) {
65        self.worker = worker;
66    }
67
68    pub fn worker(&self) -> &'static mut GCWorker<VM> {
69        unsafe { &mut *self.worker }
70    }
71
72    pub fn mmtk(&self) -> &'static MMTK<VM> {
73        self.mmtk
74    }
75
76    pub fn plan(&self) -> &'static dyn Plan<VM = VM> {
77        self.mmtk.get_plan()
78    }
79}
80
81/// The [`crate::scheduler::GCWorkContext`] for LXR.
82///
83/// LXR does not use the generic `Trace`-based closures. Instead it schedules its own custom work
84/// packets. The `DefaultTrace`/`PinningTrace` members are therefore set to [`UnsupportedTrace`],
85/// and root scanning is routed through [`LXRRootsWorkFactory`].
86pub struct LXRGCWorkContext<VM: VMBinding>(PhantomData<VM>);
87
88impl<VM: VMBinding> crate::scheduler::GCWorkContext for LXRGCWorkContext<VM> {
89    type VM = VM;
90    type PlanType = LXR<VM>;
91    type DefaultTrace = UnsupportedTrace<VM>;
92    type PinningTrace = UnsupportedTrace<VM>;
93
94    fn make_roots_work_factory(
95        mmtk: &'static MMTK<VM>,
96    ) -> impl RootsWorkFactory<<VM as VMBinding>::VMSlot> {
97        LXRRootsWorkFactory::new(mmtk)
98    }
99}
100
101/// The [`RootsWorkFactory`] used by LXR. Roots are processed by reference-counting them through
102/// [`CollectRoots`] (which spawns `ProcessIncs`).
103pub struct LXRRootsWorkFactory<VM: VMBinding> {
104    mmtk: &'static MMTK<VM>,
105}
106
107impl<VM: VMBinding> Clone for LXRRootsWorkFactory<VM> {
108    fn clone(&self) -> Self {
109        Self { mmtk: self.mmtk }
110    }
111}
112
113impl<VM: VMBinding> LXRRootsWorkFactory<VM> {
114    fn new(mmtk: &'static MMTK<VM>) -> Self {
115        Self { mmtk }
116    }
117}
118
119impl<VM: VMBinding> RootsWorkFactory<VM::VMSlot> for LXRRootsWorkFactory<VM> {
120    fn create_process_roots_work_with_root_kind(&mut self, slots: Vec<VM::VMSlot>, kind: RootKind) {
121        let stage = self.mmtk.get_plan().root_scanning_stage();
122        let mut w = CollectRoots::new(slots, true, self.mmtk, stage);
123        w.root_kind = Some(kind);
124        crate::memory_manager::add_work_packet(self.mmtk, stage, w);
125    }
126
127    fn create_process_pinning_roots_work(&mut self, _nodes: Vec<ObjectReference>) {
128        unreachable!("LXR does not support pinning roots");
129    }
130
131    fn create_process_tpinning_roots_work(&mut self, _nodes: Vec<ObjectReference>) {
132        unreachable!("LXR does not support transitive pinning roots");
133    }
134}