Skip to content

Commit bf54dd3

Browse files
authored
Extract common work packet to schedule_common() (#471)
1 parent a08d13d commit bf54dd3

File tree

7 files changed

+68
-198
lines changed

7 files changed

+68
-198
lines changed

src/plan/generational/copying/global.rs

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use crate::plan::Plan;
1111
use crate::plan::PlanConstraints;
1212
use crate::policy::copyspace::CopySpace;
1313
use crate::policy::space::Space;
14-
use crate::scheduler::gc_work::*;
1514
use crate::scheduler::*;
1615
use crate::util::alloc::allocators::AllocatorSelector;
1716
use crate::util::heap::layout::heap_layout::Mmapper;
@@ -21,8 +20,6 @@ use crate::util::heap::HeapMeta;
2120
use crate::util::heap::VMRequest;
2221
use crate::util::metadata::side_metadata::SideMetadataSanity;
2322
use crate::util::options::UnsafeOptionsWrapper;
24-
#[cfg(feature = "sanity")]
25-
use crate::util::sanity::sanity_checker::*;
2623
use crate::util::VMWorkerThread;
2724
use crate::vm::*;
2825
use enum_map::EnumMap;
@@ -85,50 +82,25 @@ impl<VM: VMBinding> Plan for GenCopy<VM> {
8582

8683
fn schedule_collection(&'static self, scheduler: &GCWorkScheduler<VM>) {
8784
let is_full_heap = self.request_full_heap_collection();
88-
89-
// TODO: We should have a schedule_generational
90-
9185
self.base().set_collection_kind::<Self>(self);
9286
self.base().set_gc_status(GcStatus::GcPrepare);
9387
if !is_full_heap {
9488
debug!("Nursery GC");
9589
self.common()
96-
.schedule_common::<GenNurseryProcessEdges<VM, GenCopyCopyContext<VM>>>(
90+
.schedule_common::<Self, GenNurseryProcessEdges<VM, GenCopyCopyContext<VM>>, GenCopyCopyContext<VM>>(
91+
self,
9792
&GENCOPY_CONSTRAINTS,
9893
scheduler,
9994
);
100-
// Stop & scan mutators (mutator scanning can happen before STW)
101-
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(StopMutators::<
102-
GenNurseryProcessEdges<VM, GenCopyCopyContext<VM>>,
103-
>::new());
10495
} else {
10596
debug!("Full heap GC");
10697
self.common()
107-
.schedule_common::<GenCopyMatureProcessEdges<VM>>(&GENCOPY_CONSTRAINTS, scheduler);
108-
// Stop & scan mutators (mutator scanning can happen before STW)
109-
scheduler.work_buckets[WorkBucketStage::Unconstrained]
110-
.add(StopMutators::<GenCopyMatureProcessEdges<VM>>::new());
111-
}
112-
113-
// Prepare global/collectors/mutators
114-
scheduler.work_buckets[WorkBucketStage::Prepare]
115-
.add(Prepare::<Self, GenCopyCopyContext<VM>>::new(self));
116-
if is_full_heap {
117-
scheduler.work_buckets[WorkBucketStage::RefClosure]
118-
.add(ProcessWeakRefs::<GenCopyMatureProcessEdges<VM>>::new());
119-
} else {
120-
scheduler.work_buckets[WorkBucketStage::RefClosure].add(ProcessWeakRefs::<
121-
GenNurseryProcessEdges<VM, GenCopyCopyContext<VM>>,
122-
>::new());
98+
.schedule_common::<Self, GenCopyMatureProcessEdges<VM>, GenCopyCopyContext<VM>>(
99+
self,
100+
&GENCOPY_CONSTRAINTS,
101+
scheduler,
102+
);
123103
}
124-
// Release global/collectors/mutators
125-
scheduler.work_buckets[WorkBucketStage::Release]
126-
.add(Release::<Self, GenCopyCopyContext<VM>>::new(self));
127-
// Resume mutators
128-
#[cfg(feature = "sanity")]
129-
scheduler.work_buckets[WorkBucketStage::Final]
130-
.add(ScheduleSanityGC::<Self, GenCopyCopyContext<VM>>::new(self));
131-
scheduler.set_finalizer(Some(EndOfGC));
132104
}
133105

134106
fn get_allocator_mapping(&self) -> &'static EnumMap<AllocationSemantics, AllocatorSelector> {

src/plan/generational/immix/global.rs

Lines changed: 6 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use crate::plan::Plan;
1010
use crate::plan::PlanConstraints;
1111
use crate::policy::immix::ImmixSpace;
1212
use crate::policy::space::Space;
13-
use crate::scheduler::gc_work::*;
1413
use crate::scheduler::GCWorkScheduler;
1514
use crate::scheduler::GCWorkerLocalPtr;
1615
use crate::scheduler::*;
@@ -129,67 +128,28 @@ impl<VM: VMBinding> Plan for GenImmix<VM> {
129128
if !is_full_heap {
130129
debug!("Nursery GC");
131130
self.common()
132-
.schedule_common::<GenNurseryProcessEdges<VM, GenImmixCopyContext<VM>>>(
131+
.schedule_common::<Self, GenNurseryProcessEdges<VM, GenImmixCopyContext<VM>>, GenImmixCopyContext<VM>>(
132+
self,
133133
&GENIMMIX_CONSTRAINTS,
134134
scheduler,
135135
);
136-
// Stop & scan mutators (mutator scanning can happen before STW)
137-
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(StopMutators::<
138-
GenNurseryProcessEdges<VM, GenImmixCopyContext<VM>>,
139-
>::new());
140136
} else if defrag {
141137
debug!("Full heap GC Defrag");
142138
self.common()
143-
.schedule_common::<GenImmixMatureProcessEdges<VM, { TraceKind::Defrag }>>(
139+
.schedule_common::<Self, GenImmixMatureProcessEdges<VM, { TraceKind::Defrag }>, GenImmixCopyContext<VM>>(
140+
self,
144141
&GENIMMIX_CONSTRAINTS,
145142
scheduler,
146143
);
147-
// Stop & scan mutators (mutator scanning can happen before STW)
148-
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(StopMutators::<
149-
GenImmixMatureProcessEdges<VM, { TraceKind::Defrag }>,
150-
>::new());
151144
} else {
152145
debug!("Full heap GC Fast");
153146
self.common()
154-
.schedule_common::<GenImmixMatureProcessEdges<VM, { TraceKind::Fast }>>(
147+
.schedule_common::<Self, GenImmixMatureProcessEdges<VM, { TraceKind::Fast }>, GenImmixCopyContext<VM>>(
148+
self,
155149
&GENIMMIX_CONSTRAINTS,
156150
scheduler,
157151
);
158-
// Stop & scan mutators (mutator scanning can happen before STW)
159-
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(StopMutators::<
160-
GenImmixMatureProcessEdges<VM, { TraceKind::Fast }>,
161-
>::new());
162152
}
163-
164-
// Prepare global/collectors/mutators
165-
scheduler.work_buckets[WorkBucketStage::Prepare]
166-
.add(Prepare::<Self, GenImmixCopyContext<VM>>::new(self));
167-
if is_full_heap {
168-
if defrag {
169-
scheduler.work_buckets[WorkBucketStage::RefClosure].add(ProcessWeakRefs::<
170-
GenImmixMatureProcessEdges<VM, { TraceKind::Defrag }>,
171-
>::new());
172-
} else {
173-
scheduler.work_buckets[WorkBucketStage::RefClosure].add(ProcessWeakRefs::<
174-
GenImmixMatureProcessEdges<VM, { TraceKind::Fast }>,
175-
>::new());
176-
}
177-
} else {
178-
scheduler.work_buckets[WorkBucketStage::RefClosure].add(ProcessWeakRefs::<
179-
GenNurseryProcessEdges<VM, GenImmixCopyContext<VM>>,
180-
>::new());
181-
}
182-
// Release global/collectors/mutators
183-
scheduler.work_buckets[WorkBucketStage::Release]
184-
.add(Release::<Self, GenImmixCopyContext<VM>>::new(self));
185-
// Resume mutators
186-
#[cfg(feature = "sanity")]
187-
{
188-
use crate::util::sanity::sanity_checker::*;
189-
scheduler.work_buckets[WorkBucketStage::Final]
190-
.add(ScheduleSanityGC::<Self, GenImmixCopyContext<VM>>::new(self));
191-
}
192-
scheduler.set_finalizer(Some(EndOfGC));
193153
}
194154

195155
fn get_allocator_mapping(&self) -> &'static EnumMap<AllocationSemantics, AllocatorSelector> {

src/plan/global.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -919,12 +919,46 @@ impl<VM: VMBinding> CommonPlan<VM> {
919919
self.base.release(tls, full_heap)
920920
}
921921

922-
pub fn schedule_common<E: ProcessEdgesWork<VM = VM>>(
922+
/// Schedule all the common work packets
923+
pub fn schedule_common<
924+
P: Plan<VM = VM>,
925+
E: ProcessEdgesWork<VM = VM>,
926+
C: CopyContext<VM = VM> + GCWorkerLocal,
927+
>(
923928
&self,
929+
plan: &'static P,
924930
constraints: &'static PlanConstraints,
925931
scheduler: &GCWorkScheduler<VM>,
926932
) {
927-
// Schedule finalization
933+
use crate::scheduler::gc_work::*;
934+
935+
// Stop & scan mutators (mutator scanning can happen before STW)
936+
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(StopMutators::<E>::new());
937+
938+
// Prepare global/collectors/mutators
939+
scheduler.work_buckets[WorkBucketStage::Prepare].add(Prepare::<P, C>::new(plan));
940+
941+
// VM-specific weak ref processing
942+
scheduler.work_buckets[WorkBucketStage::RefClosure].add(ProcessWeakRefs::<E>::new());
943+
944+
// Release global/collectors/mutators
945+
scheduler.work_buckets[WorkBucketStage::Release].add(Release::<P, C>::new(plan));
946+
947+
// Analysis GC work
948+
#[cfg(feature = "analysis")]
949+
{
950+
use crate::util::analysis::GcHookWork;
951+
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(GcHookWork);
952+
}
953+
954+
// Sanity
955+
#[cfg(feature = "sanity")]
956+
{
957+
use crate::util::sanity::sanity_checker::ScheduleSanityGC;
958+
scheduler.work_buckets[WorkBucketStage::Final].add(ScheduleSanityGC::<P, C>::new(plan));
959+
}
960+
961+
// Finalization
928962
if !self.base.options.no_finalizer {
929963
use crate::util::finalizable_processor::{Finalization, ForwardFinalization};
930964
// finalization
@@ -935,6 +969,9 @@ impl<VM: VMBinding> CommonPlan<VM> {
935969
.add(ForwardFinalization::<E>::new());
936970
}
937971
}
972+
973+
// Set EndOfGC to run at the end
974+
scheduler.set_finalizer(Some(EndOfGC));
938975
}
939976

940977
pub fn stacks_prepared(&self) -> bool {

src/plan/immix/global.rs

Lines changed: 5 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,15 @@ use crate::plan::AllocationSemantics;
77
use crate::plan::Plan;
88
use crate::plan::PlanConstraints;
99
use crate::policy::space::Space;
10-
use crate::scheduler::gc_work::*;
1110
use crate::scheduler::*;
1211
use crate::util::alloc::allocators::AllocatorSelector;
13-
#[cfg(feature = "analysis")]
14-
use crate::util::analysis::GcHookWork;
1512
use crate::util::heap::layout::heap_layout::Mmapper;
1613
use crate::util::heap::layout::heap_layout::VMMap;
1714
use crate::util::heap::layout::vm_layout_constants::{HEAP_END, HEAP_START};
1815
use crate::util::heap::HeapMeta;
1916
use crate::util::metadata::side_metadata::SideMetadataContext;
2017
use crate::util::metadata::side_metadata::SideMetadataSanity;
2118
use crate::util::options::UnsafeOptionsWrapper;
22-
#[cfg(feature = "sanity")]
23-
use crate::util::sanity::sanity_checker::*;
2419
use crate::vm::VMBinding;
2520
use crate::{mmtk::MMTK, policy::immix::ImmixSpace, util::opaque_pointer::VMWorkerThread};
2621
use std::sync::atomic::AtomicBool;
@@ -92,45 +87,16 @@ impl<VM: VMBinding> Plan for Immix<VM> {
9287
self.base().is_user_triggered_collection(),
9388
self.base().options.full_heap_system_gc,
9489
);
95-
// Stop & scan mutators (mutator scanning can happen before STW)
96-
// The blocks are not identical, clippy is wrong. Probably it does not recognize the constant type parameter.
97-
#[allow(clippy::if_same_then_else)]
98-
// The two StopMutators have different types parameters, thus we cannot extract the common code before add().
99-
#[allow(clippy::branches_sharing_code)]
100-
if in_defrag {
101-
scheduler.work_buckets[WorkBucketStage::Unconstrained]
102-
.add(StopMutators::<ImmixProcessEdges<VM, { TraceKind::Defrag }>>::new());
103-
} else {
104-
scheduler.work_buckets[WorkBucketStage::Unconstrained]
105-
.add(StopMutators::<ImmixProcessEdges<VM, { TraceKind::Fast }>>::new());
106-
}
107-
// Prepare global/collectors/mutators
108-
scheduler.work_buckets[WorkBucketStage::Prepare]
109-
.add(Prepare::<Self, ImmixCopyContext<VM>>::new(self));
90+
11091
// The blocks are not identical, clippy is wrong. Probably it does not recognize the constant type parameter.
11192
#[allow(clippy::if_same_then_else)]
112-
// The two StopMutators have different types parameters, thus we cannot extract the common code before add().
113-
#[allow(clippy::branches_sharing_code)]
11493
if in_defrag {
115-
scheduler.work_buckets[WorkBucketStage::RefClosure].add(ProcessWeakRefs::<
116-
ImmixProcessEdges<VM, { TraceKind::Defrag }>,
117-
>::new());
94+
self.common()
95+
.schedule_common::<Self, ImmixProcessEdges<VM, { TraceKind::Defrag }>, ImmixCopyContext<VM>>(self, &IMMIX_CONSTRAINTS, scheduler);
11896
} else {
119-
scheduler.work_buckets[WorkBucketStage::RefClosure]
120-
.add(ProcessWeakRefs::<ImmixProcessEdges<VM, { TraceKind::Fast }>>::new());
97+
self.common()
98+
.schedule_common::<Self, ImmixProcessEdges<VM, { TraceKind::Fast }>, ImmixCopyContext<VM>>(self, &IMMIX_CONSTRAINTS, scheduler);
12199
}
122-
// Release global/collectors/mutators
123-
scheduler.work_buckets[WorkBucketStage::Release]
124-
.add(Release::<Self, ImmixCopyContext<VM>>::new(self));
125-
// Analysis routine that is ran. It is generally recommended to take advantage
126-
// of the scheduling system we have in place for more performance
127-
#[cfg(feature = "analysis")]
128-
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(GcHookWork);
129-
// Resume mutators
130-
#[cfg(feature = "sanity")]
131-
scheduler.work_buckets[WorkBucketStage::Final]
132-
.add(ScheduleSanityGC::<Self, ImmixCopyContext<VM>>::new(self));
133-
scheduler.set_finalizer(Some(EndOfGC));
134100
}
135101

136102
fn get_allocator_mapping(&self) -> &'static EnumMap<AllocationSemantics, AllocatorSelector> {

src/plan/marksweep/global.rs

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,16 @@ use crate::plan::PlanConstraints;
1111
use crate::policy::mallocspace::metadata::ACTIVE_CHUNK_METADATA_SPEC;
1212
use crate::policy::mallocspace::MallocSpace;
1313
use crate::policy::space::Space;
14-
use crate::scheduler::gc_work::*;
1514
use crate::scheduler::*;
1615
use crate::util::alloc::allocators::AllocatorSelector;
1716
#[cfg(not(feature = "global_alloc_bit"))]
1817
use crate::util::alloc_bit::ALLOC_SIDE_METADATA_SPEC;
19-
#[cfg(feature = "analysis")]
20-
use crate::util::analysis::GcHookWork;
2118
use crate::util::heap::layout::heap_layout::Mmapper;
2219
use crate::util::heap::layout::heap_layout::VMMap;
2320
use crate::util::heap::layout::vm_layout_constants::{HEAP_END, HEAP_START};
2421
use crate::util::heap::HeapMeta;
2522
use crate::util::metadata::side_metadata::{SideMetadataContext, SideMetadataSanity};
2623
use crate::util::options::UnsafeOptionsWrapper;
27-
#[cfg(feature = "sanity")]
28-
use crate::util::sanity::sanity_checker::*;
2924
use crate::util::VMWorkerThread;
3025
use crate::vm::VMBinding;
3126
use std::sync::Arc;
@@ -62,26 +57,12 @@ impl<VM: VMBinding> Plan for MarkSweep<VM> {
6257
self.base().set_collection_kind::<Self>(self);
6358
self.base().set_gc_status(GcStatus::GcPrepare);
6459
self.common()
65-
.schedule_common::<MSProcessEdges<VM>>(&MS_CONSTRAINTS, scheduler);
66-
// Stop & scan mutators (mutator scanning can happen before STW)
67-
scheduler.work_buckets[WorkBucketStage::Unconstrained]
68-
.add(StopMutators::<MSProcessEdges<VM>>::new());
69-
// Prepare global/collectors/mutators
70-
scheduler.work_buckets[WorkBucketStage::Prepare]
71-
.add(Prepare::<Self, NoCopy<VM>>::new(self));
60+
.schedule_common::<Self, MSProcessEdges<VM>, NoCopy<VM>>(
61+
self,
62+
&MS_CONSTRAINTS,
63+
scheduler,
64+
);
7265
scheduler.work_buckets[WorkBucketStage::Prepare].add(MSSweepChunks::<VM>::new(self));
73-
scheduler.work_buckets[WorkBucketStage::RefClosure]
74-
.add(ProcessWeakRefs::<MSProcessEdges<VM>>::new());
75-
// Release global/collectors/mutators
76-
scheduler.work_buckets[WorkBucketStage::Release]
77-
.add(Release::<Self, NoCopy<VM>>::new(self));
78-
#[cfg(feature = "analysis")]
79-
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(GcHookWork);
80-
// Resume mutators
81-
#[cfg(feature = "sanity")]
82-
scheduler.work_buckets[WorkBucketStage::Final]
83-
.add(ScheduleSanityGC::<Self, NoCopy<VM>>::new(self));
84-
scheduler.set_finalizer(Some(EndOfGC));
8566
}
8667

8768
fn get_allocator_mapping(&self) -> &'static EnumMap<AllocationSemantics, AllocatorSelector> {

src/plan/pageprotect/global.rs

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,15 @@ use crate::plan::AllocationSemantics;
66
use crate::plan::Plan;
77
use crate::plan::PlanConstraints;
88
use crate::policy::space::Space;
9-
use crate::scheduler::gc_work::*;
109
use crate::scheduler::*;
1110
use crate::util::alloc::allocators::AllocatorSelector;
12-
#[cfg(feature = "analysis")]
13-
use crate::util::analysis::GcHookWork;
1411
use crate::util::heap::layout::heap_layout::Mmapper;
1512
use crate::util::heap::layout::heap_layout::VMMap;
1613
use crate::util::heap::layout::vm_layout_constants::{HEAP_END, HEAP_START};
1714
use crate::util::heap::HeapMeta;
1815
use crate::util::heap::VMRequest;
1916
use crate::util::metadata::side_metadata::SideMetadataContext;
2017
use crate::util::options::UnsafeOptionsWrapper;
21-
#[cfg(feature = "sanity")]
22-
use crate::util::sanity::sanity_checker::*;
2318
use crate::{plan::global::BasePlan, vm::VMBinding};
2419
use crate::{
2520
plan::global::{CommonPlan, NoCopy},
@@ -81,27 +76,7 @@ impl<VM: VMBinding> Plan for PageProtect<VM> {
8176
self.base().set_collection_kind::<Self>(self);
8277
self.base().set_gc_status(GcStatus::GcPrepare);
8378
self.common()
84-
.schedule_common::<PPProcessEdges<VM>>(&CONSTRAINTS, scheduler);
85-
// Stop & scan mutators (mutator scanning can happen before STW)
86-
scheduler.work_buckets[WorkBucketStage::Unconstrained]
87-
.add(StopMutators::<PPProcessEdges<VM>>::new());
88-
// Prepare global/collectors/mutators
89-
scheduler.work_buckets[WorkBucketStage::Prepare]
90-
.add(Prepare::<Self, NoCopy<VM>>::new(self));
91-
scheduler.work_buckets[WorkBucketStage::RefClosure]
92-
.add(ProcessWeakRefs::<PPProcessEdges<VM>>::new());
93-
// Release global/collectors/mutators
94-
scheduler.work_buckets[WorkBucketStage::Release]
95-
.add(Release::<Self, NoCopy<VM>>::new(self));
96-
// Scheduling all the gc hooks of analysis routines. It is generally recommended
97-
// to take advantage of the scheduling system we have in place for more performance
98-
#[cfg(feature = "analysis")]
99-
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(GcHookWork);
100-
// Resume mutators
101-
#[cfg(feature = "sanity")]
102-
scheduler.work_buckets[WorkBucketStage::Final]
103-
.add(ScheduleSanityGC::<Self, NoCopy<VM>>::new(self));
104-
scheduler.set_finalizer(Some(EndOfGC));
79+
.schedule_common::<Self, PPProcessEdges<VM>, NoCopy<VM>>(self, &CONSTRAINTS, scheduler);
10580
}
10681

10782
fn get_allocator_mapping(&self) -> &'static EnumMap<AllocationSemantics, AllocatorSelector> {

0 commit comments

Comments
 (0)