summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2010-03-19 11:21:27 +0000
committerSimon Marlow <marlowsd@gmail.com>2010-03-19 11:21:27 +0000
commitf7d332b49c893d22c9a583e65b196189b016031c (patch)
treeb25819262d6b51af6686b106fa4e0f93c3f600f3
parent523ecf30d28c4a42090e59dfab5d05c1db9deaef (diff)
downloadhaskell-f7d332b49c893d22c9a583e65b196189b016031c.tar.gz
slight improvement to scavenging of update frames when a collision has occurred
-rw-r--r--rts/sm/Scav.c36
1 files changed, 16 insertions, 20 deletions
diff --git a/rts/sm/Scav.c b/rts/sm/Scav.c
index 1b671a097c..29a69950a3 100644
--- a/rts/sm/Scav.c
+++ b/rts/sm/Scav.c
@@ -1575,11 +1575,13 @@ scavenge_stack(StgPtr p, StgPtr stack_end)
// threadPaused(). We could traverse the whole stack again
// before GC, but that seems like overkill.
//
- // Scavenging this update frame as normal would be disastrous;
- // the updatee would end up pointing to the value. So we turn
- // the indirection into an IND_PERM, so that evacuate will
- // copy the indirection into the old generation instead of
- // discarding it.
+ // So, if the frame points to an indirection, it will get
+ // shorted out when we evacuate. If this happens, we have no
+ // closure to update any more. In the past we solved this by
+ // replacing the IND with an IND_PERM, but a better solution
+ // is to replace the update frame with a frame that no longer
+ // does the update and just uses the value already computed by
+ // the other thread, so that is what we now do.
//
// Note [upd-black-hole]
// One slight hiccup is that the THUNK_SELECTOR machinery can
@@ -1590,22 +1592,16 @@ scavenge_stack(StgPtr p, StgPtr stack_end)
// the updatee is never a THUNK_SELECTOR and we're ok.
// NB. this is a new invariant: blackholing is not optional.
{
- nat type;
- const StgInfoTable *i;
- StgClosure *updatee;
-
- updatee = ((StgUpdateFrame *)p)->updatee;
- i = updatee->header.info;
- if (!IS_FORWARDING_PTR(i)) {
- type = get_itbl(updatee)->type;
- if (type == IND) {
- updatee->header.info = &stg_IND_PERM_info;
- } else if (type == IND_OLDGEN) {
- updatee->header.info = &stg_IND_OLDGEN_PERM_info;
- }
+ StgClosure *v;
+ StgUpdateFrame *frame = (StgUpdateFrame *)p;
+
+ evacuate(&frame->updatee);
+ v = frame->updatee;
+ if (GET_CLOSURE_TAG(v) != 0 ||
+ (get_itbl(v)->type != BLACKHOLE &&
+ get_itbl(v)->type != CAF_BLACKHOLE)) {
+ frame->header.info = (const StgInfoTable*)&stg_gc_unpt_r1_info;
}
- evacuate(&((StgUpdateFrame *)p)->updatee);
- ASSERT(GET_CLOSURE_TAG(((StgUpdateFrame *)p)->updatee) == 0);
p += sizeofW(StgUpdateFrame);
continue;
}