/* -----------------------------------------------------------------------------
- * $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
*
bdescr *bd;
step *stp;
lnat live, allocated, collected = 0, copied = 0;
+ lnat oldgen_saved_blocks = 0;
nat g, s;
#ifdef PROFILING
} 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;
}
}
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) {
stp->n_to_blocks = 0;
stp->new_large_objects = NULL;
stp->scavenged_large_objects = NULL;
+ stp->n_scavenged_large_blocks = 0;
}
}
// 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);
}
// 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
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
// 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.
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) {
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)) {
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:
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:
scavenge_srt(info);
case CONSTR_0_1:
case CONSTR_0_2:
+ mark(p+1,Bdescr(p));
break;
case FUN:
recordOldToNewPtrs((StgMutClosure *)p);
}
failed_to_evac = rtsFalse;
+ mark(p+1,Bdescr(p));
break;
case MUT_VAR:
((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:
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;
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);