Skip to content

Commit

Permalink
Generational plans set next_gc_full_heap in end_of_gc (#714)
Browse files Browse the repository at this point in the history
This PR adds `Plan.end_of_gc()`. Our generational plans compute whether we should do full heap GC at the end of `Plan.release()` which is incorrect. There could be other parallel release work when we execute `Plan.release()`. This PR adds `Plan.end_of_gc()`, and we compute `next_gc_full_heap` in `end_of_gc()`.
  • Loading branch information
qinsoon committed Jan 2, 2023
1 parent 4bb37f8 commit 06237f1
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 13 deletions.
7 changes: 2 additions & 5 deletions src/plan/generational/copying/global.rs
Expand Up @@ -123,12 +123,9 @@ impl<VM: VMBinding> Plan for GenCopy<VM> {
if full_heap {
self.fromspace().release();
}
}

// TODO: Refactor so that we set the next_gc_full_heap in gen.release(). Currently have to fight with Rust borrow checker
// NOTE: We have to take care that the `Gen::should_next_gc_be_full_heap()` function is
// called _after_ all spaces have been released (including ones in `gen`) as otherwise we
// may get incorrect results since the function uses values such as available pages that
// will change dependant on which spaces have been released
fn end_of_gc(&mut self, _tls: VMWorkerThread) {
self.gen
.set_next_gc_full_heap(Gen::should_next_gc_be_full_heap(self));
}
Expand Down
7 changes: 2 additions & 5 deletions src/plan/generational/immix/global.rs
Expand Up @@ -165,12 +165,9 @@ impl<VM: VMBinding> Plan for GenImmix<VM> {
}
self.last_gc_was_full_heap
.store(full_heap, Ordering::Relaxed);
}

// TODO: Refactor so that we set the next_gc_full_heap in gen.release(). Currently have to fight with Rust borrow checker
// NOTE: We have to take care that the `Gen::should_next_gc_be_full_heap()` function is
// called _after_ all spaces have been released (including ones in `gen`) as otherwise we
// may get incorrect results since the function uses values such as available pages that
// will change dependant on which spaces have been released
fn end_of_gc(&mut self, _tls: VMWorkerThread) {
self.gen
.set_next_gc_full_heap(Gen::should_next_gc_be_full_heap(self));
}
Expand Down
11 changes: 8 additions & 3 deletions src/plan/global.rs
Expand Up @@ -221,17 +221,22 @@ pub trait Plan: 'static + Sync + Downcast {
}

/// Prepare the plan before a GC. This is invoked in an initial step in the GC.
/// This is invoked once per GC by one worker thread. 'tls' is the worker thread that executes this method.
/// This is invoked once per GC by one worker thread. `tls` is the worker thread that executes this method.
fn prepare(&mut self, tls: VMWorkerThread);

/// Prepare a worker for a GC. Each worker has its own prepare method. This hook is for plan-specific
/// per-worker preparation. This method is invoked once per worker by the worker thread passed as the argument.
fn prepare_worker(&self, _worker: &mut GCWorker<Self::VM>) {}

/// Release the plan after a GC. This is invoked at the end of a GC when most GC work is finished.
/// This is invoked once per GC by one worker thread. 'tls' is the worker thread that executes this method.
/// Release the plan after transitive closure. A plan can implement this method to call each policy's release,
/// or create any work packet that should be done in release.
/// This is invoked once per GC by one worker thread. `tls` is the worker thread that executes this method.
fn release(&mut self, tls: VMWorkerThread);

/// Inform the plan about the end of a GC. It is guaranteed that there is no further work for this GC.
/// This is invoked once per GC by one worker thread. `tls` is the worker thread that executes this method.
fn end_of_gc(&mut self, _tls: VMWorkerThread) {}

/// Ask the plan if they would trigger a GC. If MMTk is in charge of triggering GCs, this method is called
/// periodically during allocation. However, MMTk may delegate the GC triggering decision to the runtime,
/// in which case, this method may not be called. This method returns true to trigger a collection.
Expand Down
5 changes: 5 additions & 0 deletions src/scheduler/gc_work.rs
Expand Up @@ -223,6 +223,11 @@ impl<VM: VMBinding> GCWork<VM> for EndOfGC {
fn do_work(&mut self, worker: &mut GCWorker<VM>, mmtk: &'static MMTK<VM>) {
info!("End of GC");

// We assume this is the only running work packet that accesses plan at the point of execution
#[allow(clippy::cast_ref_to_mut)]
let plan_mut: &mut dyn Plan<VM = VM> = unsafe { &mut *(&*mmtk.plan as *const _ as *mut _) };
plan_mut.end_of_gc(worker.tls);

#[cfg(feature = "extreme_assertions")]
if crate::util::edge_logger::should_check_duplicate_edges(&*mmtk.plan) {
// reset the logging info at the end of each GC
Expand Down

0 comments on commit 06237f1

Please sign in to comment.