[project @ 2001-07-24 16:36:43 by simonmar]
authorsimonmar <unknown>
Tue, 24 Jul 2001 16:36:44 +0000 (16:36 +0000)
committersimonmar <unknown>
Tue, 24 Jul 2001 16:36:44 +0000 (16:36 +0000)
Bugfixes; take large objects into account in stats output.

ghc/includes/StgStorage.h
ghc/rts/GC.c
ghc/rts/Storage.c

index 174898c..3af566d 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: StgStorage.h,v 1.9 2001/07/23 17:23:19 simonmar Exp $
+ * $Id: StgStorage.h,v 1.10 2001/07/24 16:36:44 simonmar Exp $
  *
  * (c) The GHC Team, 1998-1999
  *
  */
 
 typedef struct _step {
-  unsigned int no;             /* step number */
-  bdescr *blocks;              /* blocks in this step */
-  unsigned int n_blocks;       /* number of blocks */
-  struct _step *to;            /* where collected objects from this step go */
-  struct _generation *gen;     /* generation this step belongs to */
-  unsigned int gen_no;          /* generation number (cached) */
-  bdescr *large_objects;       /* large objects (doubly linked) */
-  int is_compacted;             /* compact this step */
+  unsigned int         no;             /* step number */
+  bdescr *             blocks;         /* blocks in this step */
+  unsigned int         n_blocks;       /* number of blocks */
+  struct _step *       to;             /* destination step for live objects */
+  struct _generation * gen;            /* generation this step belongs to */
+  unsigned int         gen_no;          /* generation number (cached) */
+  bdescr *             large_objects;  /* large objects (doubly linked) */
+  unsigned int         n_large_blocks;  /* no. of blocks used by large objs */
+  int                  is_compacted;   /* compact this step? (old gen only) */
 
   /* temporary use during GC: */
-  StgPtr  hp;                  /* next free locn in to-space */
-  StgPtr  hpLim;               /* end of current to-space block */
-  bdescr *hp_bd;               /* bdescr of current to-space block */
-  bdescr *to_blocks;           /* bdescr of first to-space block */
-  unsigned int n_to_blocks;    /* number of blocks in to-space */
-  bdescr *scan_bd;             /* block currently being scanned */
-  StgPtr  scan;                        /* scan pointer in current block */
-  bdescr *new_large_objects;    /* large objects collected so far */
-  bdescr *scavenged_large_objects; /* live large objects after GC (dbl link) */
-  bdescr *bitmap;               /* bitmap for compacting collection */
+  StgPtr       hp;                     /* next free locn in to-space */
+  StgPtr       hpLim;                  /* end of current to-space block */
+  bdescr *     hp_bd;                  /* bdescr of current to-space block */
+  bdescr *     to_blocks;              /* bdescr of first to-space block */
+  unsigned int n_to_blocks;            /* number of blocks in to-space */
+  bdescr *     scan_bd;                        /* block currently being scanned */
+  StgPtr       scan;                   /* scan pointer in current block */
+  bdescr *     new_large_objects;      /* large objects collected so far */
+  bdescr *     scavenged_large_objects; /* live large objs after GC (d-link) */
+  unsigned int n_scavenged_large_blocks;/* size of above */
+  bdescr *     bitmap;                 /* bitmap for compacting collection */
 } step;
 
 typedef struct _generation {
-  unsigned int no;             /* generation number */
-  step *steps;                 /* steps */
-  unsigned int n_steps;                /* number of steps */
-  unsigned int max_blocks;     /* max blocks in step 0 */
-  StgMutClosure *mut_list;      /* mutable objects in this generation (not G0)*/
-  StgMutClosure *mut_once_list; /* objects that point to younger generations */
+  unsigned int   no;                   /* generation number */
+  step *         steps;                        /* steps */
+  unsigned int   n_steps;              /* number of steps */
+  unsigned int   max_blocks;           /* max blocks in step 0 */
+  StgMutClosure *mut_list;             /* mut objects in this gen (not G0)*/
+  StgMutClosure *mut_once_list;        /* objects that point to younger gens */
 
   /* temporary use during GC: */
-  StgMutClosure *saved_mut_list;
+  StgMutClosure * saved_mut_list;
 
   /* stats information */
   unsigned int collections;
index 2f11e8b..624afd6 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: GC.c,v 1.106 2001/07/24 06:31:36 ken Exp $
+ * $Id: GC.c,v 1.107 2001/07/24 16:36:43 simonmar Exp $
  *
  * (c) The GHC Team 1998-1999
  *
@@ -212,6 +212,7 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
   bdescr *bd;
   step *stp;
   lnat live, allocated, collected = 0, copied = 0;
+  lnat oldgen_saved_blocks = 0;
   nat g, s;
 
 #ifdef PROFILING
@@ -248,7 +249,9 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
   } else {
     N = 0;
     for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
-      if (generations[g].steps[0].n_blocks >= generations[g].max_blocks) {
+      if (generations[g].steps[0].n_blocks +
+         generations[g].steps[0].n_large_blocks
+         >= generations[g].max_blocks) {
         N = g;
       }
     }
@@ -325,6 +328,7 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
       stp->scan_bd     = bd;
       stp->new_large_objects = NULL;
       stp->scavenged_large_objects = NULL;
+      stp->n_scavenged_large_blocks = 0;
       new_blocks++;
       // mark the large objects as not evacuated yet 
       for (bd = stp->large_objects; bd; bd = bd->link) {
@@ -390,6 +394,7 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
       stp->n_to_blocks = 0;
       stp->new_large_objects = NULL;
       stp->scavenged_large_objects = NULL;
+      stp->n_scavenged_large_blocks = 0;
     }
   }
 
