Skip to content

Commit

Permalink
Rename edge to slot (#1134)
Browse files Browse the repository at this point in the history
This commit changes the term "edge" to "slot" where it actually refers
to a field of an object or a variable on the stack or in any global data
structures. Notably, the trait `Edge` is renamed to `Slot`, and related
types and methods are renamed, too. We still use the term "edge" to
refer to edges in the object graph, regardless whether the edge is
represented by a slot or by an object reference pointing to the target.

The work packet trait `ProcessEdgesWork` and its implementations still
use the term "edge". Although it was originally designed to process
slots, it can be used (and is currently actually used) in node-enqueuing
tracing as well as weak reference processing, in which case it is used
as a provider of the `trace_object` method which traces object graph
edges represented as `ObjectReference` to the target objects.

Note: This commit only does renaming, and does not change the program
logic. The behavior of the program should be exactly the same after this
change.

Fixes: #687
  • Loading branch information
wks committed May 22, 2024
1 parent dccce90 commit 56b2521
Show file tree
Hide file tree
Showing 30 changed files with 489 additions and 451 deletions.
2 changes: 1 addition & 1 deletion docs/userguide/src/portingguide/howto/nogc.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ The `VMBinding` trait is a "meta-trait" (i.e. a trait that encapsulates other tr
3. [`ObjectModel`](https://docs.mmtk.io/api/mmtk/vm/trait.ObjectModel.html): This trait implements the runtime's object model. The object model includes object metadata such as mark-bits, forwarding-bits, etc.; constants regarding assumptions about object addresses; and functions to implement copying objects, querying object sizes, etc. You should ***carefully*** implement and understand this as it is a key trait on which many things depend. We will go into more detail about this trait in the [object model section](#object-model).
4. [`ReferenceGlue`](https://docs.mmtk.io/api/mmtk/vm/trait.ReferenceGlue.html): This trait implements runtime-specific finalization and weak reference processing methods. Note that each runtime has its own way of dealing with finalization and reference processing, so this is often one of the trickiest traits to implement.
5. [`Scanning`](https://docs.mmtk.io/api/mmtk/vm/trait.Scanning.html): This trait implements object scanning functions such as scanning mutator threads for root pointers, scanning a particular object for reference fields, etc.
6. [`Edge`](https://docs.mmtk.io/api/mmtk/vm/edge_shape/trait.Edge.html): This trait implements what an edge in the object graph looks like in the runtime. This is useful as it can abstract over compressed or tagged pointers. If an edge in your runtime is indistinguishable from an arbitrary address, you may set it to the [`Address`](https://docs.mmtk.io/api/mmtk/util/address/struct.Address.html) type.
6. [`Slot`](https://docs.mmtk.io/api/mmtk/vm/slot/trait.Slot.html): This trait implements what an edge in the object graph looks like in the runtime. This is useful as it can abstract over compressed or tagged pointers. If an edge in your runtime is indistinguishable from an arbitrary address, you may set it to the [`Address`](https://docs.mmtk.io/api/mmtk/util/address/struct.Address.html) type.
7. [`MemorySlice`](https://docs.mmtk.io/api/mmtk/vm/edge_shape/trait.MemorySlice.html): This trait implements functions related to memory slices such as arrays. This is mainly used by generational collectors.

For the time-being we can implement all the above traits via `unimplemented!()` stubs. If you are using the Dummy VM binding as a starting point, you will have to edit some of the concrete implementations to `unimplemented!()`. Note that you should change the type that implements `VMBinding` from `DummyVM` to an appropriately named type for your runtime. For example, the OpenJDK binding defines the zero-struct [`OpenJDK`](https://github.com/mmtk/mmtk-openjdk/blob/54a249e877e1cbea147a71aafaafb8583f33843d/mmtk/src/lib.rs#L139-L162) which implements the `VMBinding` trait.
Expand Down
4 changes: 2 additions & 2 deletions docs/userguide/src/tutorial/code/mygc_semispace/gc_work.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ impl<VM: VMBinding> ProcessEdgesWork for MyGCProcessEdges<VM> {
type ScanObjectsWorkType = ScanObjects<Self>;

fn new(
edges: Vec<EdgeOf<Self>>,
slots: Vec<SlotOf<Self>>,
roots: bool,
mmtk: &'static MMTK<VM>,
bucket: WorkBucketStage,
) -> Self {
let base = ProcessEdgesBase::new(edges, roots, mmtk, bucket);
let base = ProcessEdgesBase::new(slots, roots, mmtk, bucket);
let plan = base.plan().downcast_ref::<MyGC<VM>>().unwrap();
Self { base, plan }
}
Expand Down
14 changes: 7 additions & 7 deletions src/memory_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::util::constants::{LOG_BYTES_IN_PAGE, MIN_OBJECT_SIZE};
use crate::util::heap::layout::vm_layout::vm_layout;
use crate::util::opaque_pointer::*;
use crate::util::{Address, ObjectReference};
use crate::vm::edge_shape::MemorySlice;
use crate::vm::slot::MemorySlice;
use crate::vm::ReferenceGlue;
use crate::vm::VMBinding;

Expand Down Expand Up @@ -250,7 +250,7 @@ pub fn post_alloc<VM: VMBinding>(
pub fn object_reference_write<VM: VMBinding>(
mutator: &mut Mutator<VM>,
src: ObjectReference,
slot: VM::VMEdge,
slot: VM::VMSlot,
target: ObjectReference,
) {
mutator.barrier().object_reference_write(src, slot, target);
Expand All @@ -276,7 +276,7 @@ pub fn object_reference_write<VM: VMBinding>(
pub fn object_reference_write_pre<VM: VMBinding>(
mutator: &mut Mutator<VM>,
src: ObjectReference,
slot: VM::VMEdge,
slot: VM::VMSlot,
target: Option<ObjectReference>,
) {
mutator
Expand Down Expand Up @@ -304,7 +304,7 @@ pub fn object_reference_write_pre<VM: VMBinding>(
pub fn object_reference_write_post<VM: VMBinding>(
mutator: &mut Mutator<VM>,
src: ObjectReference,
slot: VM::VMEdge,
slot: VM::VMSlot,
target: Option<ObjectReference>,
) {
mutator
Expand All @@ -315,7 +315,7 @@ pub fn object_reference_write_post<VM: VMBinding>(
/// The *subsuming* memory region copy barrier by MMTk.
/// This is called when the VM tries to copy a piece of heap memory to another.
/// The data within the slice does not necessarily to be all valid pointers,
/// but the VM binding will be able to filter out non-reference values on edge iteration.
/// but the VM binding will be able to filter out non-reference values on slot iteration.
///
/// For VMs that performs a heap memory copy operation, for example OpenJDK's array copy operation, the binding needs to
/// call `memory_region_copy*` APIs. Same as `object_reference_write*`, the binding can choose either the subsuming barrier,
Expand All @@ -340,7 +340,7 @@ pub fn memory_region_copy<VM: VMBinding>(
/// *before* it performs memory copy.
/// This is called when the VM tries to copy a piece of heap memory to another.
/// The data within the slice does not necessarily to be all valid pointers,
/// but the VM binding will be able to filter out non-reference values on edge iteration.
/// but the VM binding will be able to filter out non-reference values on slot iteration.
///
/// For VMs that performs a heap memory copy operation, for example OpenJDK's array copy operation, the binding needs to
/// call `memory_region_copy*` APIs. Same as `object_reference_write*`, the binding can choose either the subsuming barrier,
Expand All @@ -365,7 +365,7 @@ pub fn memory_region_copy_pre<VM: VMBinding>(
/// *after* it performs memory copy.
/// This is called when the VM tries to copy a piece of heap memory to another.
/// The data within the slice does not necessarily to be all valid pointers,
/// but the VM binding will be able to filter out non-reference values on edge iteration.
/// but the VM binding will be able to filter out non-reference values on slot iteration.
///
/// For VMs that performs a heap memory copy operation, for example OpenJDK's array copy operation, the binding needs to
/// call `memory_region_copy*` APIs. Same as `object_reference_write*`, the binding can choose either the subsuming barrier,
Expand Down
10 changes: 5 additions & 5 deletions src/mmtk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ use crate::scheduler::GCWorkScheduler;

#[cfg(feature = "analysis")]
use crate::util::analysis::AnalysisManager;
#[cfg(feature = "extreme_assertions")]
use crate::util::edge_logger::EdgeLogger;
use crate::util::finalizable_processor::FinalizableProcessor;
use crate::util::heap::gc_trigger::GCTrigger;
use crate::util::heap::layout::vm_layout::VMLayout;
Expand All @@ -20,6 +18,8 @@ use crate::util::options::Options;
use crate::util::reference_processor::ReferenceProcessors;
#[cfg(feature = "sanity")]
use crate::util::sanity::sanity_checker::SanityChecker;
#[cfg(feature = "extreme_assertions")]
use crate::util::slot_logger::SlotLogger;
use crate::util::statistics::stats::Stats;
use crate::vm::ReferenceGlue;
use crate::vm::VMBinding;
Expand Down Expand Up @@ -113,9 +113,9 @@ pub struct MMTK<VM: VMBinding> {
Mutex<FinalizableProcessor<<VM::VMReferenceGlue as ReferenceGlue<VM>>::FinalizableType>>,
pub(crate) scheduler: Arc<GCWorkScheduler<VM>>,
#[cfg(feature = "sanity")]
pub(crate) sanity_checker: Mutex<SanityChecker<VM::VMEdge>>,
pub(crate) sanity_checker: Mutex<SanityChecker<VM::VMSlot>>,
#[cfg(feature = "extreme_assertions")]
pub(crate) edge_logger: EdgeLogger<VM::VMEdge>,
pub(crate) slot_logger: SlotLogger<VM::VMSlot>,
pub(crate) gc_trigger: Arc<GCTrigger<VM>>,
pub(crate) gc_requester: Arc<GCRequester<VM>>,
pub(crate) stats: Arc<Stats>,
Expand Down Expand Up @@ -222,7 +222,7 @@ impl<VM: VMBinding> MMTK<VM> {
inside_sanity: AtomicBool::new(false),
inside_harness: AtomicBool::new(false),
#[cfg(feature = "extreme_assertions")]
edge_logger: EdgeLogger::new(),
slot_logger: SlotLogger::new(),
#[cfg(feature = "analysis")]
analysis_manager: Arc::new(AnalysisManager::new(stats.clone())),
gc_trigger,
Expand Down
16 changes: 8 additions & 8 deletions src/plan/barriers.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Read/Write barrier implementations.

use crate::vm::edge_shape::{Edge, MemorySlice};
use crate::vm::slot::{MemorySlice, Slot};
use crate::vm::ObjectModel;
use crate::{
util::{metadata::MetadataSpec, *},
Expand Down Expand Up @@ -49,7 +49,7 @@ pub trait Barrier<VM: VMBinding>: 'static + Send + Downcast {
fn object_reference_write(
&mut self,
src: ObjectReference,
slot: VM::VMEdge,
slot: VM::VMSlot,
target: ObjectReference,
) {
self.object_reference_write_pre(src, slot, Some(target));
Expand All @@ -61,7 +61,7 @@ pub trait Barrier<VM: VMBinding>: 'static + Send + Downcast {
fn object_reference_write_pre(
&mut self,
_src: ObjectReference,
_slot: VM::VMEdge,
_slot: VM::VMSlot,
_target: Option<ObjectReference>,
) {
}
Expand All @@ -70,7 +70,7 @@ pub trait Barrier<VM: VMBinding>: 'static + Send + Downcast {
fn object_reference_write_post(
&mut self,
_src: ObjectReference,
_slot: VM::VMEdge,
_slot: VM::VMSlot,
_target: Option<ObjectReference>,
) {
}
Expand All @@ -80,7 +80,7 @@ pub trait Barrier<VM: VMBinding>: 'static + Send + Downcast {
fn object_reference_write_slow(
&mut self,
_src: ObjectReference,
_slot: VM::VMEdge,
_slot: VM::VMSlot,
_target: Option<ObjectReference>,
) {
}
Expand Down Expand Up @@ -146,7 +146,7 @@ pub trait BarrierSemantics: 'static + Send {
fn object_reference_write_slow(
&mut self,
src: ObjectReference,
slot: <Self::VM as VMBinding>::VMEdge,
slot: <Self::VM as VMBinding>::VMSlot,
target: Option<ObjectReference>,
);

Expand Down Expand Up @@ -216,7 +216,7 @@ impl<S: BarrierSemantics> Barrier<S::VM> for ObjectBarrier<S> {
fn object_reference_write_post(
&mut self,
src: ObjectReference,
slot: <S::VM as VMBinding>::VMEdge,
slot: <S::VM as VMBinding>::VMSlot,
target: Option<ObjectReference>,
) {
if self.object_is_unlogged(src) {
Expand All @@ -227,7 +227,7 @@ impl<S: BarrierSemantics> Barrier<S::VM> for ObjectBarrier<S> {
fn object_reference_write_slow(
&mut self,
src: ObjectReference,
slot: <S::VM as VMBinding>::VMEdge,
slot: <S::VM as VMBinding>::VMSlot,
target: Option<ObjectReference>,
) {
if self.log_object(src) {
Expand Down
4 changes: 2 additions & 2 deletions src/plan/generational/barrier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::policy::gc_work::DEFAULT_TRACE;
use crate::scheduler::WorkBucketStage;
use crate::util::constants::BYTES_IN_INT;
use crate::util::*;
use crate::vm::edge_shape::MemorySlice;
use crate::vm::slot::MemorySlice;
use crate::vm::VMBinding;
use crate::MMTK;

Expand Down Expand Up @@ -74,7 +74,7 @@ impl<VM: VMBinding, P: GenerationalPlanExt<VM> + PlanTraceObject<VM>> BarrierSem
fn object_reference_write_slow(
&mut self,
src: ObjectReference,
_slot: VM::VMEdge,
_slot: VM::VMSlot,
_target: Option<ObjectReference>,
) {
// enqueue the object
Expand Down
16 changes: 8 additions & 8 deletions src/plan/generational/gc_work.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::plan::VectorObjectQueue;
use crate::policy::gc_work::TraceKind;
use crate::scheduler::{gc_work::*, GCWork, GCWorker, WorkBucketStage};
use crate::util::ObjectReference;
use crate::vm::edge_shape::{Edge, MemorySlice};
use crate::vm::slot::{MemorySlice, Slot};
use crate::vm::*;
use crate::MMTK;
use std::marker::PhantomData;
Expand All @@ -32,12 +32,12 @@ impl<VM: VMBinding, P: GenerationalPlanExt<VM> + PlanTraceObject<VM>, const KIND
type ScanObjectsWorkType = PlanScanObjects<Self, P>;

fn new(
edges: Vec<EdgeOf<Self>>,
slots: Vec<SlotOf<Self>>,
roots: bool,
mmtk: &'static MMTK<VM>,
bucket: WorkBucketStage,
) -> Self {
let base = ProcessEdgesBase::new(edges, roots, mmtk, bucket);
let base = ProcessEdgesBase::new(slots, roots, mmtk, bucket);
let plan = base.plan().downcast_ref().unwrap();
Self { plan, base }
}
Expand All @@ -52,7 +52,7 @@ impl<VM: VMBinding, P: GenerationalPlanExt<VM> + PlanTraceObject<VM>, const KIND
)
}

fn process_edge(&mut self, slot: EdgeOf<Self>) {
fn process_slot(&mut self, slot: SlotOf<Self>) {
let Some(object) = slot.load() else {
// Skip slots that are not holding an object reference.
return;
Expand Down Expand Up @@ -163,15 +163,15 @@ impl<E: ProcessEdgesWork> GCWork<E::VM> for ProcessRegionModBuf<E> {
.is_current_gc_nursery()
{
// Collect all the entries in all the slices
let mut edges = vec![];
let mut slots = vec![];
for slice in &self.modbuf {
for edge in slice.iter_edges() {
edges.push(edge);
for slot in slice.iter_slots() {
slots.push(slot);
}
}
// Forward entries
GCWork::do_work(
&mut E::new(edges, false, mmtk, WorkBucketStage::Closure),
&mut E::new(slots, false, mmtk, WorkBucketStage::Closure),
worker,
mmtk,
)
Expand Down
2 changes: 1 addition & 1 deletion src/plan/markcompact/gc_work.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl<VM: VMBinding> GCWork<VM> for UpdateReferences<VM> {
plan_mut.common.release(worker.tls, true);
plan_mut.common.prepare(worker.tls, true);
#[cfg(feature = "extreme_assertions")]
mmtk.edge_logger.reset();
mmtk.slot_logger.reset();

// We do two passes of transitive closures. We clear the live bytes from the first pass.
#[cfg(feature = "count_live_bytes_in_gc")]
Expand Down
11 changes: 8 additions & 3 deletions src/plan/plan_constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,14 @@ pub struct PlanConstraints {
pub max_non_los_copy_bytes: usize,
/// Does this plan use the log bit? See vm::ObjectModel::GLOBAL_LOG_BIT_SPEC.
pub needs_log_bit: bool,
/// Some plans may allow benign race for testing mark bit, and this will lead to trace the same edges
/// multiple times. If a plan allows tracing duplicate edges, we will not run duplicate edge check
/// in extreme_assertions.
/// Some plans may allow benign race for testing mark bit, and this will lead to trace the same
/// edge multiple times. If a plan allows tracing duplicated edges, we will not run duplicate
/// edge check in extreme_assertions.
///
/// Note: Both [`crate::vm::Scanning::scan_object`] (which enqueues slots) and
/// [`crate::vm::Scanning::scan_object_and_trace_edges`] (which traces the targets directly) are
/// affected by such benign races. But our current duplicate edge check in extreme_assertions
/// only identifies duplicated slots.
pub may_trace_duplicate_edges: bool,
/// The barrier this plan uses. A binding may check this and know what kind of write barrier is in use
/// if they would like to implement the barrier fast path in the binding side.
Expand Down
18 changes: 9 additions & 9 deletions src/plan/tracing.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
//! This module contains code useful for tracing,
//! i.e. visiting the reachable objects by traversing all or part of an object graph.

use crate::scheduler::gc_work::{EdgeOf, ProcessEdgesWork};
use crate::scheduler::gc_work::{ProcessEdgesWork, SlotOf};
use crate::scheduler::{GCWorker, WorkBucketStage};
use crate::util::ObjectReference;
use crate::vm::EdgeVisitor;
use crate::vm::SlotVisitor;

/// This trait represents an object queue to enqueue objects during tracing.
pub trait ObjectQueue {
Expand Down Expand Up @@ -77,11 +77,11 @@ impl ObjectQueue for VectorQueue<ObjectReference> {
}
}

/// A transitive closure visitor to collect the edges from objects.
/// It maintains a buffer for the edges, and flushes edges to a new work packet
/// A transitive closure visitor to collect the slots from objects.
/// It maintains a buffer for the slots, and flushes slots to a new work packet
/// if the buffer is full or if the type gets dropped.
pub struct ObjectsClosure<'a, E: ProcessEdgesWork> {
buffer: VectorQueue<EdgeOf<E>>,
buffer: VectorQueue<SlotOf<E>>,
pub(crate) worker: &'a mut GCWorker<E::VM>,
bucket: WorkBucketStage,
}
Expand Down Expand Up @@ -111,13 +111,13 @@ impl<'a, E: ProcessEdgesWork> ObjectsClosure<'a, E> {
}
}

impl<'a, E: ProcessEdgesWork> EdgeVisitor<EdgeOf<E>> for ObjectsClosure<'a, E> {
fn visit_edge(&mut self, slot: EdgeOf<E>) {
impl<'a, E: ProcessEdgesWork> SlotVisitor<SlotOf<E>> for ObjectsClosure<'a, E> {
fn visit_slot(&mut self, slot: SlotOf<E>) {
#[cfg(debug_assertions)]
{
use crate::vm::edge_shape::Edge;
use crate::vm::slot::Slot;
trace!(
"(ObjectsClosure) Visit edge {:?} (pointing to {:?})",
"(ObjectsClosure) Visit slot {:?} (pointing to {:?})",
slot,
slot.load()
);
Expand Down
Loading

0 comments on commit 56b2521

Please sign in to comment.