[project @ 2003-04-01 15:05:13 by sof]
[ghc-hetmet.git] / ghc / rts / GC.c
index 6e6bd07..8cd4a2c 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: GC.c,v 1.147 2003/02/12 11:59:49 simonmar Exp $
+ * $Id: GC.c,v 1.153 2003/04/01 15:05:13 sof Exp $
  *
  * (c) The GHC Team 1998-2003
  *
@@ -20,7 +20,6 @@
 #include "Sanity.h"
 #include "BlockAlloc.h"
 #include "MBlock.h"
-#include "Main.h"
 #include "ProfHeap.h"
 #include "SchedAPI.h"
 #include "Weak.h"
@@ -140,7 +139,14 @@ static lnat thunk_selector_depth = 0;
 
 static bdescr *     gc_alloc_block          ( step *stp );
 static void         mark_root               ( StgClosure **root );
-static StgClosure * evacuate                ( StgClosure *q );
+
+// Use a register argument for evacuate, if available.
+#if __GNUC__ >= 2
+static StgClosure * evacuate (StgClosure *q) __attribute__((regparm(1)));
+#else
+static StgClosure * evacuate (StgClosure *q);
+#endif
+
 static void         zero_static_object_list ( StgClosure* first_static );
 static void         zero_mutable_list       ( StgMutClosure *first );
 
@@ -304,7 +310,7 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
                     Now, Now));
 #endif
 
-#ifndef mingw32_TARGET_OS
+#if defined(RTS_USER_SIGNALS)
   // block signals
   blockUserSignals();
 #endif
@@ -1081,7 +1087,7 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
   // ok, GC over: tell the stats department what happened. 
   stat_endGC(allocated, collected, live, copied, N);
 
-#ifndef mingw32_TARGET_OS
+#if defined(RTS_USER_SIGNALS)
   // unblock signals again
   unblockUserSignals();
 #endif
@@ -1753,9 +1759,11 @@ loop:
   case WEAK:
   case FOREIGN:
   case STABLE_NAME:
-  case BCO:
     return copy(q,sizeW_fromITBL(info),stp);
 
+  case BCO:
+      return copy(q,bco_sizeW((StgBCO *)q),stp);
+
   case CAF_BLACKHOLE:
   case SE_CAF_BLACKHOLE:
   case SE_BLACKHOLE:
@@ -2001,6 +2009,25 @@ eval_thunk_selector( nat field, StgSelector * p )
 
 selector_loop:
 
+    // We don't want to end up in to-space, because this causes
+    // problems when the GC later tries to evacuate the result of
+    // eval_thunk_selector().  There are various ways this could
+    // happen:
+    //
+    // - following an IND_STATIC
+    //
+    // - when the old generation is compacted, the mark phase updates
+    //   from-space pointers to be to-space pointers, and we can't
+    //   reliably tell which we're following (eg. from an IND_STATIC).
+    // 
+    // So we use the block-descriptor test to find out if we're in
+    // to-space.
+    //
+    if (HEAP_ALLOCED(selectee) &&
+       Bdescr((StgPtr)selectee)->flags & BF_EVACUATED) {
+       goto bale_out;
+    }
+
     info = get_itbl(selectee);
     switch (info->type) {
       case CONSTR:
@@ -2015,12 +2042,15 @@ selector_loop:
          ASSERT(field <  (StgWord32)(info->layout.payload.ptrs + 
                                      info->layout.payload.nptrs));
          
+         // ToDo: shouldn't we test whether this pointer is in
+         // to-space?
          return selectee->payload[field];
 
       case IND:
       case IND_PERM:
       case IND_OLDGEN:
       case IND_OLDGEN_PERM:
+      case IND_STATIC:
          selectee = ((StgInd *)selectee)->indirectee;
          goto selector_loop;
 
@@ -2030,11 +2060,6 @@ selector_loop:
          // leaks by evaluating this selector thunk anyhow.
          break;
 
-      case IND_STATIC:
-         // We can't easily tell whether the indirectee is into 
-         // from or to-space, so just bail out here.
-         break;
-
       case THUNK_SELECTOR:
       {
          StgClosure *val;
@@ -2107,6 +2132,7 @@ selector_loop:
             (int)(info->type));
     }
 
+bale_out:
     // We didn't manage to evaluate this thunk; restore the old info pointer
     SET_INFO(p, info_ptr);
     return NULL;
@@ -2439,7 +2465,6 @@ scavenge(step *stp)
     case WEAK:
     case FOREIGN:
     case STABLE_NAME:
-    case BCO:
     {
        StgPtr end;
 
@@ -2451,6 +2476,16 @@ scavenge(step *stp)
        break;
     }
 
+    case BCO: {
+       StgBCO *bco = (StgBCO *)p;
+       (StgClosure *)bco->instrs = evacuate((StgClosure *)bco->instrs);
+       (StgClosure *)bco->literals = evacuate((StgClosure *)bco->literals);
+       (StgClosure *)bco->ptrs = evacuate((StgClosure *)bco->ptrs);
+       (StgClosure *)bco->itbls = evacuate((StgClosure *)bco->itbls);
+       p += bco_sizeW(bco);
+       break;
+    }
+
     case IND_PERM:
       if (stp->gen->no != 0) {
 #ifdef PROFILING
@@ -2768,7 +2803,6 @@ linear_scan:
        case WEAK:
        case FOREIGN:
        case STABLE_NAME:
-       case BCO:
        {
            StgPtr end;
            
@@ -2779,6 +2813,15 @@ linear_scan:
            break;
        }
 
+       case BCO: {
+           StgBCO *bco = (StgBCO *)p;
+           (StgClosure *)bco->instrs = evacuate((StgClosure *)bco->instrs);
+           (StgClosure *)bco->literals = evacuate((StgClosure *)bco->literals);
+           (StgClosure *)bco->ptrs = evacuate((StgClosure *)bco->ptrs);
+           (StgClosure *)bco->itbls = evacuate((StgClosure *)bco->itbls);
+           break;
+       }
+
        case IND_PERM:
            // don't need to do anything here: the only possible case
            // is that we're in a 1-space compacting collector, with