Commit d283bfc1 authored by simonmar's avatar simonmar
Browse files

[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.
parent 948e7f38
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* $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 * (c) The GHC Team 1998-2003
* *
...@@ -2674,6 +2674,11 @@ scavenge(step *stp) ...@@ -2674,6 +2674,11 @@ scavenge(step *stp)
// false, but that breaks some assumptions (eg. every // false, but that breaks some assumptions (eg. every
// closure on the mutable list is supposed to have the MUT // closure on the mutable list is supposed to have the MUT
// flag set, and MUT_ARR_PTRS_FROZEN doesn't). // 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; break;
} }
...@@ -2980,6 +2985,10 @@ linear_scan: ...@@ -2980,6 +2985,10 @@ linear_scan:
for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) { for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
(StgClosure *)*p = evacuate((StgClosure *)*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; break;
} }
...@@ -3202,6 +3211,10 @@ scavenge_one(StgPtr p) ...@@ -3202,6 +3211,10 @@ scavenge_one(StgPtr p)
for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) { for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
(StgClosure *)*p = evacuate((StgClosure *)*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; break;
} }
...@@ -3406,6 +3419,9 @@ scavenge_mutable_list(generation *gen) ...@@ -3406,6 +3419,9 @@ scavenge_mutable_list(generation *gen)
(StgClosure *)*q = evacuate((StgClosure *)*q); (StgClosure *)*q = evacuate((StgClosure *)*q);
} }
evac_gen = 0; 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; p->mut_link = NULL;
if (failed_to_evac) { if (failed_to_evac) {
failed_to_evac = rtsFalse; failed_to_evac = rtsFalse;
......
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
* $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 * (c) The GHC Team, 1998-2002
* *
...@@ -402,7 +402,22 @@ FN_(unsafeThawArrayzh_fast) ...@@ -402,7 +402,22 @@ FN_(unsafeThawArrayzh_fast)
{ {
FB_ FB_
SET_INFO((StgClosure *)R1.cl,&stg_MUT_ARR_PTRS_info); 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); TICK_RET_UNBOXED_TUP(1);
RET_P(R1.p); RET_P(R1.p);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment