Skip to content

Commit 5a01555

Browse files
authored
Ensure reference objects are either traced or cleared (#1126)
After retaining soft references, we postpone the scanning of soft references until the transitive closure from retained soft references is fully expanded. While tracing and scanning new objects reached from the referents of soft references, new soft references may be discovered, and they will be added to the reference processor. By postponing the scanning, we ensure the newly discovered soft references are scanned, too. To ensure we do not accidentally enqueue more objects than we should, we no longer call `trace_object` when *scanning* soft, weak and phantom references. Instead, we call `ObjectReference::get_forwarded_object` to get the forwarded references and referents. We still call `trace_object` when *retaining* soft references, and when forwarding references in MarkCompact during the second transitive closure. Fixes: #1125
1 parent 491a607 commit 5a01555

File tree

5 files changed

+137
-75
lines changed

5 files changed

+137
-75
lines changed

src/plan/markcompact/global.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,9 @@ impl<VM: VMBinding> Plan for MarkCompact<VM> {
112112
scheduler.work_buckets[WorkBucketStage::SoftRefClosure]
113113
.add(SoftRefProcessing::<MarkingProcessEdges<VM>>::new());
114114
scheduler.work_buckets[WorkBucketStage::WeakRefClosure]
115-
.add(WeakRefProcessing::<MarkingProcessEdges<VM>>::new());
115+
.add(WeakRefProcessing::<VM>::new());
116116
scheduler.work_buckets[WorkBucketStage::PhantomRefClosure]
117-
.add(PhantomRefProcessing::<MarkingProcessEdges<VM>>::new());
117+
.add(PhantomRefProcessing::<VM>::new());
118118

119119
use crate::util::reference_processor::RefForwarding;
120120
scheduler.work_buckets[WorkBucketStage::RefForwarding]

src/policy/markcompactspace.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,12 @@ impl<VM: VMBinding> MarkCompactSpace<VM> {
251251
queue.enqueue(object);
252252
}
253253

254-
Self::get_header_forwarding_pointer(object)
254+
let result = Self::get_header_forwarding_pointer(object);
255+
debug_assert!(
256+
!result.is_null(),
257+
"Object {object} does not have a forwarding pointer"
258+
);
259+
result
255260
}
256261

257262
pub fn test_and_mark(object: ObjectReference) -> bool {

src/scheduler/scheduler.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,9 @@ impl<VM: VMBinding> GCWorkScheduler<VM> {
172172
};
173173
self.work_buckets[WorkBucketStage::SoftRefClosure]
174174
.add(SoftRefProcessing::<C::DefaultProcessEdges>::new());
175-
self.work_buckets[WorkBucketStage::WeakRefClosure]
176-
.add(WeakRefProcessing::<C::DefaultProcessEdges>::new());
175+
self.work_buckets[WorkBucketStage::WeakRefClosure].add(WeakRefProcessing::<VM>::new());
177176
self.work_buckets[WorkBucketStage::PhantomRefClosure]
178-
.add(PhantomRefProcessing::<C::DefaultProcessEdges>::new());
177+
.add(PhantomRefProcessing::<VM>::new());
179178

180179
use crate::util::reference_processor::RefForwarding;
181180
if plan.constraints().needs_forward_after_liveness {

src/util/finalizable_processor.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::plan::is_nursery_gc;
22
use crate::scheduler::gc_work::ProcessEdgesWork;
33
use crate::scheduler::{GCWork, GCWorker, WorkBucketStage};
4+
use crate::util::reference_processor::RescanReferences;
45
use crate::util::ObjectReference;
56
use crate::util::VMWorkerThread;
67
use crate::vm::Finalizable;
@@ -140,6 +141,17 @@ pub struct Finalization<E: ProcessEdgesWork>(PhantomData<E>);
140141

141142
impl<E: ProcessEdgesWork> GCWork<E::VM> for Finalization<E> {
142143
fn do_work(&mut self, worker: &mut GCWorker<E::VM>, mmtk: &'static MMTK<E::VM>) {
144+
if !*mmtk.options.no_reference_types {
145+
// Rescan soft and weak references at the end of the transitive closure from resurrected
146+
// objects. New soft and weak references may be discovered during this.
147+
let rescan = Box::new(RescanReferences {
148+
soft: true,
149+
weak: true,
150+
phantom_data: PhantomData,
151+
});
152+
worker.scheduler().work_buckets[WorkBucketStage::FinalRefClosure].set_sentinel(rescan);
153+
}
154+
143155
let mut finalizable_processor = mmtk.finalizable_processor.lock().unwrap();
144156
debug!(
145157
"Finalization, {} objects in candidates, {} objects ready to finalize",

0 commit comments

Comments
 (0)