summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2022-10-22 19:10:23 +0000
committerMarge Bot <ben+marge-bot@smart-cactus.org>2023-03-08 15:02:30 -0500
commit2db92e015655e7fc22e559020572bf23233ffaae (patch)
treecaed5d7f0376a0ac2844d3b2da630c0fa3dc63fe
parent58e53bc4d33dad76b3250997f1a8300d0041f387 (diff)
downloadhaskell-2db92e015655e7fc22e559020572bf23233ffaae.tar.gz
nonmoving: Handle new closures in nonmovingIsNowAlive
We must conservatively assume that new closures are reachable since we are not guaranteed to mark such blocks.
-rw-r--r--rts/sm/NonMoving.h12
-rw-r--r--rts/sm/NonMovingMark.c14
2 files changed, 18 insertions, 8 deletions
diff --git a/rts/sm/NonMoving.h b/rts/sm/NonMoving.h
index 1f82a77a93..5be85788d7 100644
--- a/rts/sm/NonMoving.h
+++ b/rts/sm/NonMoving.h
@@ -300,19 +300,17 @@ INLINE_HEADER void nonmovingSetClosureMark(StgPtr p)
nonmovingSetMark(nonmovingGetSegment(p), nonmovingGetBlockIdx(p));
}
-/* Was the given closure marked this major GC cycle? */
-INLINE_HEADER bool nonmovingClosureMarkedThisCycle(StgPtr p)
+INLINE_HEADER uint8_t nonmovingGetClosureMark(StgPtr p)
{
struct NonmovingSegment *seg = nonmovingGetSegment(p);
nonmoving_block_idx blk_idx = nonmovingGetBlockIdx(p);
- return nonmovingGetMark(seg, blk_idx) == nonmovingMarkEpoch;
+ return nonmovingGetMark(seg, blk_idx);
}
-INLINE_HEADER bool nonmovingClosureMarked(StgPtr p)
+/* Was the given closure marked this major GC cycle? */
+INLINE_HEADER bool nonmovingClosureMarkedThisCycle(StgPtr p)
{
- struct NonmovingSegment *seg = nonmovingGetSegment(p);
- nonmoving_block_idx blk_idx = nonmovingGetBlockIdx(p);
- return nonmovingGetMark(seg, blk_idx) != 0;
+ return nonmovingGetClosureMark(p) == nonmovingMarkEpoch;
}
// Can be called during a major collection to determine whether a particular
diff --git a/rts/sm/NonMovingMark.c b/rts/sm/NonMovingMark.c
index f91bcbd58d..56cb73b5e4 100644
--- a/rts/sm/NonMovingMark.c
+++ b/rts/sm/NonMovingMark.c
@@ -1896,7 +1896,19 @@ static bool nonmovingIsNowAlive (StgClosure *p)
|| (bd->flags & BF_MARKED) != 0;
// The object was marked
} else {
- return nonmovingClosureMarkedThisCycle((P_)p);
+ struct NonmovingSegment *seg = nonmovingGetSegment((StgPtr) p);
+ StgClosure *snapshot_loc =
+ (StgClosure *) nonmovingSegmentGetBlock(seg, nonmovingSegmentInfo(seg)->next_free_snap);
+ if (p >= snapshot_loc && nonmovingGetClosureMark((StgPtr) p) == 0) {
+ /*
+ * In this case we are looking at a block that wasn't allocated
+ * at the time that the snapshot was taken. As we do not mark such
+ * blocks, we must assume that it is reachable.
+ */
+ return true;
+ } else {
+ return nonmovingClosureMarkedThisCycle((P_)p);
+ }
}
}