Skip to content

Commit

Permalink
Extract common work packet to schedule_common() (#471)
Browse files Browse the repository at this point in the history
  • Loading branch information
qinsoon authored Oct 28, 2021
1 parent a08d13d commit bf54dd3
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 198 deletions.
42 changes: 7 additions & 35 deletions src/plan/generational/copying/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use crate::plan::Plan;
use crate::plan::PlanConstraints;
use crate::policy::copyspace::CopySpace;
use crate::policy::space::Space;
use crate::scheduler::gc_work::*;
use crate::scheduler::*;
use crate::util::alloc::allocators::AllocatorSelector;
use crate::util::heap::layout::heap_layout::Mmapper;
Expand All @@ -21,8 +20,6 @@ use crate::util::heap::HeapMeta;
use crate::util::heap::VMRequest;
use crate::util::metadata::side_metadata::SideMetadataSanity;
use crate::util::options::UnsafeOptionsWrapper;
#[cfg(feature = "sanity")]
use crate::util::sanity::sanity_checker::*;
use crate::util::VMWorkerThread;
use crate::vm::*;
use enum_map::EnumMap;
Expand Down Expand Up @@ -85,50 +82,25 @@ impl<VM: VMBinding> Plan for GenCopy<VM> {

fn schedule_collection(&'static self, scheduler: &GCWorkScheduler<VM>) {
let is_full_heap = self.request_full_heap_collection();

// TODO: We should have a schedule_generational

self.base().set_collection_kind::<Self>(self);
self.base().set_gc_status(GcStatus::GcPrepare);
if !is_full_heap {
debug!("Nursery GC");
self.common()
.schedule_common::<GenNurseryProcessEdges<VM, GenCopyCopyContext<VM>>>(
.schedule_common::<Self, GenNurseryProcessEdges<VM, GenCopyCopyContext<VM>>, GenCopyCopyContext<VM>>(
self,
&GENCOPY_CONSTRAINTS,
scheduler,
);
// Stop & scan mutators (mutator scanning can happen before STW)
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(StopMutators::<
GenNurseryProcessEdges<VM, GenCopyCopyContext<VM>>,
>::new());
} else {
debug!("Full heap GC");
self.common()
.schedule_common::<GenCopyMatureProcessEdges<VM>>(&GENCOPY_CONSTRAINTS, scheduler);
// Stop & scan mutators (mutator scanning can happen before STW)
scheduler.work_buckets[WorkBucketStage::Unconstrained]
.add(StopMutators::<GenCopyMatureProcessEdges<VM>>::new());
}

// Prepare global/collectors/mutators
scheduler.work_buckets[WorkBucketStage::Prepare]
.add(Prepare::<Self, GenCopyCopyContext<VM>>::new(self));
if is_full_heap {
scheduler.work_buckets[WorkBucketStage::RefClosure]
.add(ProcessWeakRefs::<GenCopyMatureProcessEdges<VM>>::new());
} else {
scheduler.work_buckets[WorkBucketStage::RefClosure].add(ProcessWeakRefs::<
GenNurseryProcessEdges<VM, GenCopyCopyContext<VM>>,
>::new());
.schedule_common::<Self, GenCopyMatureProcessEdges<VM>, GenCopyCopyContext<VM>>(
self,
&GENCOPY_CONSTRAINTS,
scheduler,
);
}
// Release global/collectors/mutators
scheduler.work_buckets[WorkBucketStage::Release]
.add(Release::<Self, GenCopyCopyContext<VM>>::new(self));
// Resume mutators
#[cfg(feature = "sanity")]
scheduler.work_buckets[WorkBucketStage::Final]
.add(ScheduleSanityGC::<Self, GenCopyCopyContext<VM>>::new(self));
scheduler.set_finalizer(Some(EndOfGC));
}

fn get_allocator_mapping(&self) -> &'static EnumMap<AllocationSemantics, AllocatorSelector> {
Expand Down
52 changes: 6 additions & 46 deletions src/plan/generational/immix/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use crate::plan::Plan;
use crate::plan::PlanConstraints;
use crate::policy::immix::ImmixSpace;
use crate::policy::space::Space;
use crate::scheduler::gc_work::*;
use crate::scheduler::GCWorkScheduler;
use crate::scheduler::GCWorkerLocalPtr;
use crate::scheduler::*;
Expand Down Expand Up @@ -129,67 +128,28 @@ impl<VM: VMBinding> Plan for GenImmix<VM> {
if !is_full_heap {
debug!("Nursery GC");
self.common()
.schedule_common::<GenNurseryProcessEdges<VM, GenImmixCopyContext<VM>>>(
.schedule_common::<Self, GenNurseryProcessEdges<VM, GenImmixCopyContext<VM>>, GenImmixCopyContext<VM>>(
self,
&GENIMMIX_CONSTRAINTS,
scheduler,
);
// Stop & scan mutators (mutator scanning can happen before STW)
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(StopMutators::<
GenNurseryProcessEdges<VM, GenImmixCopyContext<VM>>,
>::new());
} else if defrag {
debug!("Full heap GC Defrag");
self.common()
.schedule_common::<GenImmixMatureProcessEdges<VM, { TraceKind::Defrag }>>(
.schedule_common::<Self, GenImmixMatureProcessEdges<VM, { TraceKind::Defrag }>, GenImmixCopyContext<VM>>(
self,
&GENIMMIX_CONSTRAINTS,
scheduler,
);
// Stop & scan mutators (mutator scanning can happen before STW)
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(StopMutators::<
GenImmixMatureProcessEdges<VM, { TraceKind::Defrag }>,
>::new());
} else {
debug!("Full heap GC Fast");
self.common()
.schedule_common::<GenImmixMatureProcessEdges<VM, { TraceKind::Fast }>>(
.schedule_common::<Self, GenImmixMatureProcessEdges<VM, { TraceKind::Fast }>, GenImmixCopyContext<VM>>(
self,
&GENIMMIX_CONSTRAINTS,
scheduler,
);
// Stop & scan mutators (mutator scanning can happen before STW)
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(StopMutators::<
GenImmixMatureProcessEdges<VM, { TraceKind::Fast }>,
>::new());
}

// Prepare global/collectors/mutators
scheduler.work_buckets[WorkBucketStage::Prepare]
.add(Prepare::<Self, GenImmixCopyContext<VM>>::new(self));
if is_full_heap {
if defrag {
scheduler.work_buckets[WorkBucketStage::RefClosure].add(ProcessWeakRefs::<
GenImmixMatureProcessEdges<VM, { TraceKind::Defrag }>,
>::new());
} else {
scheduler.work_buckets[WorkBucketStage::RefClosure].add(ProcessWeakRefs::<
GenImmixMatureProcessEdges<VM, { TraceKind::Fast }>,
>::new());
}
} else {
scheduler.work_buckets[WorkBucketStage::RefClosure].add(ProcessWeakRefs::<
GenNurseryProcessEdges<VM, GenImmixCopyContext<VM>>,
>::new());
}
// Release global/collectors/mutators
scheduler.work_buckets[WorkBucketStage::Release]
.add(Release::<Self, GenImmixCopyContext<VM>>::new(self));
// Resume mutators
#[cfg(feature = "sanity")]
{
use crate::util::sanity::sanity_checker::*;
scheduler.work_buckets[WorkBucketStage::Final]
.add(ScheduleSanityGC::<Self, GenImmixCopyContext<VM>>::new(self));
}
scheduler.set_finalizer(Some(EndOfGC));
}

fn get_allocator_mapping(&self) -> &'static EnumMap<AllocationSemantics, AllocatorSelector> {
Expand Down
41 changes: 39 additions & 2 deletions src/plan/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -919,12 +919,46 @@ impl<VM: VMBinding> CommonPlan<VM> {
self.base.release(tls, full_heap)
}

pub fn schedule_common<E: ProcessEdgesWork<VM = VM>>(
/// Schedule all the common work packets
pub fn schedule_common<
P: Plan<VM = VM>,
E: ProcessEdgesWork<VM = VM>,
C: CopyContext<VM = VM> + GCWorkerLocal,
>(
&self,
plan: &'static P,
constraints: &'static PlanConstraints,
scheduler: &GCWorkScheduler<VM>,
) {
// Schedule finalization
use crate::scheduler::gc_work::*;

// Stop & scan mutators (mutator scanning can happen before STW)
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(StopMutators::<E>::new());

// Prepare global/collectors/mutators
scheduler.work_buckets[WorkBucketStage::Prepare].add(Prepare::<P, C>::new(plan));

// VM-specific weak ref processing
scheduler.work_buckets[WorkBucketStage::RefClosure].add(ProcessWeakRefs::<E>::new());

// Release global/collectors/mutators
scheduler.work_buckets[WorkBucketStage::Release].add(Release::<P, C>::new(plan));

// Analysis GC work
#[cfg(feature = "analysis")]
{
use crate::util::analysis::GcHookWork;
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(GcHookWork);
}

// Sanity
#[cfg(feature = "sanity")]
{
use crate::util::sanity::sanity_checker::ScheduleSanityGC;
scheduler.work_buckets[WorkBucketStage::Final].add(ScheduleSanityGC::<P, C>::new(plan));
}

// Finalization
if !self.base.options.no_finalizer {
use crate::util::finalizable_processor::{Finalization, ForwardFinalization};
// finalization
Expand All @@ -935,6 +969,9 @@ impl<VM: VMBinding> CommonPlan<VM> {
.add(ForwardFinalization::<E>::new());
}
}

// Set EndOfGC to run at the end
scheduler.set_finalizer(Some(EndOfGC));
}

pub fn stacks_prepared(&self) -> bool {
Expand Down
44 changes: 5 additions & 39 deletions src/plan/immix/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,15 @@ use crate::plan::AllocationSemantics;
use crate::plan::Plan;
use crate::plan::PlanConstraints;
use crate::policy::space::Space;
use crate::scheduler::gc_work::*;
use crate::scheduler::*;
use crate::util::alloc::allocators::AllocatorSelector;
#[cfg(feature = "analysis")]
use crate::util::analysis::GcHookWork;
use crate::util::heap::layout::heap_layout::Mmapper;
use crate::util::heap::layout::heap_layout::VMMap;
use crate::util::heap::layout::vm_layout_constants::{HEAP_END, HEAP_START};
use crate::util::heap::HeapMeta;
use crate::util::metadata::side_metadata::SideMetadataContext;
use crate::util::metadata::side_metadata::SideMetadataSanity;
use crate::util::options::UnsafeOptionsWrapper;
#[cfg(feature = "sanity")]
use crate::util::sanity::sanity_checker::*;
use crate::vm::VMBinding;
use crate::{mmtk::MMTK, policy::immix::ImmixSpace, util::opaque_pointer::VMWorkerThread};
use std::sync::atomic::AtomicBool;
Expand Down Expand Up @@ -92,45 +87,16 @@ impl<VM: VMBinding> Plan for Immix<VM> {
self.base().is_user_triggered_collection(),
self.base().options.full_heap_system_gc,
);
// Stop & scan mutators (mutator scanning can happen before STW)
// The blocks are not identical, clippy is wrong. Probably it does not recognize the constant type parameter.
#[allow(clippy::if_same_then_else)]
// The two StopMutators have different types parameters, thus we cannot extract the common code before add().
#[allow(clippy::branches_sharing_code)]
if in_defrag {
scheduler.work_buckets[WorkBucketStage::Unconstrained]
.add(StopMutators::<ImmixProcessEdges<VM, { TraceKind::Defrag }>>::new());
} else {
scheduler.work_buckets[WorkBucketStage::Unconstrained]
.add(StopMutators::<ImmixProcessEdges<VM, { TraceKind::Fast }>>::new());
}
// Prepare global/collectors/mutators
scheduler.work_buckets[WorkBucketStage::Prepare]
.add(Prepare::<Self, ImmixCopyContext<VM>>::new(self));

// The blocks are not identical, clippy is wrong. Probably it does not recognize the constant type parameter.
#[allow(clippy::if_same_then_else)]
// The two StopMutators have different types parameters, thus we cannot extract the common code before add().
#[allow(clippy::branches_sharing_code)]
if in_defrag {
scheduler.work_buckets[WorkBucketStage::RefClosure].add(ProcessWeakRefs::<
ImmixProcessEdges<VM, { TraceKind::Defrag }>,
>::new());
self.common()
.schedule_common::<Self, ImmixProcessEdges<VM, { TraceKind::Defrag }>, ImmixCopyContext<VM>>(self, &IMMIX_CONSTRAINTS, scheduler);
} else {
scheduler.work_buckets[WorkBucketStage::RefClosure]
.add(ProcessWeakRefs::<ImmixProcessEdges<VM, { TraceKind::Fast }>>::new());
self.common()
.schedule_common::<Self, ImmixProcessEdges<VM, { TraceKind::Fast }>, ImmixCopyContext<VM>>(self, &IMMIX_CONSTRAINTS, scheduler);
}
// Release global/collectors/mutators
scheduler.work_buckets[WorkBucketStage::Release]
.add(Release::<Self, ImmixCopyContext<VM>>::new(self));
// Analysis routine that is ran. It is generally recommended to take advantage
// of the scheduling system we have in place for more performance
#[cfg(feature = "analysis")]
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(GcHookWork);
// Resume mutators
#[cfg(feature = "sanity")]
scheduler.work_buckets[WorkBucketStage::Final]
.add(ScheduleSanityGC::<Self, ImmixCopyContext<VM>>::new(self));
scheduler.set_finalizer(Some(EndOfGC));
}

fn get_allocator_mapping(&self) -> &'static EnumMap<AllocationSemantics, AllocatorSelector> {
Expand Down
29 changes: 5 additions & 24 deletions src/plan/marksweep/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,16 @@ use crate::plan::PlanConstraints;
use crate::policy::mallocspace::metadata::ACTIVE_CHUNK_METADATA_SPEC;
use crate::policy::mallocspace::MallocSpace;
use crate::policy::space::Space;
use crate::scheduler::gc_work::*;
use crate::scheduler::*;
use crate::util::alloc::allocators::AllocatorSelector;
#[cfg(not(feature = "global_alloc_bit"))]
use crate::util::alloc_bit::ALLOC_SIDE_METADATA_SPEC;
#[cfg(feature = "analysis")]
use crate::util::analysis::GcHookWork;
use crate::util::heap::layout::heap_layout::Mmapper;
use crate::util::heap::layout::heap_layout::VMMap;
use crate::util::heap::layout::vm_layout_constants::{HEAP_END, HEAP_START};
use crate::util::heap::HeapMeta;
use crate::util::metadata::side_metadata::{SideMetadataContext, SideMetadataSanity};
use crate::util::options::UnsafeOptionsWrapper;
#[cfg(feature = "sanity")]
use crate::util::sanity::sanity_checker::*;
use crate::util::VMWorkerThread;
use crate::vm::VMBinding;
use std::sync::Arc;
Expand Down Expand Up @@ -62,26 +57,12 @@ impl<VM: VMBinding> Plan for MarkSweep<VM> {
self.base().set_collection_kind::<Self>(self);
self.base().set_gc_status(GcStatus::GcPrepare);
self.common()
.schedule_common::<MSProcessEdges<VM>>(&MS_CONSTRAINTS, scheduler);
// Stop & scan mutators (mutator scanning can happen before STW)
scheduler.work_buckets[WorkBucketStage::Unconstrained]
.add(StopMutators::<MSProcessEdges<VM>>::new());
// Prepare global/collectors/mutators
scheduler.work_buckets[WorkBucketStage::Prepare]
.add(Prepare::<Self, NoCopy<VM>>::new(self));
.schedule_common::<Self, MSProcessEdges<VM>, NoCopy<VM>>(
self,
&MS_CONSTRAINTS,
scheduler,
);
scheduler.work_buckets[WorkBucketStage::Prepare].add(MSSweepChunks::<VM>::new(self));
scheduler.work_buckets[WorkBucketStage::RefClosure]
.add(ProcessWeakRefs::<MSProcessEdges<VM>>::new());
// Release global/collectors/mutators
scheduler.work_buckets[WorkBucketStage::Release]
.add(Release::<Self, NoCopy<VM>>::new(self));
#[cfg(feature = "analysis")]
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(GcHookWork);
// Resume mutators
#[cfg(feature = "sanity")]
scheduler.work_buckets[WorkBucketStage::Final]
.add(ScheduleSanityGC::<Self, NoCopy<VM>>::new(self));
scheduler.set_finalizer(Some(EndOfGC));
}

fn get_allocator_mapping(&self) -> &'static EnumMap<AllocationSemantics, AllocatorSelector> {
Expand Down
27 changes: 1 addition & 26 deletions src/plan/pageprotect/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,15 @@ use crate::plan::AllocationSemantics;
use crate::plan::Plan;
use crate::plan::PlanConstraints;
use crate::policy::space::Space;
use crate::scheduler::gc_work::*;
use crate::scheduler::*;
use crate::util::alloc::allocators::AllocatorSelector;
#[cfg(feature = "analysis")]
use crate::util::analysis::GcHookWork;
use crate::util::heap::layout::heap_layout::Mmapper;
use crate::util::heap::layout::heap_layout::VMMap;
use crate::util::heap::layout::vm_layout_constants::{HEAP_END, HEAP_START};
use crate::util::heap::HeapMeta;
use crate::util::heap::VMRequest;
use crate::util::metadata::side_metadata::SideMetadataContext;
use crate::util::options::UnsafeOptionsWrapper;
#[cfg(feature = "sanity")]
use crate::util::sanity::sanity_checker::*;
use crate::{plan::global::BasePlan, vm::VMBinding};
use crate::{
plan::global::{CommonPlan, NoCopy},
Expand Down Expand Up @@ -81,27 +76,7 @@ impl<VM: VMBinding> Plan for PageProtect<VM> {
self.base().set_collection_kind::<Self>(self);
self.base().set_gc_status(GcStatus::GcPrepare);
self.common()
.schedule_common::<PPProcessEdges<VM>>(&CONSTRAINTS, scheduler);
// Stop & scan mutators (mutator scanning can happen before STW)
scheduler.work_buckets[WorkBucketStage::Unconstrained]
.add(StopMutators::<PPProcessEdges<VM>>::new());
// Prepare global/collectors/mutators
scheduler.work_buckets[WorkBucketStage::Prepare]
.add(Prepare::<Self, NoCopy<VM>>::new(self));
scheduler.work_buckets[WorkBucketStage::RefClosure]
.add(ProcessWeakRefs::<PPProcessEdges<VM>>::new());
// Release global/collectors/mutators
scheduler.work_buckets[WorkBucketStage::Release]
.add(Release::<Self, NoCopy<VM>>::new(self));
// Scheduling all the gc hooks of analysis routines. It is generally recommended
// to take advantage of the scheduling system we have in place for more performance
#[cfg(feature = "analysis")]
scheduler.work_buckets[WorkBucketStage::Unconstrained].add(GcHookWork);
// Resume mutators
#[cfg(feature = "sanity")]
scheduler.work_buckets[WorkBucketStage::Final]
.add(ScheduleSanityGC::<Self, NoCopy<VM>>::new(self));
scheduler.set_finalizer(Some(EndOfGC));
.schedule_common::<Self, PPProcessEdges<VM>, NoCopy<VM>>(self, &CONSTRAINTS, scheduler);
}

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

0 comments on commit bf54dd3

Please sign in to comment.