Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename edge to slot #1134

Merged
merged 26 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from 23 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
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
Loading