[project @ 2005-11-07 14:43:34 by simonmar]
authorsimonmar <unknown>
Mon, 7 Nov 2005 14:43:34 +0000 (14:43 +0000)
committersimonmar <unknown>
Mon, 7 Nov 2005 14:43:34 +0000 (14:43 +0000)
Fix some problems with array thawing/freezing and the GC.

ghc/rts/ClosureFlags.c
ghc/rts/GC.c
ghc/rts/PrimOps.cmm

index 8a3d97a..df9ef7b 100644 (file)
@@ -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           ),
index 9a21af8..0399d60 100644 (file)
@@ -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;
     }
 
index 1eaf727..630319f 100644 (file)
@@ -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);
 }
 
 /* -----------------------------------------------------------------------------