32-bit fix
[ghc-hetmet.git] / rts / sm / GC.c
index ee3e170..7c5f99e 100644 (file)
@@ -221,7 +221,7 @@ GarbageCollect (rtsBool force_major_gc,
   /* Approximate how much we allocated.  
    * Todo: only when generating stats? 
    */
-  allocated = calcAllocated();
+  allocated = calcAllocated(rtsFalse/* don't count the nursery yet */);
 
   /* Figure out which generation to collect
    */
@@ -648,7 +648,7 @@ SET_GCT(gc_threads[0]);
         freeChain(gen->large_objects);
         gen->large_objects  = gen->scavenged_large_objects;
         gen->n_large_blocks = gen->n_scavenged_large_blocks;
-       gen->n_new_large_blocks = 0;
+        gen->n_new_large_words = 0;
         ASSERT(countBlocks(gen->large_objects) == gen->n_large_blocks);
     }
     else // for generations > N
@@ -674,10 +674,6 @@ SET_GCT(gc_threads[0]);
   // Calculate the amount of live data for stats.
   live = calcLiveWords();
 
-  // Free the small objects allocated via allocate(), since this will
-  // all have been copied into G0S1 now.  
-  alloc_blocks_lim = RtsFlags.GcFlags.minAllocAreaSize;
-
   // Start a new pinned_object_block
   for (n = 0; n < n_capabilities; n++) {
       capabilities[n].pinned_object_block = NULL;
@@ -699,9 +695,14 @@ SET_GCT(gc_threads[0]);
       }
   }
 
+  // Reset the nursery: make the blocks empty
+  allocated += clearNurseries();
+
   resize_nursery();
 
- // mark the garbage collected CAFs as dead 
+  resetNurseries();
+
+ // mark the garbage collected CAFs as dead
 #if 0 && defined(DEBUG) // doesn't work at the moment 
   if (major_gc) { gcCAFs(); }
 #endif
@@ -724,15 +725,7 @@ SET_GCT(gc_threads[0]);
       }
   }
 
-  // Reset the nursery
-  resetNurseries();
-
-  // start any pending finalizers 
-  RELEASE_SM_LOCK;
-  scheduleFinalizers(cap, old_weak_ptr_list);
-  ACQUIRE_SM_LOCK;
-  
-  // send exceptions to any threads which were about to die 
+  // send exceptions to any threads which were about to die
   RELEASE_SM_LOCK;
   resurrectThreads(resurrected_threads);
   ACQUIRE_SM_LOCK;
@@ -740,6 +733,30 @@ SET_GCT(gc_threads[0]);
   // Update the stable pointer hash table.
   updateStablePtrTable(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();
+
+  // Start any pending finalizers.  Must be after
+  // updateStablePtrTable() and stablePtrPostGC() (see #4221).
+  RELEASE_SM_LOCK;
+  scheduleFinalizers(cap, old_weak_ptr_list);
+  ACQUIRE_SM_LOCK;
+
+  if (major_gc) {
+      nat need, got;
+      need = BLOCKS_TO_MBLOCKS(n_alloc_blocks);
+      got = mblocks_allocated;
+      /* If the amount of data remains constant, next major GC we'll
+         require (F+1)*need. We leave (F+2)*need in order to reduce
+         repeated deallocation and reallocation. */
+      need = (RtsFlags.GcFlags.oldGenFactor + 2) * need;
+      if (got > need) {
+          returnMemoryToOS(got - need);
+      }
+  }
+
   // check sanity after GC
   IF_DEBUG(sanity, checkSanity(rtsTrue));
 
@@ -771,9 +788,6 @@ SET_GCT(gc_threads[0]);
   slop = calcLiveBlocks() * BLOCK_SIZE_W - live;
   stat_endGC(allocated, live, copied, N, max_copied, avg_copied, slop);
 
-  // unlock the StablePtr table
-  stablePtrPostGC();
-
   // Guess which generation we'll collect *next* time
   initialise_N(force_major_gc);
 
@@ -1293,6 +1307,10 @@ init_collected_gen (nat g, nat n_threads)
                 if (!(bd->flags & BF_FRAGMENTED)) {
                     bd->flags |= BF_MARKED;
                 }
+
+                // BF_SWEPT should be marked only for blocks that are being
+                // collected in sweep()
+                bd->flags &= ~BF_SWEPT;
             }
         }
     }