Commit 76a51a41 authored by simonmar's avatar simonmar
Browse files

[project @ 2001-07-24 16:36:43 by simonmar]

Bugfixes; take large objects into account in stats output.
parent 9acd03bd
/* -----------------------------------------------------------------------------
* $Id: StgStorage.h,v 1.9 2001/07/23 17:23:19 simonmar Exp $
* $Id: StgStorage.h,v 1.10 2001/07/24 16:36:44 simonmar Exp $
*
* (c) The GHC Team, 1998-1999
*
......@@ -48,38 +48,40 @@
*/
typedef struct _step {
unsigned int no; /* step number */
bdescr *blocks; /* blocks in this step */
unsigned int n_blocks; /* number of blocks */
struct _step *to; /* where collected objects from this step go */
struct _generation *gen; /* generation this step belongs to */
unsigned int gen_no; /* generation number (cached) */
bdescr *large_objects; /* large objects (doubly linked) */
int is_compacted; /* compact this step */
unsigned int no; /* step number */
bdescr * blocks; /* blocks in this step */
unsigned int n_blocks; /* number of blocks */
struct _step * to; /* destination step for live objects */
struct _generation * gen; /* generation this step belongs to */
unsigned int gen_no; /* generation number (cached) */
bdescr * large_objects; /* large objects (doubly linked) */
unsigned int n_large_blocks; /* no. of blocks used by large objs */
int is_compacted; /* compact this step? (old gen only) */
/* temporary use during GC: */
StgPtr hp; /* next free locn in to-space */
StgPtr hpLim; /* end of current to-space block */
bdescr *hp_bd; /* bdescr of current to-space block */
bdescr *to_blocks; /* bdescr of first to-space block */
unsigned int n_to_blocks; /* number of blocks in to-space */
bdescr *scan_bd; /* block currently being scanned */
StgPtr scan; /* scan pointer in current block */
bdescr *new_large_objects; /* large objects collected so far */
bdescr *scavenged_large_objects; /* live large objects after GC (dbl link) */
bdescr *bitmap; /* bitmap for compacting collection */
StgPtr hp; /* next free locn in to-space */
StgPtr hpLim; /* end of current to-space block */
bdescr * hp_bd; /* bdescr of current to-space block */
bdescr * to_blocks; /* bdescr of first to-space block */
unsigned int n_to_blocks; /* number of blocks in to-space */
bdescr * scan_bd; /* block currently being scanned */
StgPtr scan; /* scan pointer in current block */
bdescr * new_large_objects; /* large objects collected so far */
bdescr * scavenged_large_objects; /* live large objs after GC (d-link) */
unsigned int n_scavenged_large_blocks;/* size of above */
bdescr * bitmap; /* bitmap for compacting collection */
} step;
typedef struct _generation {
unsigned int no; /* generation number */
step *steps; /* steps */
unsigned int n_steps; /* number of steps */
unsigned int max_blocks; /* max blocks in step 0 */
StgMutClosure *mut_list; /* mutable objects in this generation (not G0)*/
StgMutClosure *mut_once_list; /* objects that point to younger generations */
unsigned int no; /* generation number */
step * steps; /* steps */
unsigned int n_steps; /* number of steps */
unsigned int max_blocks; /* max blocks in step 0 */
StgMutClosure *mut_list; /* mut objects in this gen (not G0)*/
StgMutClosure *mut_once_list; /* objects that point to younger gens */
/* temporary use during GC: */
StgMutClosure *saved_mut_list;
StgMutClosure * saved_mut_list;
/* stats information */
unsigned int collections;
......
/* -----------------------------------------------------------------------------
* $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
*
......@@ -212,6 +212,7 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
bdescr *bd;
step *stp;
lnat live, allocated, collected = 0, copied = 0;
lnat oldgen_saved_blocks = 0;
nat g, s;
#ifdef PROFILING
......@@ -248,7 +249,9 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
} 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;
}
}
......@@ -325,6 +328,7 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
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) {
......@@ -390,6 +394,7 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
stp->n_to_blocks = 0;
stp->new_large_objects = NULL;
stp->scavenged_large_objects = NULL;
stp->n_scavenged_large_blocks = 0;
}
}
......@@ -588,6 +593,8 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
// 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);
}
......@@ -617,7 +624,12 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
// 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
......@@ -665,10 +677,13 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
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
......@@ -701,10 +716,11 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
// 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.
......@@ -823,7 +839,7 @@ GarbageCollect ( void (*get_roots)(evac_fn), rtsBool force_major_gc )
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) {
......@@ -1135,8 +1151,12 @@ isAlive(StgClosure *p)
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)) {
......@@ -2348,6 +2368,7 @@ scavenge_mark_stack(void)
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:
......@@ -2358,6 +2379,7 @@ scavenge_mark_stack(void)
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:
......@@ -2367,6 +2389,7 @@ scavenge_mark_stack(void)
scavenge_srt(info);
case CONSTR_0_1:
case CONSTR_0_2:
mark(p+1,Bdescr(p));
break;
case FUN:
......@@ -2403,6 +2426,7 @@ scavenge_mark_stack(void)
recordOldToNewPtrs((StgMutClosure *)p);
}
failed_to_evac = rtsFalse;
mark(p+1,Bdescr(p));
break;
case MUT_VAR:
......@@ -2410,6 +2434,7 @@ scavenge_mark_stack(void)
((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:
......@@ -2828,12 +2853,31 @@ scavenge_mutable_list(generation *gen)
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;
......@@ -3266,6 +3310,9 @@ scavenge_large(step *stp)
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);
......
/* -----------------------------------------------------------------------------
* $Id: Storage.c,v 1.41 2001/07/23 17:23:20 simonmar Exp $
* $Id: Storage.c,v 1.42 2001/07/24 16:36:43 simonmar Exp $
*
* (c) The GHC Team, 1998-1999
*
......@@ -605,7 +605,7 @@ calcLive(void)
continue;
}
stp = &generations[g].steps[s];
live += (stp->n_blocks - 1) * BLOCK_SIZE_W;
live += (stp->n_large_blocks + stp->n_blocks - 1) * BLOCK_SIZE_W;
if (stp->hp_bd != NULL) {
live += ((lnat)stp->hp_bd->free - (lnat)stp->hp_bd->start)
/ sizeof(W_);
......@@ -633,7 +633,9 @@ calcNeeded(void)
for (s = 0; s < generations[g].n_steps; s++) {
if (g == 0 && s == 0) { continue; }
stp = &generations[g].steps[s];
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
&& stp->is_compacted == 0) {
needed += 2 * stp->n_blocks;
} else {
......@@ -712,7 +714,7 @@ countBlocks(bdescr *bd)
{
nat n;
for (n=0; bd != NULL; bd=bd->link) {
n++;
n += bd->blocks;
}
return n;
}
......@@ -732,9 +734,11 @@ checkSanity( void )
for (s = 0; s < generations[g].n_steps; s++) {
if (g == 0 && s == 0) { continue; }
checkHeap(generations[g].steps[s].blocks);
checkChain(generations[g].steps[s].large_objects);
ASSERT(countBlocks(generations[g].steps[s].blocks)
== generations[g].steps[s].n_blocks);
checkChain(generations[g].steps[s].large_objects);
ASSERT(countBlocks(generations[g].steps[s].large_objects)
== generations[g].steps[s].n_large_blocks);
if (g > 0) {
checkMutableList(generations[g].mut_list, g);
checkMutOnceList(generations[g].mut_once_list, g);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment