From 76a51a41211a151d68a90e8dd732aeea1da17847 Mon Sep 17 00:00:00 2001 From: simonmar Date: Tue, 24 Jul 2001 16:36:44 +0000 Subject: [PATCH] [project @ 2001-07-24 16:36:43 by simonmar] Bugfixes; take large objects into account in stats output. --- ghc/includes/StgStorage.h | 54 +++++++++++++++++++------------------ ghc/rts/GC.c | 65 ++++++++++++++++++++++++++++++++++++++------- ghc/rts/Storage.c | 14 ++++++---- 3 files changed, 93 insertions(+), 40 deletions(-) diff --git a/ghc/includes/StgStorage.h b/ghc/includes/StgStorage.h index 174898c..3af566d 100644 --- a/ghc/includes/StgStorage.h +++ b/ghc/includes/StgStorage.h @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $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; diff --git a/ghc/rts/GC.c b/ghc/rts/GC.c index 2f11e8b..624afd6 100644 --- a/ghc/rts/GC.c +++ b/ghc/rts/GC.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $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); diff --git a/ghc/rts/Storage.c b/ghc/rts/Storage.c index 320a834..1e53758 100644 --- a/ghc/rts/Storage.c +++ b/ghc/rts/Storage.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $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); -- 1.7.10.4