Merge branch 'master' into atomics
[ghc.git] / rts / sm / GC.c
index f4a479e..8bbdda2 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Documentation on the architecture of the Garbage Collector can be
  * found in the online commentary:
- * 
+ *
  *   http://hackage.haskell.org/trac/ghc/wiki/Commentary/Rts/Storage/GC
  *
  * ---------------------------------------------------------------------------*/
 #include "Prelude.h"
 #include "RtsSignals.h"
 #include "STM.h"
-#if defined(RTS_GTK_FRONTPANEL)
-#include "FrontPanel.h"
-#endif
 #include "Trace.h"
 #include "RetainerProfile.h"
 #include "LdvProfile.h"
 #include "RaiseAsync.h"
 #include "Papi.h"
 #include "Stable.h"
+#include "CheckUnload.h"
 
 #include <string.h> // for memset()
 #include <unistd.h>
  * linking objects on to the list.  We use a stack-type list, consing
  * objects on the front as they are added (this means that the
  * scavenge phase is depth-first, not breadth-first, but that
- * shouldn't matter).  
+ * shouldn't matter).
  *
  * A separate list is kept for objects that have been scavenged
  * already - this is so that we can zero all the marks afterwards.
  *
  * An object is on the list if its static link field is non-zero; this
- * means that we have to mark the end of the list with '1', not NULL.  
+ * means that we have to mark the end of the list with '1', not NULL.
  *
  * Extra notes for generational GC:
  *
@@ -103,7 +101,7 @@ rtsBool major_gc;
 
 /* Data used for allocation area sizing.
  */
-static W_ g0_pcnt_kept = 30; // percentage of g0 live at last minor GC 
+static W_ g0_pcnt_kept = 30; // percentage of g0 live at last minor GC
 
 /* Mut-list stats */
 #ifdef DEBUG
@@ -156,7 +154,7 @@ static StgWord dec_running          (void);
 static void wakeup_gc_threads       (nat me);
 static void shutdown_gc_threads     (nat me);
 static void collect_gct_blocks      (void);
-static StgWord collect_pinned_object_blocks (void);
+static void collect_pinned_object_blocks (void);
 
 #if 0 && defined(DEBUG)
 static void gcCAFs                  (void);
@@ -186,7 +184,7 @@ GarbageCollect (nat collect_gen,
 {
   bdescr *bd;
   generation *gen;
-  StgWord live_blocks, live_words, allocated, par_max_copied, par_tot_copied;
+  StgWord live_blocks, live_words, par_max_copied, par_tot_copied;
 #if defined(THREADED_RTS)
   gc_thread *saved_gct;
 #endif
@@ -216,11 +214,11 @@ GarbageCollect (nat collect_gen,
   // this is the main thread
   SET_GCT(gc_threads[cap->no]);
 
-  // tell the stats department that we've started a GC 
+  // tell the stats department that we've started a GC
   stat_startGC(cap, gct);
 
   // lock the StablePtr table
-  stablePtrPreGC();
+  stableLock();
 
 #ifdef DEBUG
   mutlist_MUTVARS = 0;
@@ -235,7 +233,7 @@ GarbageCollect (nat collect_gen,
   mutlist_OTHERS = 0;
 #endif
 
-  // attribute any costs to CCS_GC 
+  // attribute any costs to CCS_GC
 #ifdef PROFILING
   for (n = 0; n < n_capabilities; n++) {
       save_CCS[n] = capabilities[n].r.rCCCS;
@@ -243,11 +241,6 @@ GarbageCollect (nat collect_gen,
   }
 #endif
 
-  /* Approximate how much we allocated.  
-   * Todo: only when generating stats? 
-   */
-  allocated = countLargeAllocated(); /* don't count the nursery yet */
-
   /* Figure out which generation to collect
    */
   N = collect_gen;
@@ -259,7 +252,7 @@ GarbageCollect (nat collect_gen,
       // It's not always a good idea to do load balancing in parallel
       // GC.  In particular, for a parallel program we don't want to
       // lose locality by moving cached data into another CPU's cache
-      // (this effect can be quite significant). 
+      // (this effect can be quite significant).
       //
       // We could have a more complex way to deterimine whether to do
       // work stealing or not, e.g. it might be a good idea to do it
@@ -288,14 +281,8 @@ GarbageCollect (nat collect_gen,
   debugTrace(DEBUG_gc, "GC (gen %d, using %d thread(s))",
              N, n_gc_threads);
 
-#ifdef RTS_GTK_FRONTPANEL
-  if (RtsFlags.GcFlags.frontpanel) {
-      updateFrontPanelBeforeGC(N);
-  }
-#endif
-
 #ifdef DEBUG
-  // check for memory leaks if DEBUG is on 
+  // check for memory leaks if DEBUG is on
   memInventory(DEBUG_gc);
 #endif
 
@@ -304,7 +291,7 @@ GarbageCollect (nat collect_gen,
 
   // gather blocks allocated using allocatePinned() from each capability
   // and put them on the g0->large_object list.
-  allocated += collect_pinned_object_blocks();
+  collect_pinned_object_blocks();
 
   // Initialise all the generations/steps that we're collecting.
   for (g = 0; g <= N; g++) {
@@ -395,7 +382,7 @@ GarbageCollect (nat collect_gen,
   initWeakForGC();
 
   // Mark the stable pointer table.
-  markStablePtrTable(mark_root, gct);
+  markStableTables(mark_root, gct);
 
   /* -------------------------------------------------------------------------
    * Repeatedly scavenge all the areas we know about until there's no
@@ -406,10 +393,10 @@ GarbageCollect (nat collect_gen,
       scavenge_until_all_done();
       // The other threads are now stopped.  We might recurse back to
       // here, but from now on this is the only thread.
-      
+
       // must be last...  invariant is that everything is fully
       // scavenged at this point.
-      if (traverseWeakPtrList()) { // returns rtsTrue if evaced something 
+      if (traverseWeakPtrList()) { // returns rtsTrue if evaced something
          inc_running();
          continue;
       }
@@ -419,13 +406,13 @@ GarbageCollect (nat collect_gen,
   }
 
   if (!DEBUG_IS_ON && n_gc_threads != 1) {
-      gct->allocated = clearNursery(cap);
+      clearNursery(cap);
   }
 
   shutdown_gc_threads(gct->thread_index);
 
   // Now see which stable names are still alive.
-  gcStablePtrTable();
+  gcStableTables();
 
 #ifdef THREADED_RTS
   if (n_gc_threads == 1) {
@@ -456,7 +443,7 @@ GarbageCollect (nat collect_gen,
 
   // Finally: compact or sweep the oldest generation.
   if (major_gc && oldest_gen->mark) {
-      if (oldest_gen->compact) 
+      if (oldest_gen->compact)
           compact(gct->scavenged_static_objects);
       else
           sweep(oldest_gen);
@@ -465,7 +452,7 @@ GarbageCollect (nat collect_gen,
   copied = 0;
   par_max_copied = 0;
   par_tot_copied = 0;
-  { 
+  {
       nat i;
       for (i=0; i < n_gc_threads; i++) {
           if (n_gc_threads > 1) {
@@ -499,7 +486,7 @@ GarbageCollect (nat collect_gen,
   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
 
     if (g == N) {
-      generations[g].collections++; // for stats 
+      generations[g].collections++; // for stats
       if (n_gc_threads > 1) generations[g].par_collections++;
     }
 
@@ -526,7 +513,7 @@ GarbageCollect (nat collect_gen,
     bdescr *next, *prev;
     gen = &generations[g];
 
-    // for generations we collected... 
+    // for generations we collected...
     if (g <= N) {
 
        /* free old memory and shift to-space into from-space for all
@@ -537,12 +524,12 @@ GarbageCollect (nat collect_gen,
         {
             // tack the new blocks on the end of the existing blocks
             if (gen->old_blocks != NULL) {
-                
+
                 prev = NULL;
                 for (bd = gen->old_blocks; bd != NULL; bd = next) {
-                    
+
                     next = bd->link;
-                    
+
                     if (!(bd->flags & BF_MARKED))
                     {
                         if (prev == NULL) {
@@ -556,17 +543,17 @@ GarbageCollect (nat collect_gen,
                     else
                     {
                         gen->n_words += bd->free - bd->start;
-                        
+
                         // NB. this step might not be compacted next
                         // time, so reset the BF_MARKED flags.
                         // They are set before GC if we're going to
                         // compact.  (search for BF_MARKED above).
                         bd->flags &= ~BF_MARKED;
-                        
+
                         // between GCs, all blocks in the heap except
                         // for the nursery have the BF_EVACUATED flag set.
                         bd->flags |= BF_EVACUATED;
-                        
+
                         prev = bd;
                     }
                 }
@@ -611,8 +598,8 @@ GarbageCollect (nat collect_gen,
             dbl_link_onto(bd, &gen->large_objects);
             gen->n_large_words += bd->free - bd->start;
         }
-        
-       // add the new blocks we promoted during this GC 
+
+       // add the new blocks we promoted during this GC
        gen->n_large_blocks += gen->n_scavenged_large_blocks;
     }
 
@@ -639,7 +626,7 @@ GarbageCollect (nat collect_gen,
 
   // update the max size of older generations after a major GC
   resize_generations();
-  
+
   // Free the mark stack.
   if (mark_stack_top_bd != NULL) {
       debugTrace(DEBUG_gc, "mark stack: %d blocks",
@@ -659,17 +646,14 @@ GarbageCollect (nat collect_gen,
   // Reset the nursery: make the blocks empty
   if (DEBUG_IS_ON || n_gc_threads == 1) {
       for (n = 0; n < n_capabilities; n++) {
-          allocated += clearNursery(&capabilities[n]);
+          clearNursery(&capabilities[n]);
       }
   } else {
       // When doing parallel GC, clearNursery() is called by the
-      // worker threads, and the value returned is stored in
-      // gct->allocated.
+      // worker threads
       for (n = 0; n < n_capabilities; n++) {
           if (gc_threads[n]->idle) {
-              allocated += clearNursery(&capabilities[n]);
-          } else {
-              allocated += gc_threads[n]->allocated;
+              clearNursery(&capabilities[n]);
           }
       }
   }
@@ -678,11 +662,15 @@ GarbageCollect (nat collect_gen,
 
   resetNurseries();
 
+  if (major_gc) {
+      checkUnload (gct->scavenged_static_objects);
+  }
+
  // mark the garbage collected CAFs as dead
-#if 0 && defined(DEBUG) // doesn't work at the moment 
+#if 0 && defined(DEBUG) // doesn't work at the moment
   if (major_gc) { gcCAFs(); }
 #endif
-  
+
 #ifdef PROFILING
   // resetStaticObjectForRetainerProfiling() must be called before
   // zeroing below.
@@ -691,7 +679,7 @@ GarbageCollect (nat collect_gen,
   resetStaticObjectForRetainerProfiling(gct->scavenged_static_objects);
 #endif
 
-  // zero the scavenged static object list 
+  // zero the scavenged static object list
   if (major_gc) {
       nat i;
       if (n_gc_threads == 1) {
@@ -706,17 +694,17 @@ GarbageCollect (nat collect_gen,
   }
 
   // Update the stable pointer hash table.
-  updateStablePtrTable(major_gc);
+  updateStableTables(major_gc);
 
   // unlock the StablePtr table.  Must be before scheduleFinalizers(),
   // because a finalizer may call hs_free_fun_ptr() or
   // hs_free_stable_ptr(), both of which access the StablePtr table.
-  stablePtrPostGC();
+  stableUnlock();
 
   // Start any pending finalizers.  Must be after
-  // updateStablePtrTable() and stablePtrPostGC() (see #4221).
+  // updateStableTables() and stableUnlock() (see #4221).
   RELEASE_SM_LOCK;
-  scheduleFinalizers(cap, old_weak_ptr_list);
+  scheduleFinalizers(cap, dead_weak_ptr_list);
   ACQUIRE_SM_LOCK;
 
   // check sanity after GC
@@ -758,11 +746,11 @@ GarbageCollect (nat collect_gen,
   IF_DEBUG(gc, statDescribeGens());
 
 #ifdef DEBUG
-  // symbol-table based profiling 
+  // symbol-table based profiling
   /*  heapCensus(to_blocks); */ /* ToDo */
 #endif
 
-  // restore enclosing cost centre 
+  // restore enclosing cost centre
 #ifdef PROFILING
   for (n = 0; n < n_capabilities; n++) {
       capabilities[n].r.rCCCS = save_CCS[n];
@@ -770,18 +758,12 @@ GarbageCollect (nat collect_gen,
 #endif
 
 #ifdef DEBUG
-  // check for memory leaks if DEBUG is on 
+  // check for memory leaks if DEBUG is on
   memInventory(DEBUG_gc);
 #endif
 
-#ifdef RTS_GTK_FRONTPANEL
-  if (RtsFlags.GcFlags.frontpanel) {
-      updateFrontPanelAfterGC( N, live );
-  }
-#endif
-
-  // ok, GC over: tell the stats department what happened. 
-  stat_endGC(cap, gct, allocated, live_words, copied,
+  // ok, GC over: tell the stats department what happened.
+  stat_endGC(cap, gct, live_words, copied,
              live_blocks * BLOCK_SIZE_W - live_words /* slop */,
              N, n_gc_threads, par_max_copied, par_tot_copied);
 
@@ -829,7 +811,7 @@ new_gc_thread (nat n, gc_thread *t)
     t->gc_count = 0;
 
     init_gc_thread(t);
-    
+
 #ifdef USE_PAPI
     t->papi_events = -1;
 #endif
@@ -840,7 +822,7 @@ new_gc_thread (nat n, gc_thread *t)
         ws->gen = &generations[g];
         ASSERT(g == ws->gen->no);
         ws->my_gct = t;
-        
+
         // We want to call
         //   alloc_todo_block(ws,0);
         // but can't, because it uses gct which isn't set up at this point.
@@ -942,7 +924,7 @@ static StgWord
 inc_running (void)
 {
     StgWord new;
-    new = atomic_inc(&gc_running_threads);
+    new = atomic_inc(&gc_running_threads, 1);
     ASSERT(new <= n_gc_threads);
     return new;
 }
@@ -968,7 +950,7 @@ any_work (void)
     if (mark_stack_bd != NULL && !mark_stack_empty()) {
        return rtsTrue;
     }
-    
+
     // Check for global work in any step.  We don't need to check for
     // local work, because we have already exited scavenge_loop(),
     // which means there is no local work for this thread.
@@ -999,13 +981,13 @@ any_work (void)
 #endif
 
     return rtsFalse;
-}    
+}
 
 static void
 scavenge_until_all_done (void)
 {
     DEBUG_ONLY( nat r );
-       
+
 
 loop:
 #if defined(THREADED_RTS)
@@ -1031,7 +1013,7 @@ loop:
     traceEventGcIdle(gct->cap);
 
     debugTrace(DEBUG_gc, "%d GC threads still running", r);
-    
+
     while (gc_running_threads != 0) {
         // usleep(1);
         if (any_work()) {
@@ -1041,10 +1023,10 @@ loop:
         }
         // any_work() does not remove the work from the queue, it
         // just checks for the presence of work.  If we find any,
-        // then we increment gc_running_threads and go back to 
+        // then we increment gc_running_threads and go back to
         // scavenge_loop() to perform any pending work.
     }
-    
+
     traceEventGcDone(gct->cap);
 }
 
@@ -1073,7 +1055,7 @@ gcWorkerThread (Capability *cap)
     gct->wakeup = GC_THREAD_STANDING_BY;
     debugTrace(DEBUG_gc, "GC thread %d standing by...", gct->thread_index);
     ACQUIRE_SPIN_LOCK(&gct->gc_spin);
-    
+
 #ifdef USE_PAPI
     // start performance counters in this thread...
     if (gct->papi_events == -1) {
@@ -1092,9 +1074,9 @@ gcWorkerThread (Capability *cap)
     scavenge_capability_mut_lists(cap);
 
     scavenge_until_all_done();
-    
+
     if (!DEBUG_IS_ON) {
-        gct->allocated = clearNursery(cap);
+        clearNursery(cap);
     }
 
 #ifdef THREADED_RTS
@@ -1115,7 +1097,7 @@ gcWorkerThread (Capability *cap)
     // Wait until we're told to continue
     RELEASE_SPIN_LOCK(&gct->gc_spin);
     gct->wakeup = GC_THREAD_WAITING_TO_CONTINUE;
-    debugTrace(DEBUG_gc, "GC thread %d waiting to continue...", 
+    debugTrace(DEBUG_gc, "GC thread %d waiting to continue...",
                gct->thread_index);
     ACQUIRE_SPIN_LOCK(&gct->mut_spin);
     debugTrace(DEBUG_gc, "GC thread %d on my way...", gct->thread_index);
@@ -1221,7 +1203,7 @@ releaseGCThreads (Capability *cap USED_IF_THREADS)
         if (i == me || gc_threads[i]->idle) continue;
         if (gc_threads[i]->wakeup != GC_THREAD_WAITING_TO_CONTINUE)
             barf("releaseGCThreads");
-        
+
         gc_threads[i]->wakeup = GC_THREAD_INACTIVE;
         ACQUIRE_SPIN_LOCK(&gc_threads[i]->gc_spin);
         RELEASE_SPIN_LOCK(&gc_threads[i]->mut_spin);
@@ -1230,7 +1212,7 @@ releaseGCThreads (Capability *cap USED_IF_THREADS)
 #endif
 
 /* ----------------------------------------------------------------------------
-   Initialise a generation that is to be collected 
+   Initialise a generation that is to be collected
    ------------------------------------------------------------------------- */
 
 static void
@@ -1301,7 +1283,7 @@ prepare_collected_gen (generation *gen)
     for (bd = gen->old_blocks; bd; bd = bd->link) {
         bd->flags &= ~BF_EVACUATED;
     }
-    
+
     // mark the large objects as from-space
     for (bd = gen->large_objects; bd; bd = bd->link) {
         bd->flags &= ~BF_EVACUATED;
@@ -1312,7 +1294,7 @@ prepare_collected_gen (generation *gen)
         StgWord bitmap_size; // in bytes
         bdescr *bitmap_bdescr;
         StgWord *bitmap;
-       
+
         bitmap_size = gen->n_old_blocks * BLOCK_SIZE / (sizeof(W_)*BITS_PER_BYTE);
 
         if (bitmap_size > 0) {
@@ -1320,19 +1302,19 @@ prepare_collected_gen (generation *gen)
                                        / BLOCK_SIZE);
             gen->bitmap = bitmap_bdescr;
             bitmap = bitmap_bdescr->start;
-            
+
             debugTrace(DEBUG_gc, "bitmap_size: %d, bitmap: %p",
                        bitmap_size, bitmap);
-            
+
             // don't forget to fill it with zeros!
             memset(bitmap, 0, bitmap_size);
-            
+
             // For each block in this step, point to its bitmap from the
             // block descriptor.
             for (bd=gen->old_blocks; bd != NULL; bd = bd->link) {
                 bd->u.bitmap = bitmap;
                 bitmap += BLOCK_SIZE_W / (sizeof(W_)*BITS_PER_BYTE);
-               
+
                 // Also at this point we set the BF_MARKED flag
                 // for this block.  The invariant is that
                 // BF_MARKED is always unset, except during GC
@@ -1363,7 +1345,7 @@ stash_mut_list (Capability *cap, nat gen_no)
 }
 
 /* ----------------------------------------------------------------------------
-   Initialise a generation that is *not* to be collected 
+   Initialise a generation that is *not* to be collected
    ------------------------------------------------------------------------- */
 
 static void
@@ -1396,10 +1378,10 @@ collect_gct_blocks (void)
     nat g;
     gen_workspace *ws;
     bdescr *bd, *prev;
-    
+
     for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
         ws = &gct->gens[g];
-        
+
         // there may still be a block attached to ws->todo_bd;
         // leave it there to use next time.
 
@@ -1408,7 +1390,7 @@ collect_gct_blocks (void)
 
             ASSERT(gct->scan_bd == NULL);
             ASSERT(countBlocks(ws->scavd_list) == ws->n_scavd_blocks);
-        
+
             prev = NULL;
             for (bd = ws->scavd_list; bd != NULL; bd = bd->link) {
                 ws->gen->n_words += bd->free - bd->start;
@@ -1417,7 +1399,7 @@ collect_gct_blocks (void)
             if (prev != NULL) {
                 prev->link = ws->gen->blocks;
                 ws->gen->blocks = ws->scavd_list;
-            } 
+            }
             ws->gen->n_blocks += ws->n_scavd_blocks;
 
             ws->scavd_list = NULL;
@@ -1439,17 +1421,15 @@ collect_gct_blocks (void)
    purposes.
    -------------------------------------------------------------------------- */
 
-static StgWord
+static void
 collect_pinned_object_blocks (void)
 {
     nat n;
     bdescr *bd, *prev;
-    StgWord allocated = 0;
 
     for (n = 0; n < n_capabilities; n++) {
         prev = NULL;
         for (bd = capabilities[n].pinned_object_blocks; bd != NULL; bd = bd->link) {
-            allocated += bd->free - bd->start;
             prev = bd;
         }
         if (prev != NULL) {
@@ -1461,8 +1441,6 @@ collect_pinned_object_blocks (void)
             capabilities[n].pinned_object_blocks = 0;
         }
     }
-
-    return allocated;
 }
 
 /* -----------------------------------------------------------------------------
@@ -1480,7 +1458,6 @@ init_gc_thread (gc_thread *t)
     t->failed_to_evac = rtsFalse;
     t->eager_promotion = rtsTrue;
     t->thunk_selector_depth = 0;
-    t->allocated = 0;
     t->copied = 0;
     t->scanned = 0;
     t->any_work = 0;
@@ -1505,9 +1482,9 @@ mark_root(void *user USED_IF_THREADS, StgClosure **root)
     saved_gct = gct;
 #endif
     SET_GCT(user);
-    
+
     evacuate(root);
-    
+
     SET_GCT(saved_gct);
 }
 
@@ -1532,7 +1509,7 @@ zero_static_object_list(StgClosure* first_static)
 /* ----------------------------------------------------------------------------
    Reset the sizes of the older generations when we do a major
    collection.
-  
+
    CURRENT STRATEGY: make all generations except zero the same size.
    We have to stay within the maximum heap size, and leave a certain
    percentage of the maximum heap size available to allocate into.
@@ -1547,7 +1524,7 @@ resize_generations (void)
         W_ live, size, min_alloc, words;
         const W_ max  = RtsFlags.GcFlags.maxHeapSize;
         const W_ gens = RtsFlags.GcFlags.generations;
-       
+
        // live in the oldest generations
         if (oldest_gen->live_estimate != 0) {
             words = oldest_gen->live_estimate;
@@ -1556,11 +1533,11 @@ resize_generations (void)
         }
         live = (words + BLOCK_SIZE_W - 1) / BLOCK_SIZE_W +
             oldest_gen->n_large_blocks;
-       
+
        // default max size for all generations except zero
        size = stg_max(live * RtsFlags.GcFlags.oldGenFactor,
                       RtsFlags.GcFlags.minOldGenSize);
-       
+
         if (RtsFlags.GcFlags.heapSizeSuggestionAuto) {
             if (max > 0) {
                 RtsFlags.GcFlags.heapSizeSuggestion = stg_min(max, size);
@@ -1577,7 +1554,7 @@ resize_generations (void)
        // certain percentage of the maximum heap size (default: 30%).
        if (RtsFlags.GcFlags.compact ||
             (max > 0 &&
-             oldest_gen->n_blocks > 
+             oldest_gen->n_blocks >
              (RtsFlags.GcFlags.compactThreshold * max) / 100)) {
            oldest_gen->mark = 1;
            oldest_gen->compact = 1;
@@ -1597,14 +1574,14 @@ resize_generations (void)
        // different if compaction is turned on, because we don't need
        // to double the space required to collect the old generation.
        if (max != 0) {
-           
+
            // this test is necessary to ensure that the calculations
            // below don't have any negative results - we're working
            // with unsigned values here.
            if (max < min_alloc) {
                heapOverflow();
            }
-           
+
            if (oldest_gen->compact) {
                if ( (size + (size - 1) * (gens - 2) * 2) + min_alloc > max ) {
                    size = (max - min_alloc) / ((gens - 1) * 2 - 1);
@@ -1614,17 +1591,17 @@ resize_generations (void)
                    size = (max - min_alloc) / ((gens - 1) * 2);
                }
            }
-           
+
            if (size < live) {
                heapOverflow();
            }
        }
-       
+
 #if 0
        debugBelch("live: %d, min_alloc: %d, size : %d, max = %d\n", live,
                   min_alloc, size, max);
 #endif
-       
+
        for (g = 0; g < gens; g++) {
            generations[g].max_blocks = size;
        }
@@ -1643,7 +1620,7 @@ resize_nursery (void)
     if (RtsFlags.GcFlags.generations == 1)
     {   // Two-space collector:
         W_ blocks;
-    
+
        /* set up a new nursery.  Allocate a nursery size based on a
         * function of the amount of live data (by default a factor of 2)
         * Use the blocks from the old nursery if possible, freeing up any
@@ -1653,25 +1630,25 @@ resize_nursery (void)
         * size accordingly.  If the nursery is the same size as the live
         * data (L), then we need 3L bytes.  We can reduce the size of the
         * nursery to bring the required memory down near 2L bytes.
-        * 
+        *
         * A normal 2-space collector would need 4L bytes to give the same
         * performance we get from 3L bytes, reducing to the same
         * performance at 2L bytes.
         */
        blocks = generations[0].n_blocks;
-       
+
        if ( RtsFlags.GcFlags.maxHeapSize != 0 &&
-            blocks * RtsFlags.GcFlags.oldGenFactor * 2 > 
+            blocks * RtsFlags.GcFlags.oldGenFactor * 2 >
             RtsFlags.GcFlags.maxHeapSize )
        {
-           long adjusted_blocks;  // signed on purpose 
-           int pc_free; 
-           
+           long adjusted_blocks;  // signed on purpose
+           int pc_free;
+
            adjusted_blocks = (RtsFlags.GcFlags.maxHeapSize - 2 * blocks);
-           
-           debugTrace(DEBUG_gc, "near maximum heap size of 0x%x blocks, blocks = %d, adjusted to %ld", 
+
+           debugTrace(DEBUG_gc, "near maximum heap size of 0x%x blocks, blocks = %d, adjusted to %ld",
                       RtsFlags.GcFlags.maxHeapSize, blocks, adjusted_blocks);
-           
+
            pc_free = adjusted_blocks * 100 / RtsFlags.GcFlags.maxHeapSize;
            if (pc_free < RtsFlags.GcFlags.pcFreeHeap) /* might even * be < 0 */
            {
@@ -1691,7 +1668,7 @@ resize_nursery (void)
     }
     else  // Generational collector
     {
-       /* 
+       /*
         * If the user has given us a suggested heap size, adjust our
         * allocation area to make best use of the memory available.
         */
@@ -1701,7 +1678,7 @@ resize_nursery (void)
             StgWord needed;
 
             calcNeeded(rtsFalse, &needed); // approx blocks needed at next GC
-           
+
            /* Guess how much will be live in generation 0 step 0 next time.
             * A good approximation is obtained by finding the
             * percentage of g0 that was live at the last minor GC.
@@ -1716,7 +1693,7 @@ resize_nursery (void)
                g0_pcnt_kept = ((copied / (BLOCK_SIZE_W - 10)) * 100)
                    / countNurseryBlocks();
            }
-           
+
            /* Estimate a size for the allocation area based on the
             * information available.  We might end up going slightly under
             * or over the suggested heap size, but we should be pretty
@@ -1729,14 +1706,14 @@ resize_nursery (void)
             * where 'needed' is the amount of memory needed at the next
             * collection for collecting all gens except g0.
             */
-           blocks = 
+           blocks =
                (((long)RtsFlags.GcFlags.heapSizeSuggestion - (long)needed) * 100) /
                (100 + (long)g0_pcnt_kept);
-           
+
            if (blocks < (long)min_nursery) {
                blocks = min_nursery;
            }
-           
+
             resizeNurseries((W_)blocks);
        }
        else
@@ -1757,7 +1734,7 @@ resize_nursery (void)
    whenever the program tries to enter a garbage collected CAF.
 
    Any garbage collected CAFs are taken off the CAF list at the same
-   time. 
+   time.
    -------------------------------------------------------------------------- */
 
 #if 0 && defined(DEBUG)
@@ -1775,14 +1752,14 @@ gcCAFs(void)
   pp = &caf_list;
 
   while (p != NULL) {
-    
+
     info = get_itbl(p);
 
     ASSERT(info->type == IND_STATIC);
 
     if (STATIC_LINK(info,p) == NULL) {
        debugTrace(DEBUG_gccafs, "CAF gc'd at 0x%04lx", (long)p);
-       // black hole it 
+       // black hole it
        SET_INFO(p,&stg_BLACKHOLE_info);
        p = STATIC_LINK2(info,p);
        *pp = p;
@@ -1795,6 +1772,6 @@ gcCAFs(void)
 
   }
 
-  debugTrace(DEBUG_gccafs, "%d CAFs live", i); 
+  debugTrace(DEBUG_gccafs, "%d CAFs live", i);
 }
 #endif