Skip to content

Commit 1fc31f6

Browse files
authored
Simplify type parameters for schedule_common() (#487)
* Introduce GCWorkContext * Use GCWorkContext for schedule_common() * Use GCWorkContext for Prepare and Release * Fix tutorial code * Move schedule_common() to GCScheduler
1 parent 4274987 commit 1fc31f6

File tree

22 files changed

+230
-153
lines changed

22 files changed

+230
-153
lines changed

docs/tutorial/code/mygc_semispace/gc_work.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,14 @@ impl<VM: VMBinding> DerefMut for MyGCProcessEdges<VM> {
149149
&mut self.base
150150
}
151151
}
152-
// ANCHOR_END: deref
152+
// ANCHOR_END: deref
153+
154+
// ANCHOR: workcontext
155+
pub struct MyGCWorkContext<VM: VMBinding>(std::marker::PhantomData<VM>);
156+
impl<VM: VMBinding> crate::scheduler::GCWorkContext for MyGCWorkContext<VM> {
157+
type VM = VM;
158+
type PlanType = MyGC<VM>;
159+
type CopyContextType = MyGCCopyContext<VM>;
160+
type ProcessEdgesWorkType = MyGCProcessEdges<VM>;
161+
}
162+
// ANCHOR_END: workcontext

docs/tutorial/code/mygc_semispace/global.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::plan::global::BasePlan; //Modify
44
use crate::plan::global::CommonPlan; // Add
55
use crate::plan::global::GcStatus; // Add
66
use crate::plan::mygc::mutator::ALLOCATOR_MAPPING;
7+
use crate::plan::mygc::gc_work::MyGCWorkContext;
78
use crate::plan::AllocationSemantics;
89
use crate::plan::Plan;
910
use crate::plan::PlanConstraints;
@@ -96,13 +97,7 @@ impl<VM: VMBinding> Plan for MyGC<VM> {
9697
fn schedule_collection(&'static self, scheduler: &GCWorkScheduler<VM>) {
9798
self.base().set_collection_kind::<Self>(self);
9899
self.base().set_gc_status(GcStatus::GcPrepare);
99-
scheduler.work_buckets[WorkBucketStage::Unconstrained]
100-
.add(StopMutators::<MyGCProcessEdges<VM>>::new());
101-
scheduler.work_buckets[WorkBucketStage::Prepare]
102-
.add(Prepare::<Self, MyGCCopyContext<VM>>::new(self));
103-
scheduler.work_buckets[WorkBucketStage::Release]
104-
.add(Release::<Self, MyGCCopyContext<VM>>::new(self));
105-
scheduler.set_finalizer(Some(EndOfGC));
100+
scheduler.schedule_common_work::<MyGCWorkContext<VM>>(self);
106101
}
107102
// ANCHOR_END: schedule_collection
108103

docs/tutorial/src/mygc/ss/collection.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,17 @@ scheduler's prepare stage and resumes the mutators. The `StopMutators` work
132132
will invoke code from the bindings to scan threads and other roots, and those
133133
scanning work will further push work for a transitive closure.
134134

135+
Though you can add those work packets by yourself, `GCWorkScheduler` provides a
136+
method `schedule_common_work()` that will add common work packets for you.
137+
138+
To use `schedule_common_work()`, first we need to create a type `MyGCWorkContext`
139+
and implement the trait `GCWorkContext` for it. We create this type in `gc_work.rs`.
140+
141+
```rust
142+
{{#include ../../../code/mygc_semispace/gc_work.rs:workcontext}}
143+
144+
Then we implement `schedule_collection()` using `MyGCWorkContext` and `schedule_common_work()`.
145+
135146
```rust
136147
{{#include ../../../code/mygc_semispace/global.rs:schedule_collection}}
137148
```

src/plan/generational/copying/gc_work.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::global::GenCopy;
2+
use crate::plan::generational::gc_work::GenNurseryProcessEdges;
23
use crate::plan::CopyContext;
34
use crate::plan::PlanConstraints;
45
use crate::policy::space::Space;
@@ -85,6 +86,7 @@ impl<VM: VMBinding> GenCopyMatureProcessEdges<VM> {
8586

8687
impl<VM: VMBinding> ProcessEdgesWork for GenCopyMatureProcessEdges<VM> {
8788
type VM = VM;
89+
8890
fn new(edges: Vec<Address>, roots: bool, mmtk: &'static MMTK<VM>) -> Self {
8991
let base = ProcessEdgesBase::new(edges, roots, mmtk);
9092
let plan = base.plan().downcast_ref::<GenCopy<VM>>().unwrap();
@@ -130,3 +132,19 @@ impl<VM: VMBinding> DerefMut for GenCopyMatureProcessEdges<VM> {
130132
&mut self.base
131133
}
132134
}
135+
136+
pub struct GenCopyNurseryGCWorkContext<VM: VMBinding>(std::marker::PhantomData<VM>);
137+
impl<VM: VMBinding> crate::scheduler::GCWorkContext for GenCopyNurseryGCWorkContext<VM> {
138+
type VM = VM;
139+
type PlanType = GenCopy<VM>;
140+
type CopyContextType = GenCopyCopyContext<VM>;
141+
type ProcessEdgesWorkType = GenNurseryProcessEdges<VM, Self::CopyContextType>;
142+
}
143+
144+
pub(super) struct GenCopyMatureGCWorkContext<VM: VMBinding>(std::marker::PhantomData<VM>);
145+
impl<VM: VMBinding> crate::scheduler::GCWorkContext for GenCopyMatureGCWorkContext<VM> {
146+
type VM = VM;
147+
type PlanType = GenCopy<VM>;
148+
type CopyContextType = GenCopyCopyContext<VM>;
149+
type ProcessEdgesWorkType = GenCopyMatureProcessEdges<VM>;
150+
}

src/plan/generational/copying/global.rs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
use super::gc_work::{GenCopyCopyContext, GenCopyMatureProcessEdges};
1+
use super::gc_work::{GenCopyCopyContext, GenCopyMatureGCWorkContext, GenCopyNurseryGCWorkContext};
22
use super::mutator::ALLOCATOR_MAPPING;
33
use crate::mmtk::MMTK;
4-
use crate::plan::generational::gc_work::GenNurseryProcessEdges;
54
use crate::plan::generational::global::Gen;
65
use crate::plan::global::BasePlan;
76
use crate::plan::global::CommonPlan;
@@ -86,20 +85,10 @@ impl<VM: VMBinding> Plan for GenCopy<VM> {
8685
self.base().set_gc_status(GcStatus::GcPrepare);
8786
if !is_full_heap {
8887
debug!("Nursery GC");
89-
self.common()
90-
.schedule_common::<Self, GenNurseryProcessEdges<VM, GenCopyCopyContext<VM>>, GenCopyCopyContext<VM>>(
91-
self,
92-
&GENCOPY_CONSTRAINTS,
93-
scheduler,
94-
);
88+
scheduler.schedule_common_work::<GenCopyNurseryGCWorkContext<VM>>(self);
9589
} else {
9690
debug!("Full heap GC");
97-
self.common()
98-
.schedule_common::<Self, GenCopyMatureProcessEdges<VM>, GenCopyCopyContext<VM>>(
99-
self,
100-
&GENCOPY_CONSTRAINTS,
101-
scheduler,
102-
);
91+
scheduler.schedule_common_work::<GenCopyMatureGCWorkContext<VM>>(self);
10392
}
10493
}
10594

src/plan/generational/gc_work.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@ use crate::MMTK;
99
use std::ops::{Deref, DerefMut};
1010

1111
/// Process edges for a nursery GC. A generatinoal plan should use this type for a nursery GC.
12-
pub struct GenNurseryProcessEdges<VM: VMBinding, C: CopyContext + GCWorkerLocal> {
12+
pub struct GenNurseryProcessEdges<VM: VMBinding, C: CopyContext<VM = VM> + GCWorkerLocal> {
1313
gen: &'static Gen<VM>,
1414
base: ProcessEdgesBase<GenNurseryProcessEdges<VM, C>>,
1515
}
1616

17-
impl<VM: VMBinding, C: CopyContext + GCWorkerLocal> ProcessEdgesWork
17+
impl<VM: VMBinding, C: CopyContext<VM = VM> + GCWorkerLocal> ProcessEdgesWork
1818
for GenNurseryProcessEdges<VM, C>
1919
{
2020
type VM = VM;
21+
2122
fn new(edges: Vec<Address>, roots: bool, mmtk: &'static MMTK<VM>) -> Self {
2223
let base = ProcessEdgesBase::new(edges, roots, mmtk);
2324
let gen = base.plan().generational();
@@ -40,14 +41,18 @@ impl<VM: VMBinding, C: CopyContext + GCWorkerLocal> ProcessEdgesWork
4041
}
4142
}
4243

43-
impl<VM: VMBinding, C: CopyContext + GCWorkerLocal> Deref for GenNurseryProcessEdges<VM, C> {
44+
impl<VM: VMBinding, C: CopyContext<VM = VM> + GCWorkerLocal> Deref
45+
for GenNurseryProcessEdges<VM, C>
46+
{
4447
type Target = ProcessEdgesBase<Self>;
4548
fn deref(&self) -> &Self::Target {
4649
&self.base
4750
}
4851
}
4952

50-
impl<VM: VMBinding, C: CopyContext + GCWorkerLocal> DerefMut for GenNurseryProcessEdges<VM, C> {
53+
impl<VM: VMBinding, C: CopyContext<VM = VM> + GCWorkerLocal> DerefMut
54+
for GenNurseryProcessEdges<VM, C>
55+
{
5156
fn deref_mut(&mut self) -> &mut Self::Target {
5257
&mut self.base
5358
}

src/plan/generational/immix/gc_work.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::global::GenImmix;
2+
use crate::plan::generational::gc_work::GenNurseryProcessEdges;
23
use crate::plan::CopyContext;
34
use crate::plan::PlanConstraints;
45
use crate::policy::space::Space;
@@ -187,3 +188,23 @@ impl<VM: VMBinding, const KIND: TraceKind> DerefMut for GenImmixMatureProcessEdg
187188
&mut self.base
188189
}
189190
}
191+
192+
pub struct GenImmixNurseryGCWorkContext<VM: VMBinding>(std::marker::PhantomData<VM>);
193+
impl<VM: VMBinding> crate::scheduler::GCWorkContext for GenImmixNurseryGCWorkContext<VM> {
194+
type VM = VM;
195+
type PlanType = GenImmix<VM>;
196+
type CopyContextType = GenImmixCopyContext<VM>;
197+
type ProcessEdgesWorkType = GenNurseryProcessEdges<VM, Self::CopyContextType>;
198+
}
199+
200+
pub(super) struct GenImmixMatureGCWorkContext<VM: VMBinding, const KIND: TraceKind>(
201+
std::marker::PhantomData<VM>,
202+
);
203+
impl<VM: VMBinding, const KIND: TraceKind> crate::scheduler::GCWorkContext
204+
for GenImmixMatureGCWorkContext<VM, KIND>
205+
{
206+
type VM = VM;
207+
type PlanType = GenImmix<VM>;
208+
type CopyContextType = GenImmixCopyContext<VM>;
209+
type ProcessEdgesWorkType = GenImmixMatureProcessEdges<VM, KIND>;
210+
}

src/plan/generational/immix/global.rs

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
use super::gc_work::{GenImmixCopyContext, GenImmixMatureProcessEdges};
2-
use crate::plan::generational::gc_work::GenNurseryProcessEdges;
1+
use super::gc_work::{
2+
GenImmixCopyContext, GenImmixMatureGCWorkContext, GenImmixNurseryGCWorkContext,
3+
};
34
use crate::plan::generational::global::Gen;
45
use crate::plan::global::BasePlan;
56
use crate::plan::global::CommonPlan;
@@ -127,28 +128,17 @@ impl<VM: VMBinding> Plan for GenImmix<VM> {
127128

128129
if !is_full_heap {
129130
debug!("Nursery GC");
130-
self.common()
131-
.schedule_common::<Self, GenNurseryProcessEdges<VM, GenImmixCopyContext<VM>>, GenImmixCopyContext<VM>>(
132-
self,
133-
&GENIMMIX_CONSTRAINTS,
134-
scheduler,
135-
);
131+
scheduler.schedule_common_work::<GenImmixNurseryGCWorkContext<VM>>(self);
136132
} else if defrag {
137133
debug!("Full heap GC Defrag");
138-
self.common()
139-
.schedule_common::<Self, GenImmixMatureProcessEdges<VM, { TraceKind::Defrag }>, GenImmixCopyContext<VM>>(
134+
scheduler
135+
.schedule_common_work::<GenImmixMatureGCWorkContext<VM, { TraceKind::Defrag }>>(
140136
self,
141-
&GENIMMIX_CONSTRAINTS,
142-
scheduler,
143137
);
144138
} else {
145139
debug!("Full heap GC Fast");
146-
self.common()
147-
.schedule_common::<Self, GenImmixMatureProcessEdges<VM, { TraceKind::Fast }>, GenImmixCopyContext<VM>>(
148-
self,
149-
&GENIMMIX_CONSTRAINTS,
150-
scheduler,
151-
);
140+
scheduler
141+
.schedule_common_work::<GenImmixMatureGCWorkContext<VM, { TraceKind::Fast }>>(self);
152142
}
153143
}
154144

src/plan/global.rs

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use crate::plan::Mutator;
99
use crate::policy::immortalspace::ImmortalSpace;
1010
use crate::policy::largeobjectspace::LargeObjectSpace;
1111
use crate::policy::space::Space;
12-
use crate::scheduler::gc_work::ProcessEdgesWork;
1312
use crate::scheduler::*;
1413
use crate::util::alloc::allocators::AllocatorSelector;
1514
#[cfg(feature = "analysis")]
@@ -952,61 +951,6 @@ impl<VM: VMBinding> CommonPlan<VM> {
952951
self.base.release(tls, full_heap)
953952
}
954953

955-
/// Schedule all the common work packets
956-
pub fn schedule_common<
957-
P: Plan<VM = VM>,
958-
E: ProcessEdgesWork<VM = VM>,
959-
C: CopyContext<VM = VM> + GCWorkerLocal,
960-
>(
961-
&self,
962-
plan: &'static P,
963-
constraints: &'static PlanConstraints,
964-
scheduler: &GCWorkScheduler<VM>,
965-
) {
966-
use crate::scheduler::gc_work::*;
967-
968-
// Stop & scan mutators (mutator scanning can happen before STW)
969-
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(StopMutators::<E>::new());
970-
971-
// Prepare global/collectors/mutators
972-
scheduler.work_buckets[WorkBucketStage::Prepare].add(Prepare::<P, C>::new(plan));
973-
974-
// VM-specific weak ref processing
975-
scheduler.work_buckets[WorkBucketStage::RefClosure].add(ProcessWeakRefs::<E>::new());
976-
977-
// Release global/collectors/mutators
978-
scheduler.work_buckets[WorkBucketStage::Release].add(Release::<P, C>::new(plan));
979-
980-
// Analysis GC work
981-
#[cfg(feature = "analysis")]
982-
{
983-
use crate::util::analysis::GcHookWork;
984-
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(GcHookWork);
985-
}
986-
987-
// Sanity
988-
#[cfg(feature = "sanity")]
989-
{
990-
use crate::util::sanity::sanity_checker::ScheduleSanityGC;
991-
scheduler.work_buckets[WorkBucketStage::Final].add(ScheduleSanityGC::<P, C>::new(plan));
992-
}
993-
994-
// Finalization
995-
if !self.base.options.no_finalizer {
996-
use crate::util::finalizable_processor::{Finalization, ForwardFinalization};
997-
// finalization
998-
scheduler.work_buckets[WorkBucketStage::RefClosure].add(Finalization::<E>::new());
999-
// forward refs
1000-
if constraints.needs_forward_after_liveness {
1001-
scheduler.work_buckets[WorkBucketStage::RefForwarding]
1002-
.add(ForwardFinalization::<E>::new());
1003-
}
1004-
}
1005-
1006-
// Set EndOfGC to run at the end
1007-
scheduler.set_finalizer(Some(EndOfGC));
1008-
}
1009-
1010954
pub fn stacks_prepared(&self) -> bool {
1011955
self.base.stacks_prepared()
1012956
}

src/plan/immix/gc_work.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ impl<VM: VMBinding, const KIND: TraceKind> ImmixProcessEdges<VM, KIND> {
9797

9898
impl<VM: VMBinding, const KIND: TraceKind> ProcessEdgesWork for ImmixProcessEdges<VM, KIND> {
9999
type VM = VM;
100+
100101
const OVERWRITE_REFERENCE: bool = crate::policy::immix::DEFRAG;
101102

102103
fn new(edges: Vec<Address>, roots: bool, mmtk: &'static MMTK<VM>) -> Self {
@@ -166,3 +167,15 @@ impl<VM: VMBinding, const KIND: TraceKind> DerefMut for ImmixProcessEdges<VM, KI
166167
&mut self.base
167168
}
168169
}
170+
171+
pub(super) struct ImmixGCWorkContext<VM: VMBinding, const KIND: TraceKind>(
172+
std::marker::PhantomData<VM>,
173+
);
174+
impl<VM: VMBinding, const KIND: TraceKind> crate::scheduler::GCWorkContext
175+
for ImmixGCWorkContext<VM, KIND>
176+
{
177+
type VM = VM;
178+
type PlanType = Immix<VM>;
179+
type CopyContextType = ImmixCopyContext<VM>;
180+
type ProcessEdgesWorkType = ImmixProcessEdges<VM, KIND>;
181+
}

0 commit comments

Comments
 (0)