[project @ 1999-11-08 15:30:32 by sewardj]
[ghc-hetmet.git] / ghc / rts / GC.c
index 9bee6b2..02daeec 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: GC.c,v 1.58 1999/05/04 10:19:14 sof Exp $
+ * $Id: GC.c,v 1.65 1999/11/02 15:05:56 simonmar Exp $
  *
  * (c) The GHC Team 1998-1999
  *
@@ -19,7 +19,7 @@
 #include "GC.h"
 #include "BlockAlloc.h"
 #include "Main.h"
-#include "DebugProf.h"
+#include "ProfHeap.h"
 #include "SchedAPI.h"
 #include "Weak.h"
 #include "StablePriv.h"
@@ -162,25 +162,8 @@ void GarbageCollect(void (*get_roots)(void))
   CCCS = CCS_GC;
 #endif
 
-  /* We might have been called from Haskell land by _ccall_GC, in
-   * which case we need to call threadPaused() because the scheduler
-   * won't have done it.
-   */
-  if (CurrentTSO) { threadPaused(CurrentTSO); }
-
-  /* Approximate how much we allocated: number of blocks in the
-   * nursery + blocks allocated via allocate() - unused nusery blocks.
-   * This leaves a little slop at the end of each block, and doesn't
-   * take into account large objects (ToDo).
-   */
-  allocated = (nursery_blocks * BLOCK_SIZE_W) + allocated_bytes();
-  for ( bd = current_nursery->link; bd != NULL; bd = bd->link ) {
-    allocated -= BLOCK_SIZE_W;
-  }
-  if (current_nursery->free < current_nursery->start + BLOCK_SIZE_W) {
-    allocated -= (current_nursery->start + BLOCK_SIZE_W)
-      - current_nursery->free;
-  }
+  /* Approximate how much we allocated */
+  allocated = calcAllocated();
 
   /* Figure out which generation to collect
    */
@@ -334,12 +317,6 @@ void GarbageCollect(void (*get_roots)(void))
   evac_gen = 0;
   get_roots();
 
-  /* And don't forget to mark the TSO if we got here direct from
-   * Haskell! */
-  if (CurrentTSO) {
-    CurrentTSO = (StgTSO *)MarkRoot((StgClosure *)CurrentTSO);
-  }
-
   /* Mark the weak pointer list, and prepare to detect dead weak
    * pointers.
    */
@@ -669,13 +646,7 @@ void GarbageCollect(void (*get_roots)(void))
 
   /* Reset the nursery
    */
-  for (bd = g0s0->blocks; bd; bd = bd->link) {
-    bd->free = bd->start;
-    ASSERT(bd->gen == g0);
-    ASSERT(bd->step == g0s0);
-    IF_DEBUG(sanity,memset(bd->start, 0xaa, BLOCK_SIZE));
-  }
-  current_nursery = g0s0->blocks;
+  resetNurseries();
 
   /* start any pending finalizers */
   scheduleFinalizers(old_weak_ptr_list);
@@ -693,6 +664,7 @@ void GarbageCollect(void (*get_roots)(void))
 
   /* restore enclosing cost centre */
 #ifdef PROFILING
+  heapCensus();
   CCCS = prev_CCS;
 #endif
 
@@ -840,7 +812,7 @@ cleanup_weak_ptr_list ( StgWeak **list )
 StgClosure *
 isAlive(StgClosure *p)
 {
-  StgInfoTable *info;
+  const StgInfoTable *info;
 
   while (1) {
 
@@ -1130,6 +1102,9 @@ loop:
     }
     step = bd->step->to;
   }
