Skip to content

Commit 092b756

Browse files
authored
Fix issues in sanity GC (#1079)
This PR fixes two issues in sanity GC. * It fixes #1078 by removing the code to prepare/release mutator/collector, which seems unnecessary. * It replaces the use of `ScanObjects` for cached root nodes with `ProcessRootNode`. Otherwise, the assertion `assert!(!self.roots())` will fail in `ScanObjectsWork::do_work_common`.
1 parent 42754a5 commit 092b756

File tree

5 files changed

+33
-82
lines changed

5 files changed

+33
-82
lines changed

.github/workflows/merge-check.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,9 @@ jobs:
2525
checkInterval: 600
2626
env:
2727
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
28+
- name: Check result
29+
if: ${{ steps.waitforstatuschecks.outputs.status != 'success' }}
30+
uses: actions/github-script@v3
31+
with:
32+
script: |
33+
core.setFailed('Status checks failed')

docs/userguide/src/tutorial/code/mygc_semispace/gc_work.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ impl<VM: VMBinding> ProcessEdgesWork for MyGCProcessEdges<VM> {
7878
}
7979
}
8080

81-
fn create_scan_work(&self, nodes: Vec<ObjectReference>, roots: bool) -> ScanObjects<Self> {
82-
ScanObjects::<Self>::new(nodes, false, roots, self.bucket)
81+
fn create_scan_work(&self, nodes: Vec<ObjectReference>) -> ScanObjects<Self> {
82+
ScanObjects::<Self>::new(nodes, false, self.bucket)
8383
}
8484
}
8585
// ANCHOR_END: mygc_process_edges_impl

src/plan/generational/gc_work.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,8 @@ impl<VM: VMBinding, P: GenerationalPlanExt<VM> + PlanTraceObject<VM>> ProcessEdg
5757
}
5858
}
5959

60-
fn create_scan_work(
61-
&self,
62-
nodes: Vec<ObjectReference>,
63-
roots: bool,
64-
) -> Self::ScanObjectsWorkType {
65-
PlanScanObjects::new(self.plan, nodes, false, roots, self.bucket)
60+
fn create_scan_work(&self, nodes: Vec<ObjectReference>) -> Self::ScanObjectsWorkType {
61+
PlanScanObjects::new(self.plan, nodes, false, self.bucket)
6662
}
6763
}
6864

