Skip to content

Commit e2951ad

Browse files
authored
NULL and movement check in process_edge (#1032)
This PR does two things: 1. `ProcessEdgesWork::process_edge` will skip slots that are not holding references (i.e. if `Edge::load()` returns `ObjectReference::NULL`). 2. `ProcessEdgesWork::process_edge` will skip the `Edge::store()` if the object is not moved. Doing (1) removes unnecessary invocations of `trace_object()` as well as the subsequent `Edge::store()`. It also allows slots to hold non-reference tagged values. In that case, the VM binding can return `ObjectReference::NULL` in `Edge::load()` so that mmtk-core will simply skip the slot, fixing #1031 Doing (2) removes unnecessary `Edge::store()` operations in the case where the objects are not moved during `trace_object`. It reduces the STW time in most cases, fixing #574 Fixes: #1031 Fixes: #574
1 parent 658bce8 commit e2951ad

File tree

14 files changed

+82
-40
lines changed

14 files changed

+82
-40
lines changed

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,7 @@ impl<VM: VMBinding> ProcessEdgesWork for MyGCProcessEdges<VM> {
5656
}
5757

5858
fn trace_object(&mut self, object: ObjectReference) -> ObjectReference {
59-
if object.is_null() {
60-
return object;
61-
}
59+
debug_assert!(!object.is_null());
6260
let worker = self.worker();
6361
let queue = &mut self.base.nodes;
6462
if self.plan.tospace().in_space(object) {

docs/userguide/src/tutorial/mygc/ss/exercise_solution.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,7 @@ In `gc_work.rs`:
149149
the tospace and fromspace:
150150
```rust
151151
fn trace_object(&mut self, object: ObjectReference) -> ObjectReference {
152-
if object.is_null() {
153-
return object;
154-
}
152+
debug_assert!(!object.is_null());
155153
156154
// Add this!
157155
else if self.plan().youngspace().in_space(object) {

src/plan/generational/gc_work.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,25 @@ impl<VM: VMBinding, P: GenerationalPlanExt<VM> + PlanTraceObject<VM>> ProcessEdg
3636
Self { plan, base }
3737
}
3838
fn trace_object(&mut self, object: ObjectReference) -> ObjectReference {
39-
if object.is_null() {
40-
return object;
41-
}
39+
debug_assert!(!object.is_null());
40+
4241
// We cannot borrow `self` twice in a call, so we extract `worker` as a local variable.
4342
let worker = self.worker();
4443
self.plan
4544
.trace_object_nursery(&mut self.base.nodes, object, worker)
4645
}
4746
fn process_edge(&mut self, slot: EdgeOf<Self>) {
4847
let object = slot.load();
48+
if object.is_null() {
49+
return;
50+
}
4951
let new_object = self.trace_object(object);
5052
debug_assert!(!self.plan.is_object_in_nursery(new_object));
51-
slot.store(new_object);
53+
// Note: If `object` is a mature object, `trace_object` will not call `space.trace_object`,
54+
// but will still return `object`. In that case, we don't need to write it back.
55+
if new_object != object {
56+
slot.store(new_object);
57+
}
5258
}
5359

5460
fn create_scan_work(

src/policy/copyspace.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ impl<VM: VMBinding> CopySpace<VM> {
217217
worker: &mut GCWorker<VM>,
218218
) -> ObjectReference {
219219
trace!("copyspace.trace_object(, {:?}, {:?})", object, semantics,);
220+
debug_assert!(!object.is_null());
220221

221222
// If this is not from space, we do not need to trace it (the object has been copied to the tosapce)
222223
if !self.is_from_space() {

src/policy/immix/immixspace.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ impl<VM: VMBinding> crate::policy::gc_work::PolicyTraceObject<VM> for ImmixSpace
184184
copy: Option<CopySemantics>,
185185
worker: &mut GCWorker<VM>,
186186
) -> ObjectReference {
187+
debug_assert!(!object.is_null());
187188
if KIND == TRACE_KIND_TRANSITIVE_PIN {
188189
self.trace_object_without_moving(queue, object)
189190
} else if KIND == TRACE_KIND_DEFRAG {

src/policy/immortalspace.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ impl<VM: VMBinding> ImmortalSpace<VM> {
187187
queue: &mut Q,
188188
object: ObjectReference,
189189
) -> ObjectReference {
190+
debug_assert!(!object.is_null());
190191
#[cfg(feature = "vo_bit")]
191192
debug_assert!(
192193
crate::util::metadata::vo_bit::is_vo_bit_set::<VM>(object),

src/policy/largeobjectspace.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ impl<VM: VMBinding> LargeObjectSpace<VM> {
189189
queue: &mut Q,
190190
object: ObjectReference,
191191
) -> ObjectReference {
192+
debug_assert!(!object.is_null());
192193
#[cfg(feature = "vo_bit")]
193194
debug_assert!(
194195
crate::util::metadata::vo_bit::is_vo_bit_set::<VM>(object),

src/policy/markcompactspace.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ impl<VM: VMBinding> crate::policy::gc_work::PolicyTraceObject<VM> for MarkCompac
130130
_copy: Option<CopySemantics>,
131131
_worker: &mut GCWorker<VM>,
132132
) -> ObjectReference {
133+
debug_assert!(!object.is_null());
133134
debug_assert!(
134135
KIND != TRACE_KIND_TRANSITIVE_PIN,
135136
"MarkCompact does not support transitive pin trace."

src/policy/marksweepspace/malloc_ms/global.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -400,9 +400,7 @@ impl<VM: VMBinding> MallocSpace<VM> {
400400
queue: &mut Q,
401401
object: ObjectReference,
402402
) -> ObjectReference {
403-
if object.is_null() {
404-
return object;
405-
}
403+
debug_assert!(!object.is_null());
406404

407405
assert!(
408406
self.in_space(object),

src/policy/marksweepspace/native_ms/global.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,7 @@ impl<VM: VMBinding> MarkSweepSpace<VM> {
241241
queue: &mut Q,
242242
object: ObjectReference,
243243
) -> ObjectReference {
244-
if object.is_null() {
245-
return object;
246-
}
244+
debug_assert!(!object.is_null());
247245
debug_assert!(
248246
self.in_space(object),
249247
"Cannot mark an object {} that was not alloced by free list allocator.",

0 commit comments

Comments
 (0)