+#ifdef DEBUG
+  else step = NULL; /* make sure copy() will crash if HEAP_ALLOCED is wrong */
+#endif
 
   /* make sure the info pointer is into text space */
   ASSERT(q && (LOOKS_LIKE_GHC_INFO(GET_INFO(q))
@@ -1139,7 +1114,18 @@ loop:
   switch (info -> type) {
 
   case BCO:
-    return copy(q,bco_sizeW(stgCast(StgBCO*,q)),step);
+    {
+      nat size = bco_sizeW((StgBCO*)q);
+
+      if (size >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
+       evacuate_large((P_)q, rtsFalse);
+       to = q;
+      } else {
+       /* just copy the block */
+       to = copy(q,size,step);
+      }
+      return to;
+    }
 
   case MUT_VAR:
     ASSERT(q->header.info != &MUT_CONS_info);
@@ -1189,6 +1175,8 @@ loop:
     return copy(q,sizeW_fromITBL(info),step);
 
   case CAF_BLACKHOLE:
+  case SE_CAF_BLACKHOLE:
+  case SE_BLACKHOLE:
   case BLACKHOLE:
     return copyPart(q,BLACKHOLE_sizeW(),sizeofW(StgHeader),step);
 
@@ -1271,13 +1259,16 @@ loop:
        /* aargh - do recursively???? */
       case CAF_UNENTERED:
       case CAF_BLACKHOLE:
+      case SE_CAF_BLACKHOLE:
+      case SE_BLACKHOLE:
       case BLACKHOLE:
       case BLACKHOLE_BQ:
        /* not evaluated yet */
        break;
 
       default:
-       barf("evacuate: THUNK_SELECTOR: strange selectee");
+       barf("evacuate: THUNK_SELECTOR: strange selectee %d",
+            (int)(selectee_info->type));
       }
     }
     return copy(q,THUNK_SELECTOR_sizeW(),step);
@@ -1432,7 +1423,7 @@ loop:
     return q;
 
   default:
-    barf("evacuate: strange closure type");
+    barf("evacuate: strange closure type %d", (int)(info->type));
   }
 
   barf("evacuate");
@@ -1482,7 +1473,7 @@ relocate_TSO(StgTSO *src, StgTSO *dest)
       break;
 
     default:
-      barf("relocate_TSO");
+      barf("relocate_TSO %d", (int)(get_itbl(su)->type));
     }
     break;
   }
@@ -1722,6 +1713,8 @@ scavenge(step *step)
       break;
 
     case CAF_BLACKHOLE:
+    case SE_CAF_BLACKHOLE:
+    case SE_BLACKHOLE:
     case BLACKHOLE:
        p += BLACKHOLE_sizeW();
        break;
@@ -1832,8 +1825,9 @@ scavenge(step *step)
        evac_gen = 0;
        /* chase the link field for any TSOs on the same queue */
        (StgClosure *)tso->link = evacuate((StgClosure *)tso->link);
-       if (tso->blocked_on) {
-         tso->blocked_on = evacuate(tso->blocked_on);
+       if (   tso->why_blocked == BlockedOnMVar
+           || tso->why_blocked == BlockedOnBlackHole) {
+         tso->block_info.closure = evacuate(tso->block_info.closure);
        }
        /* scavenge this thread's stack */
        scavenge_stack(tso->sp, &(tso->stack[tso->stack_size]));
@@ -1875,7 +1869,7 @@ scavenge(step *step)
 static rtsBool
 scavenge_one(StgClosure *p)
 {
-  StgInfoTable *info;
+  const StgInfoTable *info;
   rtsBool no_luck;
 
   ASSERT(p && (LOOKS_LIKE_GHC_INFO(GET_INFO(p))
@@ -1919,6 +1913,8 @@ scavenge_one(StgClosure *p)
     }
 
   case CAF_BLACKHOLE:
+  case SE_CAF_BLACKHOLE:
+  case SE_BLACKHOLE:
   case BLACKHOLE:
       break;
 
@@ -1971,7 +1967,7 @@ scavenge_one(StgClosure *p)
 static void
 scavenge_mut_once_list(generation *gen)
 {
-  StgInfoTable *info;
+  const StgInfoTable *info;
   StgMutClosure *p, *next, *new_list;
 
   p = gen->mut_once_list;
@@ -2091,7 +2087,7 @@ scavenge_mut_once_list(generation *gen)
 
     default:
       /* shouldn't have anything else on the mutables list */
-      barf("scavenge_mut_once_list: strange object?");
+      barf("scavenge_mut_once_list: strange object? %d", (int)(info->type));
     }
   }
 
@@ -2102,7 +2098,7 @@ scavenge_mut_once_list(generation *gen)
 static void
 scavenge_mutable_list(generation *gen)
 {
-  StgInfoTable *info;
+  const StgInfoTable *info;
   StgMutClosure *p, *next;
 
   p = gen->saved_mut_list;
@@ -2183,8 +2179,9 @@ scavenge_mutable_list(generation *gen)
        StgTSO *tso = (StgTSO *)p;
 
        (StgClosure *)tso->link = evacuate((StgClosure *)tso->link);
-       if (tso->blocked_on) {
-         tso->blocked_on = evacuate(tso->blocked_on);
+       if (   tso->why_blocked == BlockedOnMVar
+           || tso->why_blocked == BlockedOnBlackHole) {
+         tso->block_info.closure = evacuate(tso->block_info.closure);
        }
        scavenge_stack(tso->sp, &(tso->stack[tso->stack_size]));
 
@@ -2209,7 +2206,7 @@ scavenge_mutable_list(generation *gen)
 
     default:
       /* shouldn't have anything else on the mutables list */
-      barf("scavenge_mut_list: strange object?");
+      barf("scavenge_mut_list: strange object? %d", (int)(info->type));
     }
   }
 }
@@ -2402,6 +2399,8 @@ scavenge_stack(StgPtr p, StgPtr stack_end)
            recordMutable((StgMutClosure *)to);
            continue;
          default:
+            /* will never be SE_{,CAF_}BLACKHOLE, since we
+               don't push an update frame for single-entry thunks.  KSW 1999-01. */
            barf("scavenge_stack: UPDATE_FRAME updatee");
          }
        }
