/* 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
*/
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
// 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;
}
}
+ // 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
}
}
- // 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;
// 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));
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);
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;
}
}
}