[project @ 1999-03-02 19:50:12 by sof]
[ghc-hetmet.git] / ghc / rts / GC.c
index 4ea3694..64108c9 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: GC.c,v 1.39 1999/02/24 16:25:40 simonm Exp $
+ * $Id: GC.c,v 1.45 1999/02/26 17:46:08 simonm Exp $
  *
  * (c) The GHC Team 1998-1999
  *
@@ -100,21 +100,23 @@ lnat g0s0_pcnt_kept = 30; /* percentage of g0s0 live at last minor GC */
    Static function declarations
    -------------------------------------------------------------------------- */
 
-static StgClosure *evacuate(StgClosure *q);
-static void    zeroStaticObjectList(StgClosure* first_static);
-static rtsBool traverse_weak_ptr_list(void);
-static void    zeroMutableList(StgMutClosure *first);
-static void    revertDeadCAFs(void);
+static StgClosure * evacuate                ( StgClosure *q );
+static void         zero_static_object_list ( StgClosure* first_static );
+static void         zero_mutable_list       ( StgMutClosure *first );
+static void         revert_dead_CAFs        ( void );
 
-static void           scavenge_stack(StgPtr p, StgPtr stack_end);
-static void           scavenge_large(step *step);
-static void           scavenge(step *step);
-static void           scavenge_static(void);
-static void           scavenge_mutable_list(generation *g);
-static void           scavenge_mut_once_list(generation *g);
+static rtsBool      traverse_weak_ptr_list  ( void );
+static void         cleanup_weak_ptr_list   ( void );
+
+static void         scavenge_stack          ( StgPtr p, StgPtr stack_end );
+static void         scavenge_large          ( step *step );
+static void         scavenge                ( step *step );
+static void         scavenge_static         ( void );
+static void         scavenge_mutable_list   ( generation *g );
+static void         scavenge_mut_once_list  ( generation *g );
 
 #ifdef DEBUG
-static void gcCAFs(void);
+static void         gcCAFs                  ( void );
 #endif
 
 /* -----------------------------------------------------------------------------
@@ -196,10 +198,10 @@ void GarbageCollect(void (*get_roots)(void))
   scavenged_static_objects = END_OF_STATIC_LIST;
 
   /* zero the mutable list for the oldest generation (see comment by
-   * zeroMutableList below).
+   * zero_mutable_list below).
    */
   if (major_gc) { 
-    zeroMutableList(generations[RtsFlags.GcFlags.generations-1].mut_once_list);
+    zero_mutable_list(generations[RtsFlags.GcFlags.generations-1].mut_once_list);
   }
 
   /* Save the old to-space if we're doing a two-space collection
@@ -337,7 +339,6 @@ void GarbageCollect(void (*get_roots)(void))
   /* Mark the weak pointer list, and prepare to detect dead weak
    * pointers.
    */
-  markWeakList();
   old_weak_ptr_list = weak_ptr_list;
   weak_ptr_list = NULL;
   weak_done = rtsFalse;
@@ -360,7 +361,7 @@ void GarbageCollect(void (*get_roots)(void))
        */
       scavengeEverything();
       /* revert dead CAFs and update enteredCAFs list */
-      revertDeadCAFs();
+      revert_dead_CAFs();
 #endif      
       markHugsObjects();
 #if 0
@@ -427,7 +428,12 @@ void GarbageCollect(void (*get_roots)(void))
     }
   }
 
-  /* Now see which stable names are still alive
+  /* Final traversal of the weak pointer list (see comment by
+   * cleanUpWeakPtrList below).
+   */
+  cleanup_weak_ptr_list();
+
+  /* Now see which stable names are still alive.
    */
   gcStablePtrTable(major_gc);
 
@@ -660,7 +666,7 @@ void GarbageCollect(void (*get_roots)(void))
   }
 
   /* revert dead CAFs and update enteredCAFs list */
-  revertDeadCAFs();
+  revert_dead_CAFs();
   
   /* mark the garbage collected CAFs as dead */
 #ifdef DEBUG
