From: simonmar Date: Wed, 22 Oct 2003 15:01:00 +0000 (+0000) Subject: [project @ 2003-10-22 15:00:59 by simonmar] X-Git-Tag: Approx_11550_changesets_converted~338 X-Git-Url: http://git.megacz.com/?a=commitdiff_plain;h=d283bfc1b42cd6cf4a81c56d72a71bb451dfefc6;p=ghc-hetmet.git [project @ 2003-10-22 15:00:59 by simonmar] Fix a nasty bug in the GC mutable list handling, which shows up when an array is frozen and then unsafeThaw#'d. The array could end up on the mutable list twice. Fixes SourceForge bug #819116. --- diff --git a/ghc/rts/GC.c b/ghc/rts/GC.c index f127808..b90461c 100644 --- a/ghc/rts/GC.c +++ b/ghc/rts/GC.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: GC.c,v 1.160 2003/09/23 15:31:02 simonmar Exp $ + * $Id: GC.c,v 1.161 2003/10/22 15:00:59 simonmar Exp $ * * (c) The GHC Team 1998-2003 * @@ -2674,6 +2674,11 @@ scavenge(step *stp) // false, but that breaks some assumptions (eg. every // closure on the mutable list is supposed to have the MUT // flag set, and MUT_ARR_PTRS_FROZEN doesn't). + + // Set the mut_link field to NULL, so that we will put this + // array back on the mutable list if it is subsequently thawed + // by unsafeThaw#. + ((StgMutArrPtrs*)p)->mut_link = NULL; break; } @@ -2980,6 +2985,10 @@ linear_scan: for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) { (StgClosure *)*p = evacuate((StgClosure *)*p); } + // Set the mut_link field to NULL, so that we will put this + // array on the mutable list if it is subsequently thawed + // by unsafeThaw#. + ((StgMutArrPtrs*)p)->mut_link = NULL; break; } @@ -3202,6 +3211,10 @@ scavenge_one(StgPtr p) for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) { (StgClosure *)*p = evacuate((StgClosure *)*p); } + // Set the mut_link field to NULL, so that we will put this + // array on the mutable list if it is subsequently thawed + // by unsafeThaw#. + ((StgMutArrPtrs*)p)->mut_link = NULL; break; } @@ -3406,6 +3419,9 @@ scavenge_mutable_list(generation *gen) (StgClosure *)*q = evacuate((StgClosure *)*q); } evac_gen = 0; + // Set the mut_link field to NULL, so that we will put this + // array back on the mutable list if it is subsequently thawed + // by unsafeThaw#. p->mut_link = NULL; if (failed_to_evac) { failed_to_evac = rtsFalse; diff --git a/ghc/rts/PrimOps.hc b/ghc/rts/PrimOps.hc index 45fd2cf..48f5cac 100644 --- a/ghc/rts/PrimOps.hc +++ b/ghc/rts/PrimOps.hc @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: PrimOps.hc,v 1.114 2003/10/01 10:57:41 wolfgang Exp $ + * $Id: PrimOps.hc,v 1.115 2003/10/22 15:01:00 simonmar Exp $ * * (c) The GHC Team, 1998-2002 * @@ -402,7 +402,22 @@ FN_(unsafeThawArrayzh_fast) { FB_ SET_INFO((StgClosure *)R1.cl,&stg_MUT_ARR_PTRS_info); - recordMutable((StgMutClosure*)R1.cl); + + // SUBTLETY TO DO WITH THE OLD GEN MUTABLE LIST + // + // A MUT_ARR_PTRS lives on the mutable list, but a MUT_ARR_PTRS_FROZEN + // normally doesn't. However, when we freeze a MUT_ARR_PTRS, we leave + // it on the mutable list for the GC to remove (removing something from + // the mutable list is not easy, because the mut_list is only singly-linked). + // + // So, when we thaw a MUT_ARR_PTRS_FROZEN, we must cope with two cases: + // either it is on a mut_list, or it isn't. We adopt the convention that + // the mut_link field is NULL if it isn't on a mut_list, and the GC + // maintains this invariant. + // + if (((StgMutArrPtrs *)R1.cl)->mut_link == NULL) { + recordMutable((StgMutClosure*)R1.cl); + } TICK_RET_UNBOXED_TUP(1); RET_P(R1.p);