- if (!(g == 0 && s == 0 && RtsFlags.GcFlags.generations > 1)) {
- if (stp->is_compacted)
- {
- // for a compacted step, just shift the new to-space
- // onto the front of the now-compacted existing blocks.
- for (bd = stp->blocks; bd != NULL; bd = bd->link) {
- stp->n_words += bd->free - bd->start;
- }
- // tack the new blocks on the end of the existing blocks
- if (stp->old_blocks != NULL) {
- for (bd = stp->old_blocks; bd != NULL; bd = next) {
- // NB. this step might not be compacted next
- // time, so reset the BF_COMPACTED flags.
- // They are set before GC if we're going to
- // compact. (search for BF_COMPACTED above).
- bd->flags &= ~BF_COMPACTED;
- next = bd->link;
- if (next == NULL) {
- bd->link = stp->blocks;
- }
- }
- stp->blocks = stp->old_blocks;
- }
- // add the new blocks to the block tally
- stp->n_blocks += stp->n_old_blocks;
- ASSERT(countBlocks(stp->blocks) == stp->n_blocks);
- ASSERT(countOccupied(stp->blocks) == stp->n_words);
- }
- else // not copacted
- {
- freeChain(stp->old_blocks);
- }
- stp->old_blocks = NULL;
- stp->n_old_blocks = 0;
- }
-
- /* LARGE OBJECTS. The current live large objects are chained on
- * scavenged_large, having been moved during garbage
- * collection from large_objects. Any objects left on
- * large_objects list are therefore dead, so we free them here.
- */
- for (bd = stp->large_objects; bd != NULL; bd = next) {
- next = bd->link;
- freeGroup(bd);
- bd = next;
- }
-
- stp->large_objects = stp->scavenged_large_objects;
- stp->n_large_blocks = stp->n_scavenged_large_blocks;
+ if (gen->mark)
+ {
+ // 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) {
+ gen->old_blocks = next;
+ } else {
+ prev->link = next;
+ }
+ freeGroup(bd);
+ gen->n_old_blocks--;
+ }
+ 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;
+ }
+ }
+
+ if (prev != NULL) {
+ prev->link = gen->blocks;
+ gen->blocks = gen->old_blocks;
+ }
+ }
+ // add the new blocks to the block tally
+ gen->n_blocks += gen->n_old_blocks;
+ ASSERT(countBlocks(gen->blocks) == gen->n_blocks);
+ ASSERT(countOccupied(gen->blocks) == gen->n_words);
+ }
+ else // not copacted
+ {
+ freeChain(gen->old_blocks);
+ }