mmtk/plan/generational/
gc_work.rs1use atomic::Ordering;
2
3use crate::plan::PlanTraceObject;
4use crate::plan::VectorObjectQueue;
5use crate::policy::gc_work::TraceKind;
6use crate::scheduler::{gc_work::*, GCWork, GCWorker, WorkBucketStage};
7use crate::util::os::*;
8use crate::util::ObjectReference;
9use crate::vm::slot::{MemorySlice, Slot};
10use crate::vm::*;
11use crate::MMTK;
12use std::marker::PhantomData;
13use std::ops::{Deref, DerefMut};
14
15use super::global::GenerationalPlanExt;
16
17pub struct GenNurseryProcessEdges<
21 VM: VMBinding,
22 P: GenerationalPlanExt<VM> + PlanTraceObject<VM>,
23 const KIND: TraceKind,
24> {
25 plan: &'static P,
26 base: ProcessEdgesBase<VM>,
27}
28
29impl<VM: VMBinding, P: GenerationalPlanExt<VM> + PlanTraceObject<VM>, const KIND: TraceKind>
30 ProcessEdgesWork for GenNurseryProcessEdges<VM, P, KIND>
31{
32 type VM = VM;
33 type ScanObjectsWorkType = PlanScanObjects<Self, P>;
34
35 fn new(
36 slots: Vec<SlotOf<Self>>,
37 roots: bool,
38 mmtk: &'static MMTK<VM>,
39 bucket: WorkBucketStage,
40 ) -> Self {
41 let base = ProcessEdgesBase::new(slots, roots, mmtk, bucket);
42 let plan = base.plan().downcast_ref().unwrap();
43 Self { plan, base }
44 }
45
46 fn trace_object(&mut self, object: ObjectReference) -> ObjectReference {
47 let worker = self.worker();
49 self.plan.trace_object_nursery::<VectorObjectQueue, KIND>(
50 &mut self.base.nodes,
51 object,
52 worker,
53 )
54 }
55
56 fn process_slot(&mut self, slot: SlotOf<Self>) {
57 let Some(object) = slot.load() else {
58 return;
60 };
61 let new_object = self.trace_object(object);
62 debug_assert!(!self.plan.is_object_in_nursery(new_object));
63 if new_object != object {
66 slot.store(new_object);
67 }
68 }
69
70 fn create_scan_work(&self, nodes: Vec<ObjectReference>) -> Self::ScanObjectsWorkType {
71 PlanScanObjects::new(self.plan, nodes, false, self.bucket)
72 }
73}
74
75impl<VM: VMBinding, P: GenerationalPlanExt<VM> + PlanTraceObject<VM>, const KIND: TraceKind> Deref
76 for GenNurseryProcessEdges<VM, P, KIND>
77{
78 type Target = ProcessEdgesBase<VM>;
79 fn deref(&self) -> &Self::Target {
80 &self.base
81 }
82}
83
84impl<VM: VMBinding, P: GenerationalPlanExt<VM> + PlanTraceObject<VM>, const KIND: TraceKind>
85 DerefMut for GenNurseryProcessEdges<VM, P, KIND>
86{
87 fn deref_mut(&mut self) -> &mut Self::Target {
88 &mut self.base
89 }
90}
91
92pub struct ProcessModBuf<E: ProcessEdgesWork> {
96 modbuf: Vec<ObjectReference>,
97 phantom: PhantomData<E>,
98}
99
100impl<E: ProcessEdgesWork> ProcessModBuf<E> {
101 pub fn new(modbuf: Vec<ObjectReference>) -> Self {
102 debug_assert!(!modbuf.is_empty());
103 Self {
104 modbuf,
105 phantom: PhantomData,
106 }
107 }
108}
109
110impl<E: ProcessEdgesWork> GCWork<E::VM> for ProcessModBuf<E> {
111 fn do_work(&mut self, worker: &mut GCWorker<E::VM>, mmtk: &'static MMTK<E::VM>) {
112 let gen = mmtk.get_plan().generational().unwrap();
114 if gen.is_current_gc_nursery() {
115 for obj in &self.modbuf {
117 debug_assert!(
118 !gen.is_object_in_nursery(*obj),
119 "{} was logged but is not mature. Dumping process memory maps:\n{}",
120 *obj,
121 OS::get_process_memory_maps().unwrap(),
122 );
123 <E::VM as VMBinding>::VMObjectModel::GLOBAL_LOG_BIT_SPEC.store_atomic::<E::VM, u8>(
124 *obj,
125 1,
126 None,
127 Ordering::SeqCst,
128 );
129 }
130 let modbuf = std::mem::take(&mut self.modbuf);
132 GCWork::do_work(
133 &mut ScanObjects::<E>::new(modbuf, false, WorkBucketStage::Closure),
134 worker,
135 mmtk,
136 )
137 }
138 }
139}
140
141pub struct ProcessRegionModBuf<E: ProcessEdgesWork> {
145 modbuf: Vec<<E::VM as VMBinding>::VMMemorySlice>,
147 phantom: PhantomData<E>,
148}
149
150impl<E: ProcessEdgesWork> ProcessRegionModBuf<E> {
151 pub fn new(modbuf: Vec<<E::VM as VMBinding>::VMMemorySlice>) -> Self {
152 Self {
153 modbuf,
154 phantom: PhantomData,
155 }
156 }
157}
158
159impl<E: ProcessEdgesWork> GCWork<E::VM> for ProcessRegionModBuf<E> {
160 fn do_work(&mut self, worker: &mut GCWorker<E::VM>, mmtk: &'static MMTK<E::VM>) {
161 if mmtk
163 .get_plan()
164 .generational()
165 .unwrap()
166 .is_current_gc_nursery()
167 {
168 let mut slots = vec![];
170 for slice in &self.modbuf {
171 for slot in slice.iter_slots() {
172 slots.push(slot);
173 }
174 }
175 GCWork::do_work(
177 &mut E::new(slots, false, mmtk, WorkBucketStage::Closure),
178 worker,
179 mmtk,
180 )
181 }
182 }
183}