@@ -122,7 +118,7 @@ impl<E: ProcessEdgesWork> GCWork<E::VM> for ProcessModBuf<E> {
122118
// Scan objects in the modbuf and forward pointers
123119
let modbuf = std::mem::take(&mut self.modbuf);
124120
GCWork::do_work(
125-
&mut ScanObjects::<E>::new(modbuf, false, false, WorkBucketStage::Closure),
121+
&mut ScanObjects::<E>::new(modbuf, false, WorkBucketStage::Closure),
126122
worker,
127123
mmtk,
128124
)

src/scheduler/gc_work.rs

Lines changed: 17 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ impl<E: ProcessEdgesWork> ProcessEdgesWorkTracer<E> {
297297
fn flush(&mut self) {
298298
let next_nodes = self.process_edges_work.pop_nodes();
299299
assert!(!next_nodes.is_empty());
300-
let work_packet = self.process_edges_work.create_scan_work(next_nodes, false);
300+
let work_packet = self.process_edges_work.create_scan_work(next_nodes);
301301
let worker = self.process_edges_work.worker();
302302
worker.scheduler().work_buckets[self.stage].add(work_packet);
303303
}
@@ -641,18 +641,14 @@ pub trait ProcessEdgesWork:
641641
///
642642
/// `roots` indicates if we are creating a packet for root scanning. It is only true when this
643643
/// method is called to handle `RootsWorkFactory::create_process_pinning_roots_work`.
644-
fn create_scan_work(
645-
&self,
646-
nodes: Vec<ObjectReference>,
647-
roots: bool,
648-
) -> Self::ScanObjectsWorkType;
644+
fn create_scan_work(&self, nodes: Vec<ObjectReference>) -> Self::ScanObjectsWorkType;
649645

650646
/// Flush the nodes in ProcessEdgesBase, and create a ScanObjects work packet for it. If the node set is empty,
651647
/// this method will simply return with no work packet created.
652648
fn flush(&mut self) {
653649
let nodes = self.pop_nodes();
654650
if !nodes.is_empty() {
655-
self.start_or_dispatch_scan_work(self.create_scan_work(nodes, false));
651+
self.start_or_dispatch_scan_work(self.create_scan_work(nodes));
656652
}
657653
}
658654

@@ -732,8 +728,8 @@ impl<VM: VMBinding> ProcessEdgesWork for SFTProcessEdges<VM> {
732728
sft.sft_trace_object(&mut self.base.nodes, object, worker)
733729
}
734730

735-
fn create_scan_work(&self, nodes: Vec<ObjectReference>, roots: bool) -> ScanObjects<Self> {
736-
ScanObjects::<Self>::new(nodes, false, roots, self.bucket)
731+
fn create_scan_work(&self, nodes: Vec<ObjectReference>) -> ScanObjects<Self> {
732+
ScanObjects::<Self>::new(nodes, false, self.bucket)
737733
}
738734
}
739735
pub(crate) struct ProcessEdgesWorkRootsWorkFactory<
@@ -815,10 +811,6 @@ pub trait ScanObjectsWork<VM: VMBinding>: GCWork<VM> + Sized {
815811
/// The associated ProcessEdgesWork for processing the edges of the objects in this packet.
816812
type E: ProcessEdgesWork<VM = VM>;
817813

818-
/// Return true if the objects in this packet are pointed by roots, in which case we need to
819-
/// call trace_object on them.
820-
fn roots(&self) -> bool;
821-
822814
/// Called after each object is scanned.
823815
fn post_scan_object(&self, object: ObjectReference);
824816

@@ -836,7 +828,6 @@ pub trait ScanObjectsWork<VM: VMBinding>: GCWork<VM> + Sized {
836828
_mmtk: &'static MMTK<<Self::E as ProcessEdgesWork>::VM>,
837829
) {
838830
let tls = worker.tls;
839-
debug_assert!(!self.roots());
840831

841832
// Scan the nodes in the buffer.
842833
let objects_to_scan = buffer;
@@ -904,22 +895,15 @@ pub struct ScanObjects<Edges: ProcessEdgesWork> {
904895
buffer: Vec<ObjectReference>,
905896
#[allow(unused)]
906897
concurrent: bool,
907-
roots: bool,
908898
phantom: PhantomData<Edges>,
909899
bucket: WorkBucketStage,
910900
}
911901

912902
impl<Edges: ProcessEdgesWork> ScanObjects<Edges> {
913-
pub fn new(
914-
buffer: Vec<ObjectReference>,
915-
concurrent: bool,
916-
roots: bool,
917-
bucket: WorkBucketStage,
918-
) -> Self {
903+
pub fn new(buffer: Vec<ObjectReference>, concurrent: bool, bucket: WorkBucketStage) -> Self {
919904
Self {
920905
buffer,
921906
concurrent,
922-
roots,
923907
phantom: PhantomData,
924908
bucket,
925909
}
@@ -929,10 +913,6 @@ impl<Edges: ProcessEdgesWork> ScanObjects<Edges> {
929913
impl<VM: VMBinding, E: ProcessEdgesWork<VM = VM>> ScanObjectsWork<VM> for ScanObjects<E> {
930914
type E = E;
931915

932-
fn roots(&self) -> bool {
933-
self.roots
934-
}
935-
936916
fn get_bucket(&self) -> WorkBucketStage {
937917
self.bucket
938918
}
@@ -942,7 +922,7 @@ impl<VM: VMBinding, E: ProcessEdgesWork<VM = VM>> ScanObjectsWork<VM> for ScanOb
942922
}
943923

944924
fn make_another(&self, buffer: Vec<ObjectReference>) -> Self {
945-
Self::new(buffer, self.concurrent, false, self.bucket)
925+
Self::new(buffer, self.concurrent, self.bucket)
946926
}
947927
}
948928

@@ -987,12 +967,8 @@ impl<VM: VMBinding, P: PlanTraceObject<VM> + Plan<VM = VM>, const KIND: TraceKin
987967
Self { plan, base }
988968
}
989969

990-
fn create_scan_work(
991-
&self,
992-
nodes: Vec<ObjectReference>,
993-
roots: bool,
994-
) -> Self::ScanObjectsWorkType {
995-
PlanScanObjects::<Self, P>::new(self.plan, nodes, false, roots, self.bucket)
970+
fn create_scan_work(&self, nodes: Vec<ObjectReference>) -> Self::ScanObjectsWorkType {
971+
PlanScanObjects::<Self, P>::new(self.plan, nodes, false, self.bucket)
996972
}
997973

998974
fn trace_object(&mut self, object: ObjectReference) -> ObjectReference {
@@ -1041,7 +1017,6 @@ pub struct PlanScanObjects<E: ProcessEdgesWork, P: Plan<VM = E::VM> + PlanTraceO
10411017
buffer: Vec<ObjectReference>,
10421018
#[allow(dead_code)]
10431019
concurrent: bool,
1044-
roots: bool,
10451020
phantom: PhantomData<E>,
10461021
bucket: WorkBucketStage,
10471022
}
@@ -1051,14 +1026,12 @@ impl<E: ProcessEdgesWork, P: Plan<VM = E::VM> + PlanTraceObject<E::VM>> PlanScan
10511026
plan: &'static P,
10521027
buffer: Vec<ObjectReference>,
10531028
concurrent: bool,
1054-
roots: bool,
10551029
bucket: WorkBucketStage,
10561030
) -> Self {
10571031
Self {
10581032
plan,
10591033
buffer,
10601034
concurrent,
1061-
roots,
10621035
phantom: PhantomData,
10631036
bucket,
10641037
}
@@ -1070,10 +1043,6 @@ impl<E: ProcessEdgesWork, P: Plan<VM = E::VM> + PlanTraceObject<E::VM>> ScanObje
10701043
{
10711044
type E = E;
10721045

1073-
fn roots(&self) -> bool {
1074-
self.roots
1075-
}
1076-
10771046
fn get_bucket(&self) -> WorkBucketStage {
10781047
self.bucket
10791048
}
@@ -1083,7 +1052,7 @@ impl<E: ProcessEdgesWork, P: Plan<VM = E::VM> + PlanTraceObject<E::VM>> ScanObje
10831052
}
10841053

10851054
fn make_another(&self, buffer: Vec<ObjectReference>) -> Self {
1086-
Self::new(self.plan, buffer, self.concurrent, false, self.bucket)
1055+
Self::new(self.plan, buffer, self.concurrent, self.bucket)
10871056
}
10881057
}
10891058

@@ -1101,7 +1070,11 @@ impl<E: ProcessEdgesWork, P: Plan<VM = E::VM> + PlanTraceObject<E::VM>> GCWork<E
11011070
/// but creates the work to scan these objects using E. This is necessary to guarantee that these objects do not move
11021071
/// (`I` should trace them without moving) as we do not have the information about the edges pointing to them.
11031072
1104-
struct ProcessRootNode<VM: VMBinding, I: ProcessEdgesWork<VM = VM>, E: ProcessEdgesWork<VM = VM>> {
1073+
pub(crate) struct ProcessRootNode<
1074+
VM: VMBinding,
1075+
I: ProcessEdgesWork<VM = VM>,
1076+
E: ProcessEdgesWork<VM = VM>,
1077+
> {
11051078
phantom: PhantomData<(VM, I, E)>,
11061079
roots: Vec<ObjectReference>,
11071080
bucket: WorkBucketStage,
@@ -1165,7 +1138,7 @@ impl<VM: VMBinding, I: ProcessEdgesWork<VM = VM>, E: ProcessEdgesWork<VM = VM>>
11651138
};
11661139

11671140
let process_edges_work = E::new(vec![], false, mmtk, self.bucket);
1168-
let work = process_edges_work.create_scan_work(scanned_root_objects, false);
1141+
let work = process_edges_work.create_scan_work(scanned_root_objects);
11691142
crate::memory_manager::add_work_packet(mmtk, self.bucket, work);
11701143

11711144
trace!("ProcessRootNode End");
@@ -1210,11 +1183,7 @@ impl<VM: VMBinding> ProcessEdgesWork for UnsupportedProcessEdges<VM> {
12101183
panic!("unsupported!")
12111184
}
12121185

1213-
fn create_scan_work(
1214-
&self,
1215-
_nodes: Vec<ObjectReference>,
1216-
_roots: bool,
1217-
) -> Self::ScanObjectsWorkType {
1186+
fn create_scan_work(&self, _nodes: Vec<ObjectReference>) -> Self::ScanObjectsWorkType {
12181187
panic!("unsupported!")
12191188
}
12201189
}

src/util/sanity/sanity_checker.rs

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,12 @@ impl<P: Plan> GCWork<P::VM> for ScheduleSanityGC<P> {
9696
);
9797
}
9898
for roots in &sanity_checker.root_nodes {
99-
scheduler.work_buckets[WorkBucketStage::Closure].add(ScanObjects::<
99+
scheduler.work_buckets[WorkBucketStage::Closure].add(ProcessRootNode::<
100+
P::VM,
101+
SanityGCProcessEdges<P::VM>,
100102
SanityGCProcessEdges<P::VM>,
101103
>::new(
102104
roots.clone(),
103-
false,
104-
true,
105105
WorkBucketStage::Closure,
106106
));
107107
}
@@ -132,14 +132,6 @@ impl<P: Plan> GCWork<P::VM> for SanityPrepare<P> {
132132
let mut sanity_checker = mmtk.sanity_checker.lock().unwrap();
133133
sanity_checker.refs.clear();
134134
}
135-
for mutator in <P::VM as VMBinding>::VMActivePlan::mutators() {
136-
mmtk.scheduler.work_buckets[WorkBucketStage::Prepare]
137-
.add(PrepareMutator::<P::VM>::new(mutator));
138-
}
139-
for w in &mmtk.scheduler.worker_group.workers_shared {
140-
let result = w.designated_work.push(Box::new(PrepareCollector));
141-
debug_assert!(result.is_ok());
142-
}
143135
}
144136
}
145137

@@ -157,14 +149,6 @@ impl<P: Plan> GCWork<P::VM> for SanityRelease<P> {
157149
fn do_work(&mut self, _worker: &mut GCWorker<P::VM>, mmtk: &'static MMTK<P::VM>) {
158150
info!("Sanity GC release");
159151
mmtk.sanity_checker.lock().unwrap().clear_roots_cache();
160-
for mutator in <P::VM as VMBinding>::VMActivePlan::mutators() {
161-
mmtk.scheduler.work_buckets[WorkBucketStage::Release]
162-
.add(ReleaseMutator::<P::VM>::new(mutator));
163-
}
164-
for w in &mmtk.scheduler.worker_group.workers_shared {
165-
let result = w.designated_work.push(Box::new(ReleaseCollector));
166-
debug_assert!(result.is_ok());
167-
}
168152
mmtk.sanity_end();
169153
}
170154
}
@@ -243,11 +227,7 @@ impl<VM: VMBinding> ProcessEdgesWork for SanityGCProcessEdges<VM> {
243227
object
244228
}
245229

246-
fn create_scan_work(
247-
&self,
248-
nodes: Vec<ObjectReference>,
249-
roots: bool,
250-
) -> Self::ScanObjectsWorkType {
251-
ScanObjects::<Self>::new(nodes, false, roots, WorkBucketStage::Closure)
230+
fn create_scan_work(&self, nodes: Vec<ObjectReference>) -> Self::ScanObjectsWorkType {
231+
ScanObjects::<Self>::new(nodes, false, WorkBucketStage::Closure)
252232
}
253233
}

0 commit comments

Comments
 (0)