Skip to content

Commit 099ddbe

Browse files
qinsoonwenyuzhao
authored andcommitted
Tidy up mutator scan API (mmtk#875)
This PR closes mmtk#496. * Remove Scanning::SCAN_MUTATORS_IN_SAFEPOINT, and Scanning::SINGLE_THREAD_MUTATOR_SCANNING. * Remove Scanning::scan_roots_in_all_mutator_threads. * Remove Collection::prepare_mutator * Update comments for a few methods
1 parent cacb8f6 commit 099ddbe

File tree

8 files changed

+22
-107
lines changed

8 files changed

+22
-107
lines changed

src/plan/markcompact/gc_work.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,9 @@ impl<VM: VMBinding> GCWork<VM> for UpdateReferences<VM> {
4949
.worker_group
5050
.get_and_clear_worker_live_bytes();
5151

52-
// TODO investigate why the following will create duplicate edges
53-
// scheduler.work_buckets[WorkBucketStage::RefForwarding]
54-
// .add(ScanStackRoots::<ForwardingProcessEdges<VM>>::new());
5552
for mutator in VM::VMActivePlan::mutators() {
5653
mmtk.scheduler.work_buckets[WorkBucketStage::SecondRoots]
57-
.add(ScanStackRoot::<ForwardingProcessEdges<VM>>(mutator));
54+
.add(ScanMutatorRoots::<ForwardingProcessEdges<VM>>(mutator));
5855
}
5956

6057
mmtk.scheduler.work_buckets[WorkBucketStage::SecondRoots]

src/scheduler/gc_work.rs

Lines changed: 7 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,6 @@ impl<VM: VMBinding> GCWork<VM> for ReleaseCollector {
177177

178178
/// Stop all mutators
179179
///
180-
/// Schedule a `ScanStackRoots` immediately after a mutator is paused
181-
///
182180
/// TODO: Smaller work granularity
183181
#[derive(Default)]
184182
pub struct StopMutators<ScanEdges: ProcessEdgesWork>(PhantomData<ScanEdges>);
@@ -194,33 +192,13 @@ impl<E: ProcessEdgesWork> GCWork<E::VM> for StopMutators<E> {
194192
trace!("stop_all_mutators start");
195193
mmtk.plan.base().prepare_for_stack_scanning();
196194
<E::VM as VMBinding>::VMCollection::stop_all_mutators(worker.tls, |mutator| {
197-
mmtk.scheduler.work_buckets[WorkBucketStage::Prepare].add(ScanStackRoot::<E>(mutator));
195+
// TODO: The stack scanning work won't start immediately, as the `Prepare` bucket is not opened yet (the bucket is opened in notify_mutators_paused).
196+
// Should we push to Unconstrained instead?
197+
mmtk.scheduler.work_buckets[WorkBucketStage::Prepare]
198+
.add(ScanMutatorRoots::<E>(mutator));
198199
});
199200
trace!("stop_all_mutators end");
200201
mmtk.scheduler.notify_mutators_paused(mmtk);
201-
if <E::VM as VMBinding>::VMScanning::SCAN_MUTATORS_IN_SAFEPOINT {
202-
// Prepare mutators if necessary
203-
// FIXME: This test is probably redundant. JikesRVM requires to call `prepare_mutator` once after mutators are paused
204-
if !mmtk.plan.base().stacks_prepared() {
205-
for mutator in <E::VM as VMBinding>::VMActivePlan::mutators() {
206-
<E::VM as VMBinding>::VMCollection::prepare_mutator(
207-
worker.tls,
208-
mutator.get_tls(),
209-
mutator,
210-
);
211-
}
212-
}
213-
// Scan mutators
214-
if <E::VM as VMBinding>::VMScanning::SINGLE_THREAD_MUTATOR_SCANNING {
215-
mmtk.scheduler.work_buckets[WorkBucketStage::Prepare]
216-
.add(ScanStackRoots::<E>::new());
217-
} else {
218-
for mutator in <E::VM as VMBinding>::VMActivePlan::mutators() {
219-
mmtk.scheduler.work_buckets[WorkBucketStage::Prepare]
220-
.add(ScanStackRoot::<E>(mutator));
221-
}
222-
}
223-
}
224202
mmtk.scheduler.work_buckets[WorkBucketStage::Prepare].add(ScanVMSpecificRoots::<E>::new());
225203
}
226204
}
@@ -465,33 +443,11 @@ impl<VM: VMBinding> GCWork<VM> for VMPostForwarding<VM> {
465443
}
466444
}
467445

468-
#[derive(Default)]
469-
pub struct ScanStackRoots<Edges: ProcessEdgesWork>(PhantomData<Edges>);
470-
471-
impl<E: ProcessEdgesWork> ScanStackRoots<E> {
472-
pub fn new() -> Self {
473-
Self(PhantomData)
474-
}
475-
}
476-
477-
impl<E: ProcessEdgesWork> GCWork<E::VM> for ScanStackRoots<E> {
478-
fn do_work(&mut self, worker: &mut GCWorker<E::VM>, mmtk: &'static MMTK<E::VM>) {
479-
trace!("ScanStackRoots");
480-
let factory = ProcessEdgesWorkRootsWorkFactory::<E>::new(mmtk);
481-
<E::VM as VMBinding>::VMScanning::scan_roots_in_all_mutator_threads(worker.tls, factory);
482-
<E::VM as VMBinding>::VMScanning::notify_initial_thread_scan_complete(false, worker.tls);
483-
for mutator in <E::VM as VMBinding>::VMActivePlan::mutators() {
484-
mutator.flush();
485-
}
486-
mmtk.plan.common().base.set_gc_status(GcStatus::GcProper);
487-
}
488-
}
489-
490-
pub struct ScanStackRoot<Edges: ProcessEdgesWork>(pub &'static mut Mutator<Edges::VM>);
446+
pub struct ScanMutatorRoots<Edges: ProcessEdgesWork>(pub &'static mut Mutator<Edges::VM>);
491447

492-
impl<E: ProcessEdgesWork> GCWork<E::VM> for ScanStackRoot<E> {
448+
impl<E: ProcessEdgesWork> GCWork<E::VM> for ScanMutatorRoots<E> {
493449
fn do_work(&mut self, worker: &mut GCWorker<E::VM>, mmtk: &'static MMTK<E::VM>) {
494-
trace!("ScanStackRoot for mutator {:?}", self.0.get_tls());
450+
trace!("ScanMutatorRoots for mutator {:?}", self.0.get_tls());
495451
let base = &mmtk.plan.base();
496452
let mutators = <E::VM as VMBinding>::VMActivePlan::number_of_mutators();
497453
let factory = ProcessEdgesWorkRootsWorkFactory::<E>::new(mmtk);

src/scheduler/mod.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,3 @@ pub use controller::GCController;
2525

2626
pub(crate) mod gc_work;
2727
pub use gc_work::ProcessEdgesWork;
28-
// TODO: We shouldn't need to expose ScanStackRoot. However, OpenJDK uses it.
29-
// We should do some refactoring related to Scanning::SCAN_MUTATORS_IN_SAFEPOINT
30-
// to make sure this type is not exposed to the bindings.
31-
pub use gc_work::ScanStackRoot;

src/util/sanity/sanity_checker.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ impl<P: Plan> GCWork<P::VM> for ScheduleSanityGC<P> {
8383
// in openjdk binding before the second round of roots scanning.
8484
// for mutator in <P::VM as VMBinding>::VMActivePlan::mutators() {
8585
// scheduler.work_buckets[WorkBucketStage::Prepare]
86-
// .add(ScanStackRoot::<SanityGCProcessEdges<P::VM>>(mutator));
86+
// .add(ScanMutatorRoots::<SanityGCProcessEdges<P::VM>>(mutator));
8787
// }
8888
{
8989
let sanity_checker = mmtk.sanity_checker.lock().unwrap();

src/vm/collection.rs

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use crate::plan::MutatorContext;
21
use crate::util::alloc::AllocationError;
32
use crate::util::opaque_pointer::*;
43
use crate::vm::VMBinding;
@@ -16,9 +15,12 @@ pub trait Collection<VM: VMBinding> {
1615
/// This method is called by a single thread in MMTk (the GC controller).
1716
/// This method should not return until all the threads are yielded.
1817
/// The actual thread synchronization mechanism is up to the VM, and MMTk does not make assumptions on that.
18+
/// MMTk provides a callback function and expects the binding to use the callback for each mutator when it
19+
/// is ready for stack scanning. Usually a stack can be scanned as soon as the thread stops in the yieldpoint.
1920
///
2021
/// Arguments:
2122
/// * `tls`: The thread pointer for the GC controller/coordinator.
23+
/// * `mutator_visitor`: A callback. Call it with a mutator as argument to notify MMTk that the mutator is ready to be scanned.
2224
fn stop_all_mutators<F>(tls: VMWorkerThread, mutator_visitor: F)
2325
where
2426
F: FnMut(&'static mut Mutator<VM>);
@@ -54,18 +56,6 @@ pub trait Collection<VM: VMBinding> {
5456
/// In either case, the `Box` inside should be passed back to the called function.
5557
fn spawn_gc_thread(tls: VMThread, ctx: GCThreadContext<VM>);
5658

57-
/// Allow VM-specific behaviors for a mutator after all the mutators are stopped and before any actual GC work starts.
58-
///
59-
/// Arguments:
60-
/// * `tls_worker`: The thread pointer for the worker thread performing this call.
61-
/// * `tls_mutator`: The thread pointer for the target mutator thread.
62-
/// * `m`: The mutator context for the thread.
63-
fn prepare_mutator<T: MutatorContext<VM>>(
64-
tls_worker: VMWorkerThread,
65-
tls_mutator: VMMutatorThread,
66-
m: &T,
67-
);
68-
6959
/// Inform the VM of an out-of-memory error. The binding should hook into the VM's error
7060
/// routine for OOM. Note that there are two different categories of OOM:
7161
/// * Critical OOM: This is the case where the OS is unable to mmap or acquire more memory.

src/vm/scanning.rs

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -121,14 +121,6 @@ pub trait RootsWorkFactory<ES: Edge>: Clone + Send + 'static {
121121

122122
/// VM-specific methods for scanning roots/objects.
123123
pub trait Scanning<VM: VMBinding> {
124-
/// Scan stack roots after all mutators are paused.
125-
const SCAN_MUTATORS_IN_SAFEPOINT: bool = true;
126-
127-
/// Scan all the mutators within a single work packet.
128-
///
129-
/// `SCAN_MUTATORS_IN_SAFEPOINT` should also be enabled
130-
const SINGLE_THREAD_MUTATOR_SCANNING: bool = true;
131-
132124
/// Return true if the given object supports edge enqueuing.
133125
///
134126
/// - If this returns true, MMTk core will call `scan_object` on the object.
@@ -203,20 +195,16 @@ pub trait Scanning<VM: VMBinding> {
203195
/// * `tls`: The GC thread that is performing the thread scan.
204196
fn notify_initial_thread_scan_complete(partial_scan: bool, tls: VMWorkerThread);
205197

206-
/// Scan all the mutators for roots.
207-
///
208-
/// The `memory_manager::is_mmtk_object` function can be used in this function if
209-
/// - the "is_mmtk_object" feature is enabled.
210-
///
211-
/// Arguments:
212-
/// * `tls`: The GC thread that is performing this scanning.
213-
/// * `factory`: The VM uses it to create work packets for scanning roots.
214-
fn scan_roots_in_all_mutator_threads(
215-
tls: VMWorkerThread,
216-
factory: impl RootsWorkFactory<VM::VMEdge>,
217-
);
218-
219-
/// Scan one mutator for roots.
198+
/// Scan one mutator for stack roots.
199+
///
200+
/// Some VM bindings may not be able to implement this method.
201+
/// For example, the VM binding may only be able to enumerate all threads and
202+
/// scan them while enumerating, but cannot scan stacks individually when given
203+
/// the references of threads.
204+
/// In that case, it can leave this method empty, and deal with stack
205+
/// roots in [`Collection::scan_vm_specific_roots`]. However, in that case, MMTk
206+
/// does not know those roots are stack roots, and cannot perform any possible
207+
/// optimization for the stack roots.
220208
///
221209
/// The `memory_manager::is_mmtk_object` function can be used in this function if
222210
/// - the "is_mmtk_object" feature is enabled.

vmbindings/dummyvm/src/collection.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use mmtk::util::opaque_pointer::*;
33
use mmtk::vm::Collection;
44
use mmtk::vm::GCThreadContext;
55
use mmtk::Mutator;
6-
use mmtk::MutatorContext;
76

87
pub struct VMCollection {}
98

@@ -24,12 +23,4 @@ impl Collection<DummyVM> for VMCollection {
2423
}
2524

2625
fn spawn_gc_thread(_tls: VMThread, _ctx: GCThreadContext<DummyVM>) {}
27-
28-
fn prepare_mutator<T: MutatorContext<DummyVM>>(
29-
_tls_w: VMWorkerThread,
30-
_tls_m: VMMutatorThread,
31-
_mutator: &T,
32-
) {
33-
unimplemented!()
34-
}
3526
}

vmbindings/dummyvm/src/scanning.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ use mmtk::Mutator;
1010
pub struct VMScanning {}
1111

1212
impl Scanning<DummyVM> for VMScanning {
13-
fn scan_roots_in_all_mutator_threads(_tls: VMWorkerThread, _factory: impl RootsWorkFactory<DummyVMEdge>) {
14-
unimplemented!()
15-
}
1613
fn scan_roots_in_mutator_thread(
1714
_tls: VMWorkerThread,
1815
_mutator: &'static mut Mutator<DummyVM>,

0 commit comments

Comments
 (0)