summaryrefslogtreecommitdiff
path: root/rts/sm/NonMovingMark.c
diff options
context:
space:
mode:
Diffstat (limited to 'rts/sm/NonMovingMark.c')
-rw-r--r--rts/sm/NonMovingMark.c44
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;
}