@@ -669,7 +675,7 @@ void GarbageCollect(void (*get_roots)(void))
   
   /* zero the scavenged static object list */
   if (major_gc) {
-    zeroStaticObjectList(scavenged_static_objects);
+    zero_static_object_list(scavenged_static_objects);
   }
 
   /* Reset the nursery
@@ -745,6 +751,27 @@ traverse_weak_ptr_list(void)
   last_w = &old_weak_ptr_list;
   for (w = old_weak_ptr_list; w; w = next_w) {
 
+    /* First, this weak pointer might have been evacuated.  If so,
+     * remove the forwarding pointer from the weak_ptr_list.
+     */
+    if (get_itbl(w)->type == EVACUATED) {
+      w = (StgWeak *)((StgEvacuated *)w)->evacuee;
+      *last_w = w;
+    }
+
+    /* There might be a DEAD_WEAK on the list if finalizeWeak# was
+     * called on a live weak pointer object.  Just remove it.
+     */
+    if (w->header.info == &DEAD_WEAK_info) {
+      next_w = ((StgDeadWeak *)w)->link;
+      *last_w = next_w;
+      continue;
+    }
+
+    ASSERT(get_itbl(w)->type == WEAK);
+
+    /* Now, check whether the key is reachable.
+     */
     if ((new = isAlive(w->key))) {
       w->key = new;
       /* evacuate the value and finalizer */
@@ -783,6 +810,39 @@ traverse_weak_ptr_list(void)
 }
 
 /* -----------------------------------------------------------------------------
+   After GC, the live weak pointer list may have forwarding pointers
+   on it, because a weak pointer object was evacuated after being
+   moved to the live weak pointer list.  We remove those forwarding
+   pointers here.
+
+   Also, we don't consider weak pointer objects to be reachable, but
+   we must nevertheless consider them to be "live" and retain them.
+   Therefore any weak pointer objects which haven't as yet been
+   evacuated need to be evacuated now.
+   -------------------------------------------------------------------------- */
+
+static void
+cleanup_weak_ptr_list ( void )
+{
+  StgWeak *w, **last_w;
+
+  last_w = &weak_ptr_list;
+  for (w = weak_ptr_list; w; w = w->link) {
+
+    if (get_itbl(w)->type == EVACUATED) {
+      w = (StgWeak *)((StgEvacuated *)w)->evacuee;
+      *last_w = w;
+    }
+
+    if (Bdescr((P_)w)->evacuated == 0) {
+      (StgClosure *)w = evacuate((StgClosure *)w);
+      *last_w = w;
+    }
+    last_w = &(w->link);
+  }
+}
+
+/* -----------------------------------------------------------------------------
    isAlive determines whether the given closure is still alive (after
    a garbage collection) or not.  It returns the new address of the
    closure if it is alive, or NULL otherwise.
@@ -856,6 +916,13 @@ static void addBlock(step *step)
   new_blocks++;
 }
 
+static __inline__ void 
+upd_evacuee(StgClosure *p, StgClosure *dest)
+{
+  p->header.info = &EVACUATED_info;
+  ((StgEvacuated *)p)->evacuee = dest;
+}
+
 static __inline__ StgClosure *
 copy(StgClosure *src, nat size, step *step)
 {
@@ -868,7 +935,11 @@ copy(StgClosure *src, nat size, step *step)
    * by evacuate()).
    */
   if (step->gen->no < evac_gen) {
+#ifdef NO_EAGER_PROMOTION    
+    failed_to_evac = rtsTrue;
+#else
     step = &generations[evac_gen].steps[0];
+#endif
   }
 
   /* chain a new block onto the to-space for the destination step if
@@ -884,6 +955,7 @@ copy(StgClosure *src, nat size, step *step)
 
   dest = step->hp;
   step->hp = to;
+  upd_evacuee(src,(StgClosure *)dest);
   return (StgClosure *)dest;
 }
 
@@ -899,7 +971,11 @@ copyPart(StgClosure *src, nat size_to_reserve, nat size_to_copy, step *step)
 
   TICK_GC_WORDS_COPIED(size_to_copy);
   if (step->gen->no < evac_gen) {
+#ifdef NO_EAGER_PROMOTION    
+    failed_to_evac = rtsTrue;
+#else
     step = &generations[evac_gen].steps[0];
+#endif
   }
 
   if (step->hp + size_to_reserve >= step->hpLim) {
@@ -912,18 +988,10 @@ copyPart(StgClosure *src, nat size_to_reserve, nat size_to_copy, step *step)
   
   dest = step->hp;
   step->hp += size_to_reserve;
+  upd_evacuee(src,(StgClosure *)dest);
   return (StgClosure *)dest;
 }
 
-static __inline__ void 
-upd_evacuee(StgClosure *p, StgClosure *dest)
-{
-  StgEvacuated *q = (StgEvacuated *)p;
-
-  SET_INFO(q,&EVACUATED_info);
-  q->evacuee = dest;
-}
-
 /* -----------------------------------------------------------------------------
    Evacuate a large object
 
@@ -971,7 +1039,11 @@ evacuate_large(StgPtr p, rtsBool mutable)
    */
   step = bd->step->to;
   if (step->gen->no < evac_gen) {
+#ifdef NO_EAGER_PROMOTION    
+    failed_to_evac = rtsTrue;
+#else
     step = &generations[evac_gen].steps[0];
+#endif
   }
 
   bd->step = step;
