Commit 6470f502 authored by simonmar's avatar simonmar

[project @ 2005-11-07 14:43:34 by simonmar]

Fix some problems with array thawing/freezing and the GC.
parent 7aad3eb9
......@@ -78,7 +78,7 @@ StgWord16 closure_flags[] = {
/* MVAR = */ (_HNF| _NS| _MUT|_UPT ),
/* ARR_WORDS = */ (_HNF| _NS| _UPT ),
/* MUT_ARR_PTRS = */ (_HNF| _NS| _MUT|_UPT ),
/* MUT_ARR_PTRS_FROZEN0 = */ (_HNF| _NS| _UPT ),
/* MUT_ARR_PTRS_FROZEN0 = */ (_HNF| _NS| _MUT|_UPT ),
/* MUT_ARR_PTRS_FROZEN = */ (_HNF| _NS| _UPT ),
/* MUT_VAR = */ (_HNF| _NS| _MUT|_UPT ),
/* WEAK = */ (_HNF| _NS| _UPT ),
......
......@@ -2953,10 +2953,14 @@ scavenge(step *stp)
for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
*p = (StgWord)(StgPtr)evacuate((StgClosure *)*p);
}
// it's tempting to recordMutable() if failed_to_evac is
// 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).
// If we're going to put this object on the mutable list, then
// set its info ptr to MUT_ARR_PTRS_FROZEN0 to indicate that.
if (failed_to_evac) {
((StgClosure *)q)->header.info = &stg_MUT_ARR_PTRS_FROZEN0_info;
} else {
((StgClosure *)q)->header.info = &stg_MUT_ARR_PTRS_FROZEN_info;
}
break;
}
......@@ -3307,12 +3311,20 @@ linear_scan:
case MUT_ARR_PTRS_FROZEN0:
// follow everything
{
StgPtr next;
StgPtr next, q = p;
next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
*p = (StgWord)(StgPtr)evacuate((StgClosure *)*p);
}
// If we're going to put this object on the mutable list, then
// set its info ptr to MUT_ARR_PTRS_FROZEN0 to indicate that.
if (failed_to_evac) {
((StgClosure *)q)->header.info = &stg_MUT_ARR_PTRS_FROZEN0_info;
} else {
((StgClosure *)q)->header.info = &stg_MUT_ARR_PTRS_FROZEN_info;
}
break;
}
......@@ -3621,12 +3633,20 @@ scavenge_one(StgPtr p)
case MUT_ARR_PTRS_FROZEN0:
{
// follow everything
StgPtr next;
StgPtr next, q=p;
next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
*p = (StgWord)(StgPtr)evacuate((StgClosure *)*p);
}
// If we're going to put this object on the mutable list, then
// set its info ptr to MUT_ARR_PTRS_FROZEN0 to indicate that.
if (failed_to_evac) {
((StgClosure *)q)->header.info = &stg_MUT_ARR_PTRS_FROZEN0_info;
} else {
((StgClosure *)q)->header.info = &stg_MUT_ARR_PTRS_FROZEN_info;
}
break;
}
......
......@@ -126,21 +126,25 @@ unsafeThawArrayzh_fast
// the mutable list is not easy, because the mut_list is only singly-linked).
//
// So that we can tell whether a MUT_ARR_PTRS_FROZEN is on the mutable list,
// when we freeze it we set the info ptr to be MUT_ARR_PTRS_FROZEN0 to indicate
// that it is still on the mutable list.
// when we freeze it we set the info ptr to be MUT_ARR_PTRS_FROZEN0
// to indicate that it is still on the mutable list.
//
// 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 closure type is MUT_ARR_PTRS_FROZEN0 if it is on the mutable list,
// and MUT_ARR_PTRS_FROZEN otherwise.
// and MUT_ARR_PTRS_FROZEN otherwise. In fact it wouldn't matter if
// we put it on the mutable list more than once, but it would get scavenged
// multiple times during GC, which would be unnecessarily slow.
//
if (%INFO_TYPE(%GET_STD_INFO(R1)) != HALF_W_(MUT_ARR_PTRS_FROZEN0)) {
if (StgHeader_info(R1) != stg_MUT_ARR_PTRS_FROZEN0_info) {
SET_INFO(R1,stg_MUT_ARR_PTRS_info);
foreign "C" recordMutableLock(R1 "ptr") [R1];
// must be done after SET_INFO, because it ASSERTs closure_MUTABLE()
RET_P(R1);
} else {
SET_INFO(R1,stg_MUT_ARR_PTRS_info);
RET_P(R1);
}
SET_INFO(R1,stg_MUT_ARR_PTRS_info);
RET_P(R1);
}
/* -----------------------------------------------------------------------------
......
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