diff options
author | Ben Gamari <ben@smart-cactus.org> | 2020-02-26 13:05:16 -0500 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2020-02-28 02:36:12 -0500 |
commit | f4b6b594fae6b257e997ade3fae67b3378e54a22 (patch) | |
tree | 9b171679e7180497185065c483a4c7ff0e9a5bac /rts/sm/NonMovingMark.c | |
parent | 9be82389a702c09d03975e7a0c17e5866dc17ffc (diff) | |
download | haskell-f4b6b594fae6b257e997ade3fae67b3378e54a22.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.
Diffstat (limited to 'rts/sm/NonMovingMark.c')
-rw-r--r-- | rts/sm/NonMovingMark.c | 24 |
1 files changed, 13 insertions, 11 deletions
diff --git a/rts/sm/NonMovingMark.c b/rts/sm/NonMovingMark.c index 81000566cb..6d70ca21dd 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 |