-
Notifications
You must be signed in to change notification settings - Fork 78
Description
The file src/scheduler/gc_work.rs contains about 1200 lines of code, with more than 20 structs and more than 50 impl items.
- There are simply too many items, and
- they are not ordered or grouped in the way they are used. Not by use cases, and not in the temporal order in a GC.
This made it difficult for developers to find the right type or function when they want to make modification to MMTk. But one design goal of MMTk is to make this easy.
Reorganizing this file into multiple files
We can categorize the work packets and traits by their use cases.
Unless specified, items listed below are struct items.
- Generic GC scheduling work packets.
ScheduleCollectionStopMutatorsPreparePrepareMutatorPrepareCollectorReleaseReleaseMutatorReleaseCollectorVMPostForwarding(running concurrently withRelease)
- Root scanning
ScanMutatorRootsScanVMSpecificRootsProcessEdgesWorkRootsWorkFactory(implementsRootsWorkFactorydefined insrc/vm/scanning.rs)- enum
RootsKind
- Tracing (transitive closure)
- Slots/edges
ProcessEdgesBase(This is all about processing slots instead of edges).- trait
ProcessEdgesWork(This part really needs to be refactored.ProcessEdgesWork::trace_objectshouldn't be specific to slot-enqueued tracing.) SFTProcessEdgesPlanProcessEdgesProcessEdgesWorkTracer(implementsObjectTracerdefined insrc/vm/scanning.rs)UnsupportedProcessEdges
- Nodes
- trait
ScanObjectsWork ScanObjectsPlanScanObjectsProcessRootNode(for pinning and transitive-pinning roots)
- trait
- Slots/edges
- Finalizer and weak references
ProcessEdgesWorkTracerContext(implementsTracerContextdefined insrc/vm/scanning.rs)VMProcessWeakRefsVMForwardWeakRefs
Refactoring slots-processing work packets
In the early stage of the Rust port, MMTk was very focused on slot-enqueuing tracing because that's what OpenJDK and JikesRVM do. One design decision which I think is bad is that it mixed up "edge processing" and "slots processing".
- Slot processing: For each slot in a list of slots, load from it, call
trace_object, and store back forwarded reference. - Edge visiting: The
trace_object(obj) -> new_objmethod. This effectively visits an object graph edge that points toobj, regardless whetherobjis loaded from a givenSlotor obtained in VM-specific ways inScanning::scan_object_and_trace_edges. In the end, if a VM binding only supports node-enqueuing tracing (such as Ruby), we have to wrapProcessEdgesWorkbehind theObjectTracertrait which only provides thetrace_objectmethod (that is,ProcessEdgesWorkTracer).
I had a branch that refactors the trace_object into a dedicated type and leaves the ProcessEdgesWork dedicated to slot processing. The code is here: #1278, but it is very old.
And #599 contains more information about my intended refactoring.