@@ -588,6 +593,8 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
   // NO MORE EVACUATION AFTER THIS POINT!
   // Finally: compaction of the oldest generation.
   if (major_gc && RtsFlags.GcFlags.compact) { 
+      // save number of blocks for stats
+      oldgen_saved_blocks = oldest_gen->steps[0].n_blocks;
       compact(get_roots);
   }
 
@@ -617,7 +624,12 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
       // for generations we collected... 
       if (g <= N) {
 
-       collected += stp->n_blocks * BLOCK_SIZE_W; // for stats 
+         // rough calculation of garbage collected, for stats output
+         if (stp->is_compacted) {
+             collected += (oldgen_saved_blocks - stp->n_blocks) * BLOCK_SIZE_W;
+         } else {
+             collected += stp->n_blocks * BLOCK_SIZE_W;
+         }
 
        /* free old memory and shift to-space into from-space for all
         * the collected steps (except the allocation area).  These
@@ -665,10 +677,13 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
          freeGroup(bd);
          bd = next;
        }
+
+       // update the count of blocks used by large objects
        for (bd = stp->scavenged_large_objects; bd != NULL; bd = bd->link) {
          bd->flags &= ~BF_EVACUATED;
        }
-       stp->large_objects = stp->scavenged_large_objects;
+       stp->large_objects  = stp->scavenged_large_objects;
+       stp->n_large_blocks = stp->n_scavenged_large_blocks;
 
        /* Set the maximum blocks for this generation, interpolating
         * between the maximum size of the oldest and youngest
@@ -701,10 +716,11 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
 
        // add the new blocks we promoted during this GC 
        stp->n_blocks += stp->n_to_blocks;
+       stp->n_large_blocks += stp->n_scavenged_large_blocks;
       }
     }
   }
-  
+
   /* Set the maximum blocks for the oldest generation, based on twice
    * the amount of live data now, adjusted to fit the maximum heap
    * size if necessary.  
@@ -823,7 +839,7 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
       nat needed = calcNeeded();       // approx blocks needed at next GC 
 
       /* Guess how much will be live in generation 0 step 0 next time.
-       * A good approximation is the obtained by finding the
+       * A good approximation is obtained by finding the
        * percentage of g0s0 that was live at the last minor GC.
        */
       if (N == 0) {
@@ -1135,8 +1151,12 @@ isAlive(StgClosure *p)
        return p;
     }
     // large objects have an evacuated flag
-    if ((bd->flags & BF_LARGE) && (bd->flags & BF_EVACUATED)) {
-       return p;
+    if (bd->flags & BF_LARGE) {
+       if (bd->flags & BF_EVACUATED) {
+           return p;
+       } else {
+           return NULL;
+       }
     }
     // check the mark bit for compacted steps
     if (bd->step->is_compacted && is_marked((P_)p,bd)) {
@@ -2348,6 +2368,7 @@ scavenge_mark_stack(void)
        case CONSTR_2_0:
            ((StgClosure *)p)->payload[1] = evacuate(((StgClosure *)p)->payload[1]);
            ((StgClosure *)p)->payload[0] = evacuate(((StgClosure *)p)->payload[0]);
+           mark(p+1,Bdescr(p));
            break;
        
        case FUN_1_0:
@@ -2358,6 +2379,7 @@ scavenge_mark_stack(void)
        case CONSTR_1_0:
        case CONSTR_1_1:
            ((StgClosure *)p)->payload[0] = evacuate(((StgClosure *)p)->payload[0]);
+           mark(p+1,Bdescr(p));
            break;
        
        case FUN_0_1:
@@ -2367,6 +2389,7 @@ scavenge_mark_stack(void)
            scavenge_srt(info);
        case CONSTR_0_1:
        case CONSTR_0_2:
+           mark(p+1,Bdescr(p));
            break;
        
        case FUN:
@@ -2403,6 +2426,7 @@ scavenge_mark_stack(void)
                recordOldToNewPtrs((StgMutClosure *)p);
            }
            failed_to_evac = rtsFalse;
+           mark(p+1,Bdescr(p));
            break;
 
        case MUT_VAR:
@@ -2410,6 +2434,7 @@ scavenge_mark_stack(void)
            ((StgMutVar *)p)->var = evacuate(((StgMutVar *)p)->var);
            evac_gen = saved_evac_gen;
            failed_to_evac = rtsFalse;
+           mark(p+1,Bdescr(p));
            break;
 
        case MUT_CONS:
@@ -2828,12 +2853,31 @@ scavenge_mutable_list(generation *gen)
        continue;
       }
       
+      // Happens if a MUT_ARR_PTRS in the old generation is frozen
+    case MUT_ARR_PTRS_FROZEN:
+      {
+       StgPtr end, q;
+       
+       evac_gen = gen->no;
+       end = (P_)p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
+       for (q = (P_)((StgMutArrPtrs *)p)->payload; q < end; q++) {
+         (StgClosure *)*q = evacuate((StgClosure *)*q);
+       }
+       evac_gen = 0;
+       p->mut_link = NULL;
+       if (failed_to_evac) {
+           failed_to_evac = rtsFalse;
+           mkMutCons((StgClosure *)p, gen);
+       }
+       continue;
+      }
+       
     case MUT_VAR:
        ((StgMutVar *)p)->var = evacuate(((StgMutVar *)p)->var);
        p->mut_link = gen->mut_list;
        gen->mut_list = p;
        continue;
-      
+
     case MVAR:
       {
        StgMVar *mvar = (StgMVar *)p;
@@ -3266,6 +3310,9 @@ scavenge_large(step *stp)
     stp->new_large_objects = bd->link;
     dbl_link_onto(bd, &stp->scavenged_large_objects);
 
+    // update the block count in this step.
+    stp->n_scavenged_large_blocks += bd->blocks;
+
     p = bd->start;
     info  = get_itbl((StgClosure *)p);
 
index 320a834..1e53758 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: Storage.c,v 1.41 2001/07/23 17:23:20 simonmar Exp $
+ * $Id: Storage.c,v 1.42 2001/07/24 16:36:43 simonmar Exp $
  *
  * (c) The GHC Team, 1998-1999
  *
@@ -605,7 +605,7 @@ calcLive(void)
          continue; 
       }
       stp = &generations[g].steps[s];
-      live += (stp->n_blocks - 1) * BLOCK_SIZE_W;
+      live += (stp->n_large_blocks + stp->n_blocks - 1) * BLOCK_SIZE_W;
       if (stp->hp_bd != NULL) {
          live += ((lnat)stp->hp_bd->free - (lnat)stp->hp_bd->start) 
              / sizeof(W_);
@@ -633,7 +633,9 @@ calcNeeded(void)
     for (s = 0; s < generations[g].n_steps; s++) {
       if (g == 0 && s == 0) { continue; }
       stp = &generations[g].steps[s];
-      if (generations[g].steps[0].n_blocks > generations[g].max_blocks
+      if (generations[g].steps[0].n_blocks +
+         generations[g].steps[0].n_large_blocks 
+         > generations[g].max_blocks
          && stp->is_compacted == 0) {
        needed += 2 * stp->n_blocks;
       } else {
@@ -712,7 +714,7 @@ countBlocks(bdescr *bd)
 {
     nat n;
     for (n=0; bd != NULL; bd=bd->link) {
-       n++;
+       n += bd->blocks;
     }
     return n;
 }
@@ -732,9 +734,11 @@ checkSanity( void )
            for (s = 0; s < generations[g].n_steps; s++) {
                if (g == 0 && s == 0) { continue; }
                checkHeap(generations[g].steps[s].blocks);
+               checkChain(generations[g].steps[s].large_objects);
                ASSERT(countBlocks(generations[g].steps[s].blocks)
                       == generations[g].steps[s].n_blocks);
-               checkChain(generations[g].steps[s].large_objects);
+               ASSERT(countBlocks(generations[g].steps[s].large_objects)
+                      == generations[g].steps[s].n_large_blocks);
                if (g > 0) {
                    checkMutableList(generations[g].mut_list, g);
                    checkMutOnceList(generations[g].mut_once_list, g);