/* -----------------------------------------------------------------------------
- * $Id: Storage.c,v 1.8 1999/01/28 15:04:02 simonm Exp $
+ * $Id: Storage.c,v 1.17 1999/03/16 13:20:18 simonm Exp $
+ *
+ * (c) The GHC Team, 1998-1999
*
* Storage manager front end
*
if (RtsFlags.GcFlags.heapSizeSuggestion >
RtsFlags.GcFlags.maxHeapSize) {
- barf("Suggested heap size (-H<size>) is larger than max. heap size (-M<size>)\n");
+ RtsFlags.GcFlags.maxHeapSize = RtsFlags.GcFlags.heapSizeSuggestion;
}
initBlockAllocator();
gen = &generations[g];
gen->no = g;
gen->mut_list = END_MUT_LIST;
+ gen->mut_once_list = END_MUT_LIST;
gen->collections = 0;
gen->failed_promotions = 0;
- gen->max_blocks = RtsFlags.GcFlags.minOldGenSize;
+ gen->max_blocks = 0;
}
/* A couple of convenience pointers */
step->hp = NULL;
step->hpLim = NULL;
step->hp_bd = NULL;
+ step->scan = NULL;
+ step->scan_bd = NULL;
step->large_objects = NULL;
step->new_large_objects = NULL;
step->scavenged_large_objects = NULL;
/* generation 0 is special: that's the nursery */
generations[0].max_blocks = 0;
- /* G0S0: the allocation area */
+ /* G0S0: the allocation area. Policy: keep the allocation area
+ * small to begin with, even if we have a large suggested heap
+ * size. Reason: we're going to do a major collection first, and we
+ * don't want it to be a big one. This vague idea is borne out by
+ * rigorous experimental evidence.
+ */
step = &generations[0].steps[0];
g0s0 = step;
- step->blocks = allocNursery(NULL, RtsFlags.GcFlags.minAllocAreaSize);
- step->n_blocks = RtsFlags.GcFlags.minAllocAreaSize;
nursery_blocks = RtsFlags.GcFlags.minAllocAreaSize;
+ step->blocks = allocNursery(NULL, nursery_blocks);
+ step->n_blocks = nursery_blocks;
current_nursery = step->blocks;
+ g0s0->to_space = NULL;
/* hp, hpLim, hp_bd, to_space etc. aren't used in G0S0 */
weak_ptr_list = NULL;
}
void
-recordMutable(StgMutClosure *p)
-{
- bdescr *bd;
-
- ASSERT(closure_MUTABLE(p));
-
- bd = Bdescr((P_)p);
-
- /* no need to bother in generation 0 */
- if (bd->gen == g0) {
- return;
- }
-
- if (p->mut_link == NULL) {
- p->mut_link = bd->gen->mut_list;
- bd->gen->mut_list = p;
- }
-}
-
-void
newCAF(StgClosure* caf)
{
/* Put this CAF on the mutable list for the old generation.
* come to do a major GC we won't need the mut_link field
* any more and can use it as a STATIC_LINK.
*/
- ((StgMutClosure *)caf)->mut_link = oldest_gen->mut_list;
- oldest_gen->mut_list = (StgMutClosure *)caf;
+ ((StgMutClosure *)caf)->mut_link = oldest_gen->mut_once_list;
+ oldest_gen->mut_once_list = (StgMutClosure *)caf;
#ifdef DEBUG
{
info = get_itbl(caf);
ASSERT(info->type == IND_STATIC);
+#if 0
STATIC_LINK2(info,caf) = caf_list;
caf_list = caf;
+#endif
}
#endif
}
step *step;
if (RtsFlags.GcFlags.generations == 1) {
- live = g0s0->to_blocks * BLOCK_SIZE_W +
+ live = (g0s0->to_blocks - 1) * BLOCK_SIZE_W +
((lnat)g0s0->hp_bd->free - (lnat)g0s0->hp_bd->start) / sizeof(W_);
+ return live;
}
for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
for (s = 0; s < generations[g].n_steps; s++) {
/* approximate amount of live data (doesn't take into account slop
- * at end of each block).
- */
+ * at end of each block).
+ */
if (g == 0 && s == 0) {
continue;
}
step = &generations[g].steps[s];
- live += step->n_blocks * BLOCK_SIZE_W +
- ((lnat)step->hp_bd->free -(lnat)step->hp_bd->start) / sizeof(W_);
+ live += (step->n_blocks - 1) * BLOCK_SIZE_W +
+ ((lnat)step->hp_bd->free - (lnat)step->hp_bd->start) / sizeof(W_);
}
}
return live;