@@ -2557,8 +2556,9 @@ scavenge_large(step *step)
        tso = (StgTSO *)p;
        /* chase the link field for any TSOs on the same queue */
        (StgClosure *)tso->link = evacuate((StgClosure *)tso->link);
-       if (tso->blocked_on) {
-         tso->blocked_on = evacuate(tso->blocked_on);
+       if (   tso->why_blocked == BlockedOnMVar
+           || tso->why_blocked == BlockedOnBlackHole) {
+         tso->block_info.closure = evacuate(tso->block_info.closure);
        }
        /* scavenge this thread's stack */
        scavenge_stack(tso->sp, &(tso->stack[tso->stack_size]));
@@ -2734,6 +2734,9 @@ threadLazyBlackHole(StgTSO *tso)
 
       if (bh->header.info != &BLACKHOLE_BQ_info &&
          bh->header.info != &CAF_BLACKHOLE_info) {
+#if (!defined(LAZY_BLACKHOLING)) && defined(DEBUG)
+        fprintf(stderr,"Unexpected lazy BHing required at 0x%04x\n",(int)bh);
+#endif
        SET_INFO(bh,&BLACKHOLE_info);
       }
 
@@ -2857,7 +2860,12 @@ threadSqueezeStack(StgTSO *tso)
        * slower --SDM
        */
 #if 0 /* do it properly... */
-      if (GET_INFO(updatee_bypass) == BLACKHOLE_BQ_info) {
+#  if (!defined(LAZY_BLACKHOLING)) && defined(DEBUG)
+#    error Unimplemented lazy BH warning.  (KSW 1999-01)
+#  endif
+      if (GET_INFO(updatee_bypass) == BLACKHOLE_BQ_info
+         || GET_INFO(updatee_bypass) == CAF_BLACKHOLE_info
+         ) {
        /* Sigh.  It has one.  Don't lose those threads! */
          if (GET_INFO(updatee_keep) == BLACKHOLE_BQ_info) {
          /* Urgh.  Two queues.  Merge them. */
@@ -2882,6 +2890,10 @@ threadSqueezeStack(StgTSO *tso)
 #endif
 
       TICK_UPD_SQUEEZED();
+      /* wasn't there something about update squeezing and ticky to be
+       * sorted out?  oh yes: we aren't counting each enter properly
+       * in this case.  See the log somewhere.  KSW 1999-04-21
+       */
       UPD_IND(updatee_bypass, updatee_keep); /* this wakes the threads up */
       
       sp = (P_)frame - 1;      /* sp = stuff to slide */
@@ -2895,8 +2907,12 @@ threadSqueezeStack(StgTSO *tso)
        */
       if (is_update_frame) {
        StgBlockingQueue *bh = (StgBlockingQueue *)frame->updatee;
-       if (bh->header.info != &BLACKHOLE_BQ_info &&
+       if (bh->header.info != &BLACKHOLE_info &&
+           bh->header.info != &BLACKHOLE_BQ_info &&
            bh->header.info != &CAF_BLACKHOLE_info) {
+#if (!defined(LAZY_BLACKHOLING)) && defined(DEBUG)
+          fprintf(stderr,"Unexpected lazy BHing required at 0x%04x\n",(int)bh);
+#endif
          SET_INFO(bh,&BLACKHOLE_info);
        }
       }