@@ -1078,46 +1150,42 @@ loop:
   switch (info -> type) {
 
   case BCO:
-    to = copy(q,bco_sizeW(stgCast(StgBCO*,q)),step);
-    upd_evacuee(q,to);
-    return to;
+    return copy(q,bco_sizeW(stgCast(StgBCO*,q)),step);
 
   case MUT_VAR:
     ASSERT(q->header.info != &MUT_CONS_info);
   case MVAR:
     to = copy(q,sizeW_fromITBL(info),step);
-    upd_evacuee(q,to);
     recordMutable((StgMutClosure *)to);
     return to;
 
-  case STABLE_NAME:
-    stable_ptr_table[((StgStableName *)q)->sn].keep = rtsTrue;
-    to = copy(q,sizeofW(StgStableName),step);
-    upd_evacuee(q,to);
-    return to;
-
   case FUN_1_0:
   case FUN_0_1:
   case CONSTR_1_0:
   case CONSTR_0_1:
-    to = copy(q,sizeofW(StgHeader)+1,step);
-    upd_evacuee(q,to);
-    return to;
+    return copy(q,sizeofW(StgHeader)+1,step);
 
   case THUNK_1_0:              /* here because of MIN_UPD_SIZE */
   case THUNK_0_1:
-  case FUN_1_1:
-  case FUN_0_2:
-  case FUN_2_0:
   case THUNK_1_1:
   case THUNK_0_2:
   case THUNK_2_0:
+#ifdef NO_PROMOTE_THUNKS
+    if (bd->gen->no == 0 && 
+       bd->step->no != 0 &&
+       bd->step->no == bd->gen->n_steps-1) {
+      step = bd->step;
+    }
+#endif
+    return copy(q,sizeofW(StgHeader)+2,step);
+
+  case FUN_1_1:
+  case FUN_0_2:
+  case FUN_2_0:
   case CONSTR_1_1:
   case CONSTR_0_2:
   case CONSTR_2_0:
-    to = copy(q,sizeofW(StgHeader)+2,step);
-    upd_evacuee(q,to);
-    return to;
+    return copy(q,sizeofW(StgHeader)+2,step);
 
   case FUN:
   case THUNK:
@@ -1128,19 +1196,15 @@ loop:
   case CAF_ENTERED:
   case WEAK:
   case FOREIGN:
-    to = copy(q,sizeW_fromITBL(info),step);
-    upd_evacuee(q,to);
-    return to;
+  case STABLE_NAME:
+    return copy(q,sizeW_fromITBL(info),step);
 
   case CAF_BLACKHOLE:
   case BLACKHOLE:
-    to = copyPart(q,BLACKHOLE_sizeW(),sizeofW(StgHeader),step);
-    upd_evacuee(q,to);
-    return to;
+    return copyPart(q,BLACKHOLE_sizeW(),sizeofW(StgHeader),step);
 
   case BLACKHOLE_BQ:
     to = copy(q,BLACKHOLE_sizeW(),step); 
-    upd_evacuee(q,to);
     recordMutable((StgMutClosure *)to);
     return to;
 
@@ -1227,9 +1291,7 @@ loop:
        barf("evacuate: THUNK_SELECTOR: strange selectee");
       }
     }
