-
Notifications
You must be signed in to change notification settings - Fork 78
Description
TL;DR: The reference processor is tightly coupled with ProcessEdgesWork
work packets, making it impossible to support runtimes that can only do object-enqueuing. We can make it general.
Problem
Currently, reference-processing work packets {Soft,Weak,Phantom}RefProcessing
take ProcessEdgesWork
as a parameter. For example:
pub struct SoftRefProcessing<E: ProcessEdgesWork>(PhantomData<E>);
impl<E: ProcessEdgesWork> GCWork<E::VM> for SoftRefProcessing<E> {
fn do_work(&mut self, worker: &mut GCWorker<E::VM>, mmtk: &'static MMTK<E::VM>) {
let mut w = E::new(vec![], false, mmtk);
w.set_worker(worker);
mmtk.reference_processors.scan_soft_refs(&mut w, mmtk);
w.flush();
}
}
Seeing from the use pattern, it instantiates E
, passes it to scan_soft_refs
, and calls .flush()
on it. It never calls w.do_work
, which indicates ProcessEdgesWork
is not a sub-task of SoftRefProcessing
. Instead, SoftRefProcessing
is just stealing some functionalities from ProcessEdgesWork
!
Analysis
It uses the E: ProcessEdgesWork
type for three purposes:
- Use
E::trace_object
to trace object. Traced soft/weak/phantom references will become softly/weakly/phantomly reachable. - Use
E
as an object queue.E::trace_object
takes a queue parameter (currently in the form of aTransitiveClosure
, but will be refactored in Remove TransitiveClosure param from Space::trace_object and Scanning::scan_object #559). - Use the object queue to create a object-scanning work packet.
w.flush()
does this. It will create aScanObjects
work packet to scan objects.
From the analysis, the SoftRefProcessing
work packet only has two dependencies:
- A delegate for calling
trace_object
in the appropriate space, and - The type of the object-scanning work packet to create. (More concretely, the post-scan hook which Immix needs.)
The queue is just a Vec<ObjectReference>
(or whatever that wraps it) and can be created locally.
Solution
To move away from ProcessEdgesWork
, we just need to parameterise {Soft,Weak,Phantom}RefProcessing
with a trait that provides the above two operations, namely trace_object
and post_scan_object
.
I have a draft for this trait. I call it TracingDelegate
.
pub trait TracingDelegate<VM: VMBinding>: 'static + Copy + Send {
fn trace_object<T: TransitiveClosure>(
&self,
trace: &mut T,
object: ObjectReference,
worker: &mut GCWorker<VM>,
) -> ObjectReference;
fn may_move_objects() -> bool;
fn post_scan_object(&self, object: ObjectReference);
}
They are just the three methods provided by PlanTraceObject
, except without the KIND
which can be parameterised on concrete implementations.
There should be two implementations, one for SFT, and the other for PlanTraceObject
, just like there are SFTProcessEdges
and PlanProcessEdges
.
Then SoftRefProcessing
can just call trace_object
from that trait. The ScanObjects
trait can also be refactored to use that trait.