diff options
Diffstat (limited to 'rts/sm/NonMovingMark.c')
-rw-r--r-- | rts/sm/NonMovingMark.c | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/rts/sm/NonMovingMark.c b/rts/sm/NonMovingMark.c index e4c1c57d36..f91bcbd58d 100644 --- a/rts/sm/NonMovingMark.c +++ b/rts/sm/NonMovingMark.c @@ -37,6 +37,7 @@ static void trace_PAP_payload (MarkQueue *queue, StgClosure *fun, StgClosure **payload, StgWord size); +static bool is_nonmoving_weak(StgWeak *weak); // How many Array# entries to add to the mark queue at once? #define MARK_ARRAY_CHUNK_LENGTH 128 @@ -1525,10 +1526,12 @@ mark_closure (MarkQueue *queue, const StgClosure *p0, StgClosure **origin) break; } + case WEAK: + ASSERT(is_nonmoving_weak((StgWeak*) p)); + // fallthrough gen_obj: case CONSTR: case CONSTR_NOCAF: - case WEAK: case PRIM: { for (StgWord i = 0; i < info->layout.payload.ptrs; i++) { @@ -1897,6 +1900,28 @@ static bool nonmovingIsNowAlive (StgClosure *p) } } +// Mark all Weak#s on nonmoving_old_weak_ptr_list. +void nonmovingMarkWeakPtrList (struct MarkQueue_ *queue) +{ + ASSERT(nonmoving_weak_ptr_list == NULL); + for (StgWeak *w = nonmoving_old_weak_ptr_list; w != NULL; w = w->link) { + mark_closure(queue, (StgClosure *) w, NULL); + } +} + +// Determine whether a weak pointer object is on one of the nonmoving +// collector's weak pointer lists. Used for sanity checking. +static bool is_nonmoving_weak(StgWeak *weak) +{ + for (StgWeak *w = nonmoving_old_weak_ptr_list; w != NULL; w = w->link) { + if (w == weak) return true; + } + for (StgWeak *w = nonmoving_weak_ptr_list; w != NULL; w = w->link) { + if (w == weak) return true; + } + return false; +} + // Non-moving heap variant of `tidyWeakList` bool nonmovingTidyWeaks (struct MarkQueue_ *queue) { @@ -1905,6 +1930,9 @@ bool nonmovingTidyWeaks (struct MarkQueue_ *queue) StgWeak **last_w = &nonmoving_old_weak_ptr_list; StgWeak *next_w; for (StgWeak *w = nonmoving_old_weak_ptr_list; w != NULL; w = next_w) { + // This should have been marked by nonmovingMarkWeaks + ASSERT(nonmovingIsNowAlive((StgClosure *) w)); + if (w->header.info == &stg_DEAD_WEAK_info) { // finalizeWeak# was called on the weak next_w = w->link; @@ -1915,7 +1943,10 @@ bool nonmovingTidyWeaks (struct MarkQueue_ *queue) // Otherwise it's a live weak ASSERT(w->header.info == &stg_WEAK_info); - if (nonmovingIsNowAlive(w->key)) { + // See Note [Weak pointer processing and the non-moving GC] in + // MarkWeak.c + bool key_in_nonmoving = Bdescr((StgPtr) w->key)->flags & BF_NONMOVING; + if (!key_in_nonmoving || nonmovingIsNowAlive(w->key)) { nonmovingMarkLiveWeak(queue, w); did_work = true; @@ -1923,7 +1954,7 @@ bool nonmovingTidyWeaks (struct MarkQueue_ *queue) *last_w = w->link; next_w = w->link; - // and put it on the weak ptr list + // and put it on nonmoving_weak_ptr_list w->link = nonmoving_weak_ptr_list; nonmoving_weak_ptr_list = w; } else { @@ -1945,7 +1976,8 @@ void nonmovingMarkDeadWeak (struct MarkQueue_ *queue, StgWeak *w) void nonmovingMarkLiveWeak (struct MarkQueue_ *queue, StgWeak *w) { - ASSERT(nonmovingClosureMarkedThisCycle((P_)w)); + ASSERT(nonmovingIsNowAlive((StgClosure *) w)); + ASSERT(nonmovingIsNowAlive((StgClosure *) w->key)); markQueuePushClosure_(queue, w->value); markQueuePushClosure_(queue, w->finalizer); markQueuePushClosure_(queue, w->cfinalizers); @@ -1959,9 +1991,9 @@ void nonmovingMarkDeadWeaks (struct MarkQueue_ *queue, StgWeak **dead_weaks) { StgWeak *next_w; for (StgWeak *w = nonmoving_old_weak_ptr_list; w; w = next_w) { - ASSERT(!nonmovingClosureMarkedThisCycle((P_)(w->key))); + ASSERT(!nonmovingIsNowAlive(w->key)); nonmovingMarkDeadWeak(queue, w); - next_w = w ->link; + next_w = w->link; w->link = *dead_weaks; *dead_weaks = w; } |