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