[commit: ghc] ghc-8.0: Handle promotion failures when scavenging a WEAK (#11108) (0e12124)
git at git.haskell.org
git at git.haskell.org
Wed May 11 15:37:38 UTC 2016
Repository : ssh://git@git.haskell.org/ghc
On branch : ghc-8.0
Link : http://ghc.haskell.org/trac/ghc/changeset/0e12124320f0e09a56813fe6361e61043667db53/ghc
>---------------------------------------------------------------
commit 0e12124320f0e09a56813fe6361e61043667db53
Author: Takano Akio <tak at anoak.io>
Date: Wed May 11 14:45:29 2016 +0200
Handle promotion failures when scavenging a WEAK (#11108)
Previously, we ignored promotion failures when evacuating fields of
a WEAK object. When a failure happens, this resulted in an WEAK object
pointing to another object in a younger generation, causing crashes.
I used the test case from #11746 to check that the fix is working.
However I haven't managed to produce a test case that quickly reproduces
the issue.
Test Plan: ./validate
Reviewers: austin, bgamari, simonmar
Reviewed By: simonmar
Subscribers: thomie
Differential Revision: https://phabricator.haskell.org/D2189
GHC Trac Issues: #11108
(cherry picked from commit 9363f04d0ff22f3d898af35bb5432c4287e6dc9a)
>---------------------------------------------------------------
0e12124320f0e09a56813fe6361e61043667db53
rts/sm/MarkWeak.c | 37 +++++++++++++++++++++++++++++++++++--
rts/sm/MarkWeak.h | 1 +
rts/sm/Scav.c | 7 ++++++-
3 files changed, 42 insertions(+), 3 deletions(-)
diff --git a/rts/sm/MarkWeak.c b/rts/sm/MarkWeak.c
index 9a32198..bb6309d 100644
--- a/rts/sm/MarkWeak.c
+++ b/rts/sm/MarkWeak.c
@@ -25,6 +25,8 @@
#include "Storage.h"
#include "Threads.h"
+#include "sm/GCUtils.h"
+#include "sm/MarkWeak.h"
#include "sm/Sanity.h"
/* -----------------------------------------------------------------------------
@@ -265,10 +267,25 @@ static rtsBool tidyWeakList(generation *gen)
new_gen = Bdescr((P_)w)->gen;
gct->evac_gen_no = new_gen->no;
+ gct->failed_to_evac = rtsFalse;
// evacuate the value and finalizer
- evacuate(&w->value);
- evacuate(&w->finalizer);
+ //
+ // This WEAK object will not be considered by tidyWeakList
+ // during this collection because it is in a generation >= N,
+ // but it is on the mutable list so we must evacuate all of its
+ // pointers because some of them may point into a younger
+ // generation.
+ scavengeLiveWeak(w);
+
+ if (gct->failed_to_evac) {
+ debugTrace(DEBUG_weak,
+ "putting weak pointer %p into mutable list",
+ w);
+ gct->failed_to_evac = rtsFalse;
+ recordMutableGen_GC((StgClosure *)w, new_gen->no);
+ }
+
// remove this weak ptr from the old_weak_ptr list
*last_w = w->link;
next_w = w->link;
@@ -422,3 +439,19 @@ markWeakPtrList ( void )
}
}
+/* -----------------------------------------------------------------------------
+ Fully scavenge a known-to-be-alive weak pointer.
+
+ In scavenge_block, we only partially scavenge a weak pointer because it may
+ turn out to be dead. This function should be called when we decide that the
+ weak pointer is alive after this GC.
+ -------------------------------------------------------------------------- */
+
+void
+scavengeLiveWeak(StgWeak *w)
+{
+ evacuate(&w->value);
+ evacuate(&w->key);
+ evacuate(&w->finalizer);
+ evacuate(&w->cfinalizers);
+}
diff --git a/rts/sm/MarkWeak.h b/rts/sm/MarkWeak.h
index bd0231d..aabb954 100644
--- a/rts/sm/MarkWeak.h
+++ b/rts/sm/MarkWeak.h
@@ -24,6 +24,7 @@ void collectFreshWeakPtrs ( void );
void initWeakForGC ( void );
rtsBool traverseWeakPtrList ( void );
void markWeakPtrList ( void );
+void scavengeLiveWeak ( StgWeak * );
#include "EndPrivate.h"
diff --git a/rts/sm/Scav.c b/rts/sm/Scav.c
index a28d842..de098d2 100644
--- a/rts/sm/Scav.c
+++ b/rts/sm/Scav.c
@@ -28,6 +28,8 @@
#include "Capability.h"
#include "LdvProfile.h"
+#include "sm/MarkWeak.h"
+
static void scavenge_stack (StgPtr p, StgPtr stack_end);
static void scavenge_large_bitmap (StgPtr p,
@@ -1293,7 +1295,6 @@ scavenge_one(StgPtr p)
case CONSTR_1_1:
case CONSTR_0_2:
case CONSTR_2_0:
- case WEAK:
case PRIM:
case IND_PERM:
{
@@ -1306,6 +1307,10 @@ scavenge_one(StgPtr p)
break;
}
+ case WEAK:
+ scavengeLiveWeak((StgWeak *)p);
+ break;
+
case MUT_VAR_CLEAN:
case MUT_VAR_DIRTY: {
StgPtr q = p;
More information about the ghc-commits
mailing list