Skip to content

Commit 56b2521

Browse files
authored
Rename edge to slot (#1134)
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
1 parent dccce90 commit 56b2521

30 files changed

+489
-451
lines changed

docs/userguide/src/portingguide/howto/nogc.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ The `VMBinding` trait is a "meta-trait" (i.e. a trait that encapsulates other tr
6464
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).
6565
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.
6666
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.
67-
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.
67+
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.
6868
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.
6969

7070
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.

docs/userguide/src/tutorial/code/mygc_semispace/gc_work.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@ impl<VM: VMBinding> ProcessEdgesWork for MyGCProcessEdges<VM> {
4545
type ScanObjectsWorkType = ScanObjects<Self>;
4646

4747
fn new(
48-
edges: Vec<EdgeOf<Self>>,
48+
slots: Vec<SlotOf<Self>>,
4949
roots: bool,
5050
mmtk: &'static MMTK<VM>,
5151
bucket: WorkBucketStage,
5252
) -> Self {
53-
let base = ProcessEdgesBase::new(edges, roots, mmtk, bucket);
53+
let base = ProcessEdgesBase::new(slots, roots, mmtk, bucket);
5454
let plan = base.plan().downcast_ref::<MyGC<VM>>().unwrap();
5555
Self { base, plan }
5656
}

src/memory_manager.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::util::constants::{LOG_BYTES_IN_PAGE, MIN_OBJECT_SIZE};
2222
use crate::util::heap::layout::vm_layout::vm_layout;
2323
use crate::util::opaque_pointer::*;
2424
use crate::util::{Address, ObjectReference};
25-
use crate::vm::edge_shape::MemorySlice;
25+
use crate::vm::slot::MemorySlice;
2626
use crate::vm::ReferenceGlue;
2727
use crate::vm::VMBinding;
2828

@@ -250,7 +250,7 @@ pub fn post_alloc<VM: VMBinding>(
250250
pub fn object_reference_write<VM: VMBinding>(
251251
mutator: &mut Mutator<VM>,
252252
src: ObjectReference,
253-
slot: VM::VMEdge,
253+
slot: VM::VMSlot,
254254
target: ObjectReference,
255255
) {
256256
mutator.barrier().object_reference_write(src, slot, target);
@@ -276,7 +276,7 @@ pub fn object_reference_write<VM: VMBinding>(
276276
pub fn object_reference_write_pre<VM: VMBinding>(
277277
mutator: &mut Mutator<VM>,
278278
src: ObjectReference,
279-
slot: VM::VMEdge,
279+
slot: VM::VMSlot,
280280
target: Option<ObjectReference>,
281281
) {
282282
mutator
@@ -304,7 +304,7 @@ pub fn object_reference_write_pre<VM: VMBinding>(
304304
pub fn object_reference_write_post<VM: VMBinding>(
305305
mutator: &mut Mutator<VM>,
306306
src: ObjectReference,
307-
slot: VM::VMEdge,
307+
slot: VM::VMSlot,
308308
target: Option<ObjectReference>,
309309
) {
310310
mutator
@@ -315,7 +315,7 @@ pub fn object_reference_write_post<VM: VMBinding>(
315315
/// The *subsuming* memory region copy barrier by MMTk.
316316
/// This is called when the VM tries to copy a piece of heap memory to another.
317317
/// The data within the slice does not necessarily to be all valid pointers,
318-
/// but the VM binding will be able to filter out non-reference values on edge iteration.
318+
/// but the VM binding will be able to filter out non-reference values on slot iteration.
319319
///
320320
/// For VMs that performs a heap memory copy operation, for example OpenJDK's array copy operation, the binding needs to
321321
/// call `memory_region_copy*` APIs. Same as `object_reference_write*`, the binding can choose either the subsuming barrier,
@@ -340,7 +340,7 @@ pub fn memory_region_copy<VM: VMBinding>(
340340
/// *before* it performs memory copy.
341341
/// This is called when the VM tries to copy a piece of heap memory to another.
342342
/// The data within the slice does not necessarily to be all valid pointers,
343-
/// but the VM binding will be able to filter out non-reference values on edge iteration.
343+
/// but the VM binding will be able to filter out non-reference values on slot iteration.
344344
///
345345
/// For VMs that performs a heap memory copy operation, for example OpenJDK's array copy operation, the binding needs to
346346
/// call `memory_region_copy*` APIs. Same as `object_reference_write*`, the binding can choose either the subsuming barrier,
@@ -365,7 +365,7 @@ pub fn memory_region_copy_pre<VM: VMBinding>(
365365
/// *after* it performs memory copy.
366366
/// This is called when the VM tries to copy a piece of heap memory to another.
367367
/// The data within the slice does not necessarily to be all valid pointers,
368-
/// but the VM binding will be able to filter out non-reference values on edge iteration.
368+
/// but the VM binding will be able to filter out non-reference values on slot iteration.
369369
///
370370
/// For VMs that performs a heap memory copy operation, for example OpenJDK's array copy operation, the binding needs to
371371
/// call `memory_region_copy*` APIs. Same as `object_reference_write*`, the binding can choose either the subsuming barrier,

src/mmtk.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ use crate::scheduler::GCWorkScheduler;
88

99
#[cfg(feature = "analysis")]
1010
use crate::util::analysis::AnalysisManager;
11-
#[cfg(feature = "extreme_assertions")]
12-
use crate::util::edge_logger::EdgeLogger;
1311
use crate::util::finalizable_processor::FinalizableProcessor;
1412
use crate::util::heap::gc_trigger::GCTrigger;
1513
use crate::util::heap::layout::vm_layout::VMLayout;
@@ -20,6 +18,8 @@ use crate::util::options::Options;
2018
use crate::util::reference_processor::ReferenceProcessors;
2119
#[cfg(feature = "sanity")]
2220
use crate::util::sanity::sanity_checker::SanityChecker;
21+
#[cfg(feature = "extreme_assertions")]
22+
use crate::util::slot_logger::SlotLogger;
2323
use crate::util::statistics::stats::Stats;
2424
use crate::vm::ReferenceGlue;
2525
use crate::vm::VMBinding;
@@ -113,9 +113,9 @@ pub struct MMTK<VM: VMBinding> {
113113
Mutex<FinalizableProcessor<<VM::VMReferenceGlue as ReferenceGlue<VM>>::FinalizableType>>,
114114
pub(crate) scheduler: Arc<GCWorkScheduler<VM>>,
115115
#[cfg(feature = "sanity")]
116-
pub(crate) sanity_checker: Mutex<SanityChecker<VM::VMEdge>>,
116+
pub(crate) sanity_checker: Mutex<SanityChecker<VM::VMSlot>>,
117117
#[cfg(feature = "extreme_assertions")]
118-
pub(crate) edge_logger: EdgeLogger<VM::VMEdge>,
118+
pub(crate) slot_logger: SlotLogger<VM::VMSlot>,
119119
pub(crate) gc_trigger: Arc<GCTrigger<VM>>,
120120
pub(crate) gc_requester: Arc<GCRequester<VM>>,
121121
pub(crate) stats: Arc<Stats>,
@@ -222,7 +222,7 @@ impl<VM: VMBinding> MMTK<VM> {
222222
inside_sanity: AtomicBool::new(false),
223223
inside_harness: AtomicBool::new(false),
224224
#[cfg(feature = "extreme_assertions")]
225-
edge_logger: EdgeLogger::new(),
225+
slot_logger: SlotLogger::new(),
226226
#[cfg(feature = "analysis")]
227227
analysis_manager: Arc::new(AnalysisManager::new(stats.clone())),
228228
gc_trigger,

src/plan/barriers.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Read/Write barrier implementations.
22
3-
use crate::vm::edge_shape::{Edge, MemorySlice};
3+
use crate::vm::slot::{MemorySlice, Slot};
44
use crate::vm::ObjectModel;
55
use crate::{
66
util::{metadata::MetadataSpec, *},
@@ -49,7 +49,7 @@ pub trait Barrier<VM: VMBinding>: 'static + Send + Downcast {
4949
fn object_reference_write(
5050
&mut self,
5151
src: ObjectReference,
52-
slot: VM::VMEdge,
52+
slot: VM::VMSlot,
5353
target: ObjectReference,
5454
) {
5555
self.object_reference_write_pre(src, slot, Some(target));
@@ -61,7 +61,7 @@ pub trait Barrier<VM: VMBinding>: 'static + Send + Downcast {
6161
fn object_reference_write_pre(
6262
&mut self,
6363
_src: ObjectReference,
64-
_slot: VM::VMEdge,
64+
_slot: VM::VMSlot,
6565
_target: Option<ObjectReference>,
6666
) {
6767
}
@@ -70,7 +70,7 @@ pub trait Barrier<VM: VMBinding>: 'static + Send + Downcast {
7070
fn object_reference_write_post(
7171
&mut self,
7272
_src: ObjectReference,
73-
_slot: VM::VMEdge,
73+
_slot: VM::VMSlot,
7474
_target: Option<ObjectReference>,
7575
) {
7676
}
@@ -80,7 +80,7 @@ pub trait Barrier<VM: VMBinding>: 'static + Send + Downcast {
8080
fn object_reference_write_slow(
8181
&mut self,
8282
_src: ObjectReference,
83-
_slot: VM::VMEdge,
83+
_slot: VM::VMSlot,
8484
_target: Option<ObjectReference>,
8585
) {
8686
}
@@ -146,7 +146,7 @@ pub trait BarrierSemantics: 'static + Send {
146146
fn object_reference_write_slow(
147147
&mut self,
148148
src: ObjectReference,
149-
slot: <Self::VM as VMBinding>::VMEdge,
149+
slot: <Self::VM as VMBinding>::VMSlot,
150150
target: Option<ObjectReference>,
151151
);
152152

@@ -216,7 +216,7 @@ impl<S: BarrierSemantics> Barrier<S::VM> for ObjectBarrier<S> {
216216
fn object_reference_write_post(
217217
&mut self,
218218
src: ObjectReference,
219-
slot: <S::VM as VMBinding>::VMEdge,
219+
slot: <S::VM as VMBinding>::VMSlot,
220220
target: Option<ObjectReference>,
221221
) {
222222
if self.object_is_unlogged(src) {
@@ -227,7 +227,7 @@ impl<S: BarrierSemantics> Barrier<S::VM> for ObjectBarrier<S> {
227227
fn object_reference_write_slow(
228228
&mut self,
229229
src: ObjectReference,
230-
slot: <S::VM as VMBinding>::VMEdge,
230+
slot: <S::VM as VMBinding>::VMSlot,
231231
target: Option<ObjectReference>,
232232
) {
233233
if self.log_object(src) {

src/plan/generational/barrier.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::policy::gc_work::DEFAULT_TRACE;
77
use crate::scheduler::WorkBucketStage;
88
use crate::util::constants::BYTES_IN_INT;
99
use crate::util::*;
10-
use crate::vm::edge_shape::MemorySlice;
10+
use crate::vm::slot::MemorySlice;
1111
use crate::vm::VMBinding;
1212
use crate::MMTK;
1313

@@ -74,7 +74,7 @@ impl<VM: VMBinding, P: GenerationalPlanExt<VM> + PlanTraceObject<VM>> BarrierSem
7474
fn object_reference_write_slow(
7575
&mut self,
7676
src: ObjectReference,
77-
_slot: VM::VMEdge,
77+
_slot: VM::VMSlot,
7878
_target: Option<ObjectReference>,
7979
) {
8080
// enqueue the object

src/plan/generational/gc_work.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::plan::VectorObjectQueue;
55
use crate::policy::gc_work::TraceKind;
66
use crate::scheduler::{gc_work::*, GCWork, GCWorker, WorkBucketStage};
77
use crate::util::ObjectReference;
8-
use crate::vm::edge_shape::{Edge, MemorySlice};
8+
use crate::vm::slot::{MemorySlice, Slot};
99
use crate::vm::*;
1010
use crate::MMTK;
1111
use std::marker::PhantomData;
@@ -32,12 +32,12 @@ impl<VM: VMBinding, P: GenerationalPlanExt<VM> + PlanTraceObject<VM>, const KIND
3232
type ScanObjectsWorkType = PlanScanObjects<Self, P>;
3333

3434
fn new(
35-
edges: Vec<EdgeOf<Self>>,
35+
slots: Vec<SlotOf<Self>>,
3636
roots: bool,
3737
mmtk: &'static MMTK<VM>,
3838
bucket: WorkBucketStage,
3939
) -> Self {
40-
let base = ProcessEdgesBase::new(edges, roots, mmtk, bucket);
40+
let base = ProcessEdgesBase::new(slots, roots, mmtk, bucket);
4141
let plan = base.plan().downcast_ref().unwrap();
4242
Self { plan, base }
4343
}
@@ -52,7 +52,7 @@ impl<VM: VMBinding, P: GenerationalPlanExt<VM> + PlanTraceObject<VM>, const KIND
5252
)
5353
}
5454

55-
fn process_edge(&mut self, slot: EdgeOf<Self>) {
55+
fn process_slot(&mut self, slot: SlotOf<Self>) {
5656
let Some(object) = slot.load() else {
5757
// Skip slots that are not holding an object reference.
5858
return;
@@ -163,15 +163,15 @@ impl<E: ProcessEdgesWork> GCWork<E::VM> for ProcessRegionModBuf<E> {
163163
.is_current_gc_nursery()
164164
{
165165
// Collect all the entries in all the slices
166-
let mut edges = vec![];
166+
let mut slots = vec![];
167167
for slice in &self.modbuf {
168-
for edge in slice.iter_edges() {
169-
edges.push(edge);
168+
for slot in slice.iter_slots() {
169+
slots.push(slot);
170170
}
171171
}
172172
// Forward entries
173173
GCWork::do_work(
174-
&mut E::new(edges, false, mmtk, WorkBucketStage::Closure),
174+
&mut E::new(slots, false, mmtk, WorkBucketStage::Closure),
175175
worker,
176176
mmtk,
177177
)

src/plan/markcompact/gc_work.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ impl<VM: VMBinding> GCWork<VM> for UpdateReferences<VM> {
4848
plan_mut.common.release(worker.tls, true);
4949
plan_mut.common.prepare(worker.tls, true);
5050
#[cfg(feature = "extreme_assertions")]
51-
mmtk.edge_logger.reset();
51+
mmtk.slot_logger.reset();
5252

5353
// We do two passes of transitive closures. We clear the live bytes from the first pass.
5454
#[cfg(feature = "count_live_bytes_in_gc")]

src/plan/plan_constraints.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,14 @@ pub struct PlanConstraints {
2121
pub max_non_los_copy_bytes: usize,
2222
/// Does this plan use the log bit? See vm::ObjectModel::GLOBAL_LOG_BIT_SPEC.
2323
pub needs_log_bit: bool,
24-
/// Some plans may allow benign race for testing mark bit, and this will lead to trace the same edges
25-
/// multiple times. If a plan allows tracing duplicate edges, we will not run duplicate edge check
26-
/// in extreme_assertions.
24+
/// Some plans may allow benign race for testing mark bit, and this will lead to trace the same
25+
/// edge multiple times. If a plan allows tracing duplicated edges, we will not run duplicate
26+
/// edge check in extreme_assertions.
27+
///
28+
/// Note: Both [`crate::vm::Scanning::scan_object`] (which enqueues slots) and
29+
/// [`crate::vm::Scanning::scan_object_and_trace_edges`] (which traces the targets directly) are
30+
/// affected by such benign races. But our current duplicate edge check in extreme_assertions
31+
/// only identifies duplicated slots.
2732
pub may_trace_duplicate_edges: bool,
2833
/// The barrier this plan uses. A binding may check this and know what kind of write barrier is in use
2934
/// if they would like to implement the barrier fast path in the binding side.

src/plan/tracing.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
//! This module contains code useful for tracing,
22
//! i.e. visiting the reachable objects by traversing all or part of an object graph.
33
4-
use crate::scheduler::gc_work::{EdgeOf, ProcessEdgesWork};
4+
use crate::scheduler::gc_work::{ProcessEdgesWork, SlotOf};
55
use crate::scheduler::{GCWorker, WorkBucketStage};
66
use crate::util::ObjectReference;
7-
use crate::vm::EdgeVisitor;
7+
use crate::vm::SlotVisitor;
88

99
/// This trait represents an object queue to enqueue objects during tracing.
1010
pub trait ObjectQueue {
@@ -77,11 +77,11 @@ impl ObjectQueue for VectorQueue<ObjectReference> {
7777
}
7878
}
7979

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

114-
impl<'a, E: ProcessEdgesWork> EdgeVisitor<EdgeOf<E>> for ObjectsClosure<'a, E> {
115-
fn visit_edge(&mut self, slot: EdgeOf<E>) {
114+
impl<'a, E: ProcessEdgesWork> SlotVisitor<SlotOf<E>> for ObjectsClosure<'a, E> {
115+
fn visit_slot(&mut self, slot: SlotOf<E>) {
116116
#[cfg(debug_assertions)]
117117
{
118-
use crate::vm::edge_shape::Edge;
118+
use crate::vm::slot::Slot;
119119
trace!(
120-
"(ObjectsClosure) Visit edge {:?} (pointing to {:?})",
120+
"(ObjectsClosure) Visit slot {:?} (pointing to {:?})",
121121
slot,
122122
slot.load()
123123
);

0 commit comments

Comments
 (0)