diff --git a/mps/code/chain.h b/mps/code/chain.h
index bd2dd650dbe..87cfa08dd71 100644
--- a/mps/code/chain.h
+++ b/mps/code/chain.h
@@ -1,7 +1,7 @@
/* chain.h: GENERATION CHAINS
*
* $Id$
- * Copyright (c) 2001 Ravenbrook Limited. See end of file for license.
+ * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license.
*/
#ifndef chain_h
@@ -90,7 +90,8 @@ extern Res PoolGenInit(PoolGen pgen, GenDesc gen, Pool pool);
extern void PoolGenFinish(PoolGen pgen);
extern Res PoolGenAlloc(Seg *segReturn, PoolGen pgen, SegClass class,
Size size, Bool withReservoirPermit, ArgList args);
-extern void PoolGenFree(PoolGen pgen, Seg seg);
+extern void PoolGenFree(PoolGen pgen, Seg seg, Size freeSize, Size oldSize,
+ Size newSize, Bool deferred);
extern void PoolGenAccountForFill(PoolGen pgen, Size size, Bool deferred);
extern void PoolGenAccountForEmpty(PoolGen pgen, Size unused, Bool deferred);
extern void PoolGenAccountForAge(PoolGen pgen, Size aged, Bool deferred);
@@ -104,7 +105,7 @@ extern void PoolGenAccountForSegMerge(PoolGen pgen);
/* C. COPYRIGHT AND LICENSE
*
- * Copyright (C) 2001-2002 Ravenbrook Limited .
+ * Copyright (C) 2001-2014 Ravenbrook Limited .
* All rights reserved. This is an open source license. Contact
* Ravenbrook for commercial licensing options.
*
diff --git a/mps/code/locus.c b/mps/code/locus.c
index d7fb4f038f6..537eea666e8 100644
--- a/mps/code/locus.c
+++ b/mps/code/locus.c
@@ -630,13 +630,15 @@ void PoolGenAccountForSegMerge(PoolGen pgen)
/* PoolGenFree -- free a segment and update accounting
*
- * Call this when all the memory in the segment is accounted as free.
- * (If not, call PoolGenAccountForAge and then PoolGenAccountForReclaim first.)
+ * Pass the amount of memory in the segment that is accounted as free,
+ * old, or new, respectively. The deferred flag is as for
+ * PoolGenAccountForFill.
*
* See
*/
-void PoolGenFree(PoolGen pgen, Seg seg)
+void PoolGenFree(PoolGen pgen, Seg seg, Size freeSize, Size oldSize,
+ Size newSize, Bool deferred)
{
Size size;
@@ -644,6 +646,13 @@ void PoolGenFree(PoolGen pgen, Seg seg)
AVERT(Seg, seg);
size = SegSize(seg);
+ AVER(freeSize + oldSize + newSize == size);
+
+ /* Pretend to age and reclaim the contents of the segment to ensure
+ * that the entire segment is accounted as free. */
+ PoolGenAccountForAge(pgen, newSize, deferred);
+ PoolGenAccountForReclaim(pgen, oldSize + newSize, deferred);
+
AVER(pgen->totalSize >= size);
pgen->totalSize -= size;
STATISTIC_STAT ({
diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c
index 1f2cad0314f..20c5a168cdd 100644
--- a/mps/code/poolamc.c
+++ b/mps/code/poolamc.c
@@ -953,13 +953,12 @@ static void AMCFinish(Pool pool)
Seg seg = SegOfPoolRing(node);
amcGen gen = amcSegGen(seg);
amcSeg amcseg = Seg2amcSeg(seg);
-
- if (!amcseg->old) {
- PoolGenAccountForAge(&gen->pgen, SegSize(seg), amcseg->deferred);
- amcseg->old = TRUE;
- }
- PoolGenAccountForReclaim(&gen->pgen, SegSize(seg), amcseg->deferred);
- PoolGenFree(&gen->pgen, seg);
+ AVERT(amcSeg, amcseg);
+ PoolGenFree(&gen->pgen, seg,
+ 0,
+ amcseg->old ? SegSize(seg) : 0,
+ amcseg->old ? 0 : SegSize(seg),
+ amcseg->deferred);
}
/* Disassociate forwarding buffers from gens before they are */
@@ -2004,8 +2003,7 @@ static void amcReclaimNailed(Pool pool, Trace trace, Seg seg)
/* We may not free a buffered seg. */
AVER(SegBuffer(seg) == NULL);
- PoolGenAccountForReclaim(&gen->pgen, SegSize(seg), Seg2amcSeg(seg)->deferred);
- PoolGenFree(&gen->pgen, seg);
+ PoolGenFree(&gen->pgen, seg, 0, SegSize(seg), 0, Seg2amcSeg(seg)->deferred);
} else {
/* Seg retained */
STATISTIC_STAT( {
@@ -2083,8 +2081,7 @@ static void AMCReclaim(Pool pool, Trace trace, Seg seg)
trace->reclaimSize += SegSize(seg);
- PoolGenAccountForReclaim(&gen->pgen, SegSize(seg), Seg2amcSeg(seg)->deferred);
- PoolGenFree(&gen->pgen, seg);
+ PoolGenFree(&gen->pgen, seg, 0, SegSize(seg), 0, Seg2amcSeg(seg)->deferred);
}
diff --git a/mps/code/poolams.c b/mps/code/poolams.c
index cd85651a4fe..b5e942c7e84 100644
--- a/mps/code/poolams.c
+++ b/mps/code/poolams.c
@@ -736,16 +736,14 @@ static void AMSSegsDestroy(AMS ams)
RING_FOR(node, ring, next) {
Seg seg = SegOfPoolRing(node);
AMSSeg amsseg = Seg2AMSSeg(seg);
+ AVERT(AMSSeg, amsseg);
AVER(amsseg->ams == ams);
AMSSegFreeCheck(amsseg);
- PoolGenAccountForAge(&ams->pgen, AMSGrainsSize(ams, amsseg->newGrains), FALSE);
- amsseg->oldGrains += amsseg->newGrains;
- amsseg->newGrains = 0;
- PoolGenAccountForReclaim(&ams->pgen, AMSGrainsSize(ams, amsseg->oldGrains), FALSE);
- amsseg->freeGrains += amsseg->oldGrains;
- amsseg->oldGrains = 0;
- AVER(amsseg->freeGrains == amsseg->grains);
- PoolGenFree(&ams->pgen, seg);
+ PoolGenFree(&ams->pgen, seg,
+ AMSGrainsSize(ams, amsseg->freeGrains),
+ AMSGrainsSize(ams, amsseg->oldGrains),
+ AMSGrainsSize(ams, amsseg->newGrains),
+ FALSE);
}
}
@@ -1636,7 +1634,11 @@ static void AMSReclaim(Pool pool, Trace trace, Seg seg)
if (amsseg->freeGrains == grains && SegBuffer(seg) == NULL)
/* No survivors */
- PoolGenFree(&ams->pgen, seg);
+ PoolGenFree(&ams->pgen, seg,
+ AMSGrainsSize(ams, amsseg->freeGrains),
+ AMSGrainsSize(ams, amsseg->oldGrains),
+ AMSGrainsSize(ams, amsseg->newGrains),
+ FALSE);
}
diff --git a/mps/code/poolawl.c b/mps/code/poolawl.c
index ffd95c15b4d..31af1dcd160 100644
--- a/mps/code/poolawl.c
+++ b/mps/code/poolawl.c
@@ -609,14 +609,12 @@ static void AWLFinish(Pool pool)
RING_FOR(node, ring, nextNode) {
Seg seg = SegOfPoolRing(node);
AWLSeg awlseg = Seg2AWLSeg(seg);
- PoolGenAccountForAge(&awl->pgen, AWLGrainsSize(awl, awlseg->newGrains), FALSE);
- awlseg->oldGrains += awlseg->newGrains;
- awlseg->newGrains = 0;
- PoolGenAccountForReclaim(&awl->pgen, AWLGrainsSize(awl, awlseg->oldGrains), FALSE);
- awlseg->freeGrains += awlseg->oldGrains;
- awlseg->oldGrains = 0;
- AVER(awlseg->freeGrains == awlseg->grains);
- PoolGenFree(&awl->pgen, seg);
+ AVERT(AWLSeg, awlseg);
+ PoolGenFree(&awl->pgen, seg,
+ AWLGrainsSize(awl, awlseg->freeGrains),
+ AWLGrainsSize(awl, awlseg->oldGrains),
+ AWLGrainsSize(awl, awlseg->newGrains),
+ FALSE);
}
awl->sig = SigInvalid;
PoolGenFinish(&awl->pgen);
@@ -1175,7 +1173,11 @@ static void AWLReclaim(Pool pool, Trace trace, Seg seg)
if (awlseg->freeGrains == awlseg->grains && buffer == NULL)
/* No survivors */
- PoolGenFree(&awl->pgen, seg);
+ PoolGenFree(&awl->pgen, seg,
+ AWLGrainsSize(awl, awlseg->freeGrains),
+ AWLGrainsSize(awl, awlseg->oldGrains),
+ AWLGrainsSize(awl, awlseg->newGrains),
+ FALSE);
}
diff --git a/mps/code/poollo.c b/mps/code/poollo.c
index a75fc0b5ba3..af93c12bd13 100644
--- a/mps/code/poollo.c
+++ b/mps/code/poollo.c
@@ -391,7 +391,11 @@ static void loSegReclaim(LOSeg loseg, Trace trace)
SegSetWhite(seg, TraceSetDel(SegWhite(seg), trace));
if (!marked)
- PoolGenFree(&lo->pgen, seg);
+ PoolGenFree(&lo->pgen, seg,
+ LOGrainsSize(lo, loseg->freeGrains),
+ LOGrainsSize(lo, loseg->oldGrains),
+ LOGrainsSize(lo, loseg->newGrains),
+ FALSE);
}
/* This walks over _all_ objects in the heap, whether they are */
@@ -536,18 +540,12 @@ static void LOFinish(Pool pool)
RING_FOR(node, &pool->segRing, nextNode) {
Seg seg = SegOfPoolRing(node);
LOSeg loseg = SegLOSeg(seg);
-
AVERT(LOSeg, loseg);
- UNUSED(loseg); /* */
-
- PoolGenAccountForAge(&lo->pgen, LOGrainsSize(lo, loseg->newGrains), FALSE);
- loseg->oldGrains += loseg->newGrains;
- loseg->newGrains = 0;
- PoolGenAccountForReclaim(&lo->pgen, LOGrainsSize(lo, loseg->oldGrains), FALSE);
- loseg->freeGrains += loseg->oldGrains;
- loseg->oldGrains = 0;
- AVER(loseg->freeGrains == loSegGrains(loseg));
- PoolGenFree(&lo->pgen, seg);
+ PoolGenFree(&lo->pgen, seg,
+ LOGrainsSize(lo, loseg->freeGrains),
+ LOGrainsSize(lo, loseg->oldGrains),
+ LOGrainsSize(lo, loseg->newGrains),
+ FALSE);
}
PoolGenFinish(&lo->pgen);
diff --git a/mps/design/strategy.txt b/mps/design/strategy.txt
index 3ab1402d8dd..40b88863af9 100644
--- a/mps/design/strategy.txt
+++ b/mps/design/strategy.txt
@@ -270,8 +270,13 @@ _`.accounting.op`: The following operations are provided:
_`.accounting.op.alloc`: Allocate a segment in a pool generation.
Debit *total*, credit *free*. (But see `.account.total.negated`_.)
-_`.accounting.op.free`: Free a segment. Debit *free*, credit *total*.
-(But see `.account.total.negated`_.)
+_`.accounting.op.free`: Free a segment. First, ensure that the
+contents of the segment are accounted as free, by artificially ageing
+any memory accounted as *new* or *newDeferred* (see
+`.accounting.op.age`_) and then artifically reclaiming any memory
+accounted as *old* or *oldDeferred* (see `.accounting.op.reclaim`_).
+Finally, debit *free*, credit *total*. (But see
+`.account.total.negated`_.)
_`.accounting.op.fill`: Allocate memory, for example by filling a
buffer. Debit *free*, credit *new* or *newDeferred*.