-    to = copy(q,THUNK_SELECTOR_sizeW(),step);
-    upd_evacuee(q,to);
-    return to;
+    return copy(q,THUNK_SELECTOR_sizeW(),step);
 
   case IND:
   case IND_OLDGEN:
@@ -1287,9 +1349,7 @@ loop:
   case PAP:
     /* these are special - the payload is a copy of a chunk of stack,
        tagging and all. */
-    to = copy(q,pap_sizeW(stgCast(StgPAP*,q)),step);
-    upd_evacuee(q,to);
-    return to;
+    return copy(q,pap_sizeW(stgCast(StgPAP*,q)),step);
 
   case EVACUATED:
     /* Already evacuated, just return the forwarding address.
@@ -1318,9 +1378,7 @@ loop:
        return q;
       } else {
        /* just copy the block */
-       to = copy(q,size,step);
-       upd_evacuee(q,to);
-       return to;
+       return copy(q,size,step);
       }
     }
 
@@ -1335,7 +1393,6 @@ loop:
       } else {
        /* just copy the block */
        to = copy(q,size,step);
-       upd_evacuee(q,to);
        if (info->type == MUT_ARR_PTRS) {
          recordMutable((StgMutClosure *)to);
        }
@@ -1369,7 +1426,6 @@ loop:
        new_tso->splim = (StgPtr)new_tso->splim + diff;
        
        relocate_TSO(tso, new_tso);
-       upd_evacuee(q,(StgClosure *)new_tso);
 
        recordMutable((StgMutClosure *)new_tso);
        return (StgClosure *)new_tso;
@@ -2247,18 +2303,24 @@ scavenge_stack(StgPtr p, StgPtr stack_end)
            }
            continue;
          }
-         step = bd->step->to;
+
+         /* Don't promote blackholes */
+         step = bd->step;
+         if (!(step->gen->no == 0 && 
+               step->no != 0 &&
+               step->no == step->gen->n_steps-1)) {
+           step = step->to;
+         }
+
          switch (type) {
          case BLACKHOLE:
          case CAF_BLACKHOLE:
            to = copyPart(frame->updatee, BLACKHOLE_sizeW(), 
                          sizeofW(StgHeader), step);
-           upd_evacuee(frame->updatee,to);
            frame->updatee = to;
            continue;
          case BLACKHOLE_BQ:
            to = copy(frame->updatee, BLACKHOLE_sizeW(), step);
-           upd_evacuee(frame->updatee,to);
            frame->updatee = to;
            recordMutable((StgMutClosure *)to);
            continue;
@@ -2430,7 +2492,7 @@ scavenge_large(step *step)
 }
 
 static void
-zeroStaticObjectList(StgClosure* first_static)
+zero_static_object_list(StgClosure* first_static)
 {
   StgClosure* p;
   StgClosure* link;
@@ -2452,7 +2514,7 @@ zeroStaticObjectList(StgClosure* first_static)
  * mutable list.
  */
 static void
-zeroMutableList(StgMutClosure *first)
+zero_mutable_list( StgMutClosure *first )
 {
   StgMutClosure *next, *c;
 
@@ -2479,7 +2541,7 @@ void RevertCAFs(void)
   }
 }
 
-void revertDeadCAFs(void)
+void revert_dead_CAFs(void)
 {
     StgCAF* caf = enteredCAFs;
     enteredCAFs = END_CAF_LIST;
@@ -2503,7 +2565,7 @@ void revertDeadCAFs(void)
                break;
            }
        default:
-               barf("revertDeadCAFs: enteredCAFs list corrupted");
+               barf("revert_dead_CAFs: enteredCAFs list corrupted");
        } 
        caf = next;
     }