Skip to content

Commit ec6ba72

Browse files
committed
Only reset unlog bits of objects in modbuf for nursery GCs or if in bootimage
This fixes a bug wherein we were erroneously resetting the unlog bits for objects in the modbuf for full-heap GCs. If we reset the unlog bits in a full-heap GC, we may end up setting the unlog bit for an object that actually died which may cause issues for future allocations. This PR also adds debug assertions checking that any object that has been added to the modbuf is considered "live" by MMTk, or in other words, it is a mature object.
1 parent b8355f8 commit ec6ba72

File tree

2 files changed

+39
-10
lines changed

2 files changed

+39
-10
lines changed

src/plan/barriers.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,11 @@ impl<S: BarrierSemantics> Barrier<S::VM> for ObjectBarrier<S> {
231231
target: Option<ObjectReference>,
232232
) {
233233
if self.log_object(src) {
234+
debug_assert!(
235+
src.is_live::<S::VM>(),
236+
"{} was logged but is not live",
237+
src
238+
);
234239
self.semantics
235240
.object_reference_write_slow(src, slot, target);
236241
}

src/plan/generational/gc_work.rs

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -108,29 +108,53 @@ impl<E: ProcessEdgesWork> ProcessModBuf<E> {
108108

109109
impl<E: ProcessEdgesWork> GCWork<E::VM> for ProcessModBuf<E> {
110110
fn do_work(&mut self, worker: &mut GCWorker<E::VM>, mmtk: &'static MMTK<E::VM>) {
111-
// Flip the per-object unlogged bits to "unlogged" state.
112-
for obj in &self.modbuf {
113-
<E::VM as VMBinding>::VMObjectModel::GLOBAL_LOG_BIT_SPEC.store_atomic::<E::VM, u8>(
114-
*obj,
115-
1,
116-
None,
117-
Ordering::SeqCst,
118-
);
119-
}
120-
// scan modbuf only if the current GC is a nursery GC
111+
// Process and scan modbuf only if the current GC is a nursery GC
121112
if mmtk
122113
.get_plan()
123114
.generational()
124115
.unwrap()
125116
.is_current_gc_nursery()
126117
{
118+
// Flip the per-object unlogged bits to "unlogged" state.
119+
for obj in &self.modbuf {
120+
debug_assert!(
121+
(*obj).is_live::<E::VM>(),
122+
"{} was logged but is not live",
123+
*obj
124+
);
125+
126+
<E::VM as VMBinding>::VMObjectModel::GLOBAL_LOG_BIT_SPEC.store_atomic::<E::VM, u8>(
127+
*obj,
128+
1,
129+
None,
130+
Ordering::SeqCst,
131+
);
132+
}
127133
// Scan objects in the modbuf and forward pointers
128134
let modbuf = std::mem::take(&mut self.modbuf);
129135
GCWork::do_work(
130136
&mut ScanObjects::<E>::new(modbuf, false, WorkBucketStage::Closure),
131137
worker,
132138
mmtk,
133139
)
140+
} else {
141+
// Flip the per-object unlogged bits to "unlogged" state for objects inside the bootimage
142+
#[cfg(feature = "vm_space")]
143+
{
144+
use crate::policy::space::Space;
145+
146+
for obj in &self.modbuf {
147+
if mmtk.get_plan().base().vm_space.in_space(*obj) {
148+
<E::VM as VMBinding>::VMObjectModel::GLOBAL_LOG_BIT_SPEC.store_atomic::<E::VM, u8>(
149+
*obj,
150+
1,
151+
None,
152+
Ordering::SeqCst,
153+
);
154+
}
155+
}
156+
157+
}
134158
}
135159
}
136160
}

0 commit comments

Comments
 (0)