Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 19 additions & 12 deletions src/scheduler/gc_work.rs
Original file line number Diff line number Diff line change
Expand Up @@ -756,7 +756,7 @@ impl<VM: VMBinding, DPE: ProcessEdgesWork<VM = VM>, PPE: ProcessEdgesWork<VM = V
crate::memory_manager::add_work_packet(
self.mmtk,
WorkBucketStage::PinningRootsTrace,
ProcessRootNode::<VM, PPE, DPE>::new(nodes, WorkBucketStage::Closure),
ProcessRootNodes::<VM, PPE, DPE>::new(nodes, WorkBucketStage::Closure),
);
}

Expand All @@ -765,7 +765,7 @@ impl<VM: VMBinding, DPE: ProcessEdgesWork<VM = VM>, PPE: ProcessEdgesWork<VM = V
crate::memory_manager::add_work_packet(
self.mmtk,
WorkBucketStage::TPinningClosure,
ProcessRootNode::<VM, PPE, PPE>::new(nodes, WorkBucketStage::TPinningClosure),
ProcessRootNodes::<VM, PPE, PPE>::new(nodes, WorkBucketStage::TPinningClosure),
);
}
}
Expand Down Expand Up @@ -1071,7 +1071,7 @@ impl<E: ProcessEdgesWork, P: Plan<VM = E::VM> + PlanTraceObject<E::VM>> GCWork<E
/// - If `O2OPE` may move objects, then this `ProcessRootsNode<VM, R2OPE, O2OPE>` work packet
/// will only pin the objects in `roots` (because `R2OPE` must not move objects anyway), but
/// not their descendents.
pub(crate) struct ProcessRootNode<
pub(crate) struct ProcessRootNodes<
VM: VMBinding,
R2OPE: ProcessEdgesWork<VM = VM>,
O2OPE: ProcessEdgesWork<VM = VM>,
Expand All @@ -1082,7 +1082,7 @@ pub(crate) struct ProcessRootNode<
}

impl<VM: VMBinding, R2OPE: ProcessEdgesWork<VM = VM>, O2OPE: ProcessEdgesWork<VM = VM>>
ProcessRootNode<VM, R2OPE, O2OPE>
ProcessRootNodes<VM, R2OPE, O2OPE>
{
pub fn new(nodes: Vec<ObjectReference>, bucket: WorkBucketStage) -> Self {
Self {
Expand All @@ -1094,10 +1094,10 @@ impl<VM: VMBinding, R2OPE: ProcessEdgesWork<VM = VM>, O2OPE: ProcessEdgesWork<VM
}

impl<VM: VMBinding, R2OPE: ProcessEdgesWork<VM = VM>, O2OPE: ProcessEdgesWork<VM = VM>> GCWork<VM>
for ProcessRootNode<VM, R2OPE, O2OPE>
for ProcessRootNodes<VM, R2OPE, O2OPE>
{
fn do_work(&mut self, worker: &mut GCWorker<VM>, mmtk: &'static MMTK<VM>) {
trace!("ProcessRootNode");
trace!("ProcessRootNodes");

#[cfg(feature = "sanity")]
{
Expand All @@ -1109,15 +1109,17 @@ impl<VM: VMBinding, R2OPE: ProcessEdgesWork<VM = VM>, O2OPE: ProcessEdgesWork<VM
}
}

let num_roots = self.roots.len();

// This step conceptually traces the edges from root slots to the objects they point to.
// However, VMs that deliver root objects instead of root slots are incapable of updating
// root slots. Therefore, we call `trace_object` on those objects, and assert the GC
// doesn't move those objects because we cannot store the updated references back to the
// slots.
//
// The `scanned_root_objects` variable will hold those root objects which are traced for the
// The `root_objects_to_scan` variable will hold those root objects which are traced for the
// first time. We will create a work packet for scanning those roots.
let scanned_root_objects = {
let root_objects_to_scan = {
// We create an instance of E to use its `trace_object` method and its object queue.
let mut process_edges_work =
R2OPE::new(vec![], true, mmtk, WorkBucketStage::PinningRootsTrace);
Expand All @@ -1137,11 +1139,16 @@ impl<VM: VMBinding, R2OPE: ProcessEdgesWork<VM = VM>, O2OPE: ProcessEdgesWork<VM
process_edges_work.nodes.take()
};

let process_edges_work = O2OPE::new(vec![], false, mmtk, self.bucket);
let work = process_edges_work.create_scan_work(scanned_root_objects);
crate::memory_manager::add_work_packet(mmtk, self.bucket, work);
let num_enqueued_nodes = root_objects_to_scan.len();
probe!(mmtk, process_root_nodes, num_roots, num_enqueued_nodes);

if !root_objects_to_scan.is_empty() {
let process_edges_work = O2OPE::new(vec![], false, mmtk, self.bucket);
let work = process_edges_work.create_scan_work(root_objects_to_scan);
crate::memory_manager::add_work_packet(mmtk, self.bucket, work);
}

trace!("ProcessRootNode End");
trace!("ProcessRootNodes End");
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/util/sanity/sanity_checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ impl<P: Plan> GCWork<P::VM> for ScheduleSanityGC<P> {
);
}
for roots in &sanity_checker.root_nodes {
scheduler.work_buckets[WorkBucketStage::Closure].add(ProcessRootNode::<
scheduler.work_buckets[WorkBucketStage::Closure].add(ProcessRootNodes::<
P::VM,
SanityGCProcessEdges<P::VM>,
SanityGCProcessEdges<P::VM>,
Expand Down
2 changes: 2 additions & 0 deletions tools/tracing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ Currently, the core provides the following tracepoints.
- `mmtk:roots(kind: int, len: int)`: reporing roots to mmtk-core during root scanning. `kind` can
be 0, 1 or 2 for normal roots, pinning roots and transitively pinning roots, respectively.
`len` is the number of slots or nodes reported.
- `mmtk:process_root_nodes(num_roots: int, num_enqueued_nodes: int)`: a ProcessRootNodes work
packet which processes root edges represented as object references to the target objects.
- `mmtk:process_slots(num_slots: int, is_roots: bool)`: an invocation of the `process_slots`
method. The first argument is the number of slots to be processed, and the second argument is
whether these slots are root slots.
Expand Down
6 changes: 6 additions & 0 deletions tools/tracing/timeline/capture.bt
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ usdt:$MMTK:mmtk:roots {
}
}

usdt:$MMTK:mmtk:process_root_nodes {
if (@enable_print) {
printf("process_root_nodes,meta,%d,%lu,%lu,%lu\n", tid, nsecs, arg0, arg1);
}
}

usdt:$MMTK:mmtk:process_slots {
if (@enable_print) {
printf("process_slots,meta,%d,%lu,%lu,%lu\n", tid, nsecs, arg0, arg1);
Expand Down
6 changes: 6 additions & 0 deletions tools/tracing/timeline/visualize.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,12 @@ def enrich_meta(self, name, tid, ts, gc, wp, args):

roots_list.append(root_dict)

case "process_root_nodes":
wp["args"] |= {
"num_roots": int(args[0]),
"num_enqueued_nodes": int(args[1]),
}

case "process_slots":
wp["args"] |= {
# Group args by "process_slots" and "scan_objects" because a ProcessEdgesWork
Expand Down