mmtk/plan/generational/
gc_work.rs1use atomic::Ordering;
2
3use crate::plan::tracing::gc_work::closure::{ProcessNodes, ProcessSlots};
4use crate::plan::tracing::Trace;
5use crate::plan::PlanTraceObject;
6use crate::policy::gc_work::TraceKind;
7use crate::scheduler::{GCWork, GCWorker, WorkBucketStage};
8use crate::util::os::*;
9use crate::util::ObjectReference;
10use crate::vm::slot::MemorySlice;
11use crate::vm::*;
12use crate::MMTK;
13use std::marker::PhantomData;
14
15use super::global::GenerationalPlanExt;
16
17pub struct GenNurseryTrace<
21 VM: VMBinding,
22 P: GenerationalPlanExt<VM> + PlanTraceObject<VM>,
23 const KIND: TraceKind,
24> {
25 plan: &'static P,
26 phantom_data: PhantomData<VM>,
27}
28
29impl<VM: VMBinding, P: GenerationalPlanExt<VM> + PlanTraceObject<VM>, const KIND: TraceKind> Clone
30 for GenNurseryTrace<VM, P, KIND>
31{
32 fn clone(&self) -> Self {
33 Self {
34 plan: self.plan,
35 phantom_data: PhantomData,
36 }
37 }
38}
39
40impl<VM: VMBinding, P: GenerationalPlanExt<VM> + PlanTraceObject<VM>, const KIND: TraceKind> Trace
41 for GenNurseryTrace<VM, P, KIND>
42{
43 type VM = VM;
44
45 fn from_mmtk(mmtk: &'static MMTK<Self::VM>) -> Self {
46 Self {
47 plan: mmtk.get_plan().downcast_ref().unwrap(),
48 phantom_data: PhantomData,
49 }
50 }
51
52 fn trace_object<Q: crate::ObjectQueue>(
53 &self,
54 worker: &mut GCWorker<Self::VM>,
55 object: ObjectReference,
56 queue: &mut Q,
57 ) -> ObjectReference {
58 self.plan
59 .trace_object_nursery::<_, KIND>(queue, object, worker)
60 }
61
62 fn post_scan_object(&self, object: ObjectReference) {
63 self.plan.post_scan_object(object);
64 }
65
66 fn may_move_objects() -> bool {
67 true
71 }
72}
73
74pub struct ProcessModBuf<T: Trace> {
78 modbuf: Vec<ObjectReference>,
79 phantom: PhantomData<T>,
80}
81
82impl<T: Trace> ProcessModBuf<T> {
83 pub fn new(modbuf: Vec<ObjectReference>) -> Self {
84 debug_assert!(!modbuf.is_empty());
85 Self {
86 modbuf,
87 phantom: PhantomData,
88 }
89 }
90}
91
92impl<T: Trace> GCWork<T::VM> for ProcessModBuf<T> {
93 fn do_work(&mut self, worker: &mut GCWorker<T::VM>, mmtk: &'static MMTK<T::VM>) {
94 let gen = mmtk.get_plan().generational().unwrap();
96 if gen.is_current_gc_nursery() {
97 for obj in &self.modbuf {
99 debug_assert!(
100 !gen.is_object_in_nursery(*obj),
101 "{} was logged but is not mature. Dumping process memory maps:\n{}",
102 *obj,
103 OS::get_process_memory_maps().unwrap(),
104 );
105 <T::VM as VMBinding>::VMObjectModel::GLOBAL_LOG_BIT_SPEC.store_atomic::<T::VM, u8>(
106 *obj,
107 1,
108 None,
109 Ordering::SeqCst,
110 );
111 }
112 let modbuf = std::mem::take(&mut self.modbuf);
114 GCWork::do_work(
115 &mut ProcessNodes::<T>::new(modbuf, WorkBucketStage::Closure),
116 worker,
117 mmtk,
118 )
119 }
120 }
121}
122
123pub struct ProcessRegionModBuf<T: Trace> {
127 modbuf: Vec<<T::VM as VMBinding>::VMMemorySlice>,
129 phantom: PhantomData<T>,
130}
131
132impl<T: Trace> ProcessRegionModBuf<T> {
133 pub fn new(modbuf: Vec<<T::VM as VMBinding>::VMMemorySlice>) -> Self {
134 Self {
135 modbuf,
136 phantom: PhantomData,
137 }
138 }
139}
140
141impl<T: Trace> GCWork<T::VM> for ProcessRegionModBuf<T> {
142 fn do_work(&mut self, worker: &mut GCWorker<T::VM>, mmtk: &'static MMTK<T::VM>) {
143 if mmtk
145 .get_plan()
146 .generational()
147 .unwrap()
148 .is_current_gc_nursery()
149 {
150 let mut slots = vec![];
152 for slice in &self.modbuf {
153 for slot in slice.iter_slots() {
154 slots.push(slot);
155 }
156 }
157 GCWork::do_work(
159 &mut ProcessSlots::<T>::new(slots, WorkBucketStage::Closure),
160 worker,
161 mmtk,
162 )
163 }
164 }
165}