summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2020-02-26 13:05:16 -0500
committerBen Gamari <ben@smart-cactus.org>2020-03-04 12:33:25 -0500
commitea7ff702a9b8366e68aae30ff816b542c15e26c5 (patch)
treeb2c916c6c3aaf94123f87e555cfdb870934e4b69
parentfe488bbe22df3dda4cfcb02fd350eaf50e6622e1 (diff)
downloadhaskell-ea7ff702a9b8366e68aae30ff816b542c15e26c5.tar.gz
nonmoving: Fix marking in compact regions
Previously we were tracing the object we were asked to mark, even if it lives in a compact region. However, there is no need to do this; we need only to mark the region itself as live. I have seen a segfault due to this due to the concurrent mark seeing a an object in the process of being compacted by the mutator. (cherry picked from commit e4e9a7ba3abc991d3583371da4681560a7b67bd2)
-rw-r--r--rts/sm/NonMovingMark.c24
1 files changed, 13 insertions, 11 deletions
diff --git a/rts/sm/NonMovingMark.c b/rts/sm/NonMovingMark.c
index 085d7827df..433385e2bc 100644
--- a/rts/sm/NonMovingMark.c
+++ b/rts/sm/NonMovingMark.c
@@ -1276,9 +1276,19 @@ mark_closure (MarkQueue *queue, const StgClosure *p0, StgClosure **origin)
// Not in the snapshot
return;
}
- if (bd->flags & BF_MARKED) {
- goto done;
+
+ if (! (bd->flags & BF_MARKED)) {
+ dbl_link_remove(bd, &nonmoving_compact_objects);
+ dbl_link_onto(bd, &nonmoving_marked_compact_objects);
+ StgWord blocks = str->totalW / BLOCK_SIZE_W;
+ n_nonmoving_compact_blocks -= blocks;
+ n_nonmoving_marked_compact_blocks += blocks;
+ bd->flags |= BF_MARKED;
}
+
+ // N.B. the object being marked is in a compact region so by
+ // definition there is no need to do any tracing here.
+ goto done;
} else if (bd->flags & BF_LARGE) {
if (! (bd->flags & BF_NONMOVING_SWEEPING)) {
// Not in the snapshot
@@ -1611,15 +1621,7 @@ mark_closure (MarkQueue *queue, const StgClosure *p0, StgClosure **origin)
* the object's pointers since in the case of marking stacks there may be a
* mutator waiting for us to finish so it can start execution.
*/
- if (bd->flags & BF_COMPACT) {
- StgCompactNFData *str = objectGetCompact((StgClosure*)p);
- dbl_link_remove(bd, &nonmoving_compact_objects);
- dbl_link_onto(bd, &nonmoving_marked_compact_objects);
- StgWord blocks = str->totalW / BLOCK_SIZE_W;
- n_nonmoving_compact_blocks -= blocks;
- n_nonmoving_marked_compact_blocks += blocks;
- bd->flags |= BF_MARKED;
- } else if (bd->flags & BF_LARGE) {
+ if (bd->flags & BF_LARGE) {
/* Marking a large object isn't idempotent since we move it to
* nonmoving_marked_large_objects; to ensure that we don't repeatedly
* mark a large object, we only set BF_MARKED on large objects in the