summaryrefslogtreecommitdiff
path: root/rts/sm/Scav.c
diff options
context:
space:
mode:
Diffstat (limited to 'rts/sm/Scav.c')
-rw-r--r--rts/sm/Scav.c46
1 files changed, 29 insertions, 17 deletions
diff --git a/rts/sm/Scav.c b/rts/sm/Scav.c
index ea39ebdff6..b969de3a74 100644
--- a/rts/sm/Scav.c
+++ b/rts/sm/Scav.c
@@ -132,6 +132,17 @@ scavenge_fun_srt(const StgInfoTable *info)
Scavenge a TSO.
-------------------------------------------------------------------------- */
+STATIC_INLINE void
+scavenge_TSO_link (StgTSO *tso)
+{
+ // We don't always chase the link field: TSOs on the blackhole
+ // queue are not automatically alive, so the link field is a
+ // "weak" pointer in that case.
+ if (tso->why_blocked != BlockedOnBlackHole) {
+ evacuate((StgClosure **)&tso->_link);
+ }
+}
+
static void
scavengeTSO (StgTSO *tso)
{
@@ -156,13 +167,6 @@ scavengeTSO (StgTSO *tso)
}
evacuate((StgClosure **)&tso->blocked_exceptions);
- // We don't always chase the link field: TSOs on the blackhole
- // queue are not automatically alive, so the link field is a
- // "weak" pointer in that case.
- if (tso->why_blocked != BlockedOnBlackHole) {
- evacuate((StgClosure **)&tso->link);
- }
-
// scavange current transaction record
evacuate((StgClosure **)&tso->trec);
@@ -171,8 +175,15 @@ scavengeTSO (StgTSO *tso)
if (gct->failed_to_evac) {
tso->flags |= TSO_DIRTY;
+ scavenge_TSO_link(tso);
} else {
tso->flags &= ~TSO_DIRTY;
+ scavenge_TSO_link(tso);
+ if (gct->failed_to_evac) {
+ tso->flags |= TSO_LINK_DIRTY;
+ } else {
+ tso->flags &= ~TSO_LINK_DIRTY;
+ }
}
gct->eager_promotion = saved_eager;
@@ -517,7 +528,6 @@ linear_scan:
case TSO:
{
scavengeTSO((StgTSO*)p);
- gct->failed_to_evac = rtsTrue; // always on the mutable list
break;
}
@@ -837,7 +847,6 @@ scavenge_one(StgPtr p)
case TSO:
{
scavengeTSO((StgTSO*)p);
- gct->failed_to_evac = rtsTrue; // always on the mutable list
break;
}
@@ -1026,14 +1035,17 @@ scavenge_mutable_list(generation *gen)
case TSO: {
StgTSO *tso = (StgTSO *)p;
if ((tso->flags & TSO_DIRTY) == 0) {
- // A clean TSO: we don't have to traverse its
- // stack. However, we *do* follow the link field:
- // we don't want to have to mark a TSO dirty just
- // because we put it on a different queue.
- if (tso->why_blocked != BlockedOnBlackHole) {
- evacuate((StgClosure **)&tso->link);
- }
- recordMutableGen_GC((StgClosure *)p,gen);
+ // Must be on the mutable list because its link
+ // field is dirty.
+ ASSERT(tso->flags & TSO_LINK_DIRTY);
+
+ scavenge_TSO_link(tso);
+ if (gct->failed_to_evac) {
+ recordMutableGen_GC((StgClosure *)p,gen);
+ gct->failed_to_evac = rtsFalse;
+ } else {
+ tso->flags &= ~TSO_LINK_DIRTY;
+ }
continue;
}
}