diff options
| author | David Jones | 2007-07-20 18:18:31 +0100 |
|---|---|---|
| committer | David Jones | 2007-07-20 18:18:31 +0100 |
| commit | d6b020e5246febf74562a0c783fb126a0d0fcc82 (patch) | |
| tree | ada0aac1be8a5a1491c31430627b1c1156712d5b /mps/code | |
| parent | b0219be8454a19aabedb1b0c5390b8f1ec69d883 (diff) | |
| download | emacs-d6b020e5246febf74562a0c783fb126a0d0fcc82.tar.gz emacs-d6b020e5246febf74562a0c783fb126a0d0fcc82.zip | |
Mps: attempt to account for condemned in the poolgen
Copied from Perforce
Change: 162966
ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code')
| -rw-r--r-- | mps/code/chain.h | 19 | ||||
| -rw-r--r-- | mps/code/locus.c | 63 | ||||
| -rw-r--r-- | mps/code/poolamc.c | 31 |
3 files changed, 97 insertions, 16 deletions
diff --git a/mps/code/chain.h b/mps/code/chain.h index 785c25e2349..b0dc016212b 100644 --- a/mps/code/chain.h +++ b/mps/code/chain.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* chain.h: GENERATION CHAINS | 1 | /* chain.h: GENERATION CHAINS |
| 2 | * | 2 | * |
| 3 | * $Id$ | 3 | * $Id$ |
| 4 | * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. | 4 | * Copyright (c) 2001-2007 Ravenbrook Limited. See end of file for license. |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #ifndef chain_h | 7 | #ifndef chain_h |
| @@ -44,19 +44,22 @@ typedef struct PoolGenStruct *PoolGen; | |||
| 44 | 44 | ||
| 45 | typedef struct PoolGenStruct { | 45 | typedef struct PoolGenStruct { |
| 46 | Sig sig; | 46 | Sig sig; |
| 47 | Serial nr; /* generation number */ | 47 | Serial nr; /* generation number */ |
| 48 | Pool pool; /* pool this belongs to */ | 48 | Pool pool; /* pool this belongs to */ |
| 49 | Chain chain; /* chain this belongs to */ | 49 | Chain chain; /* chain this belongs to */ |
| 50 | /* link in ring of all PoolGen's in this GenDesc (locus) */ | 50 | /* link in ring of all PoolGen's in this GenDesc (locus) */ |
| 51 | RingStruct genRing; | 51 | RingStruct genRing; |
| 52 | Size totalSize; /* total size of segs in gen in this pool */ | 52 | Size totalSize; /* total size of segs in gen in this pool */ |
| 53 | Size newSize; /* size allocated since last GC */ | 53 | /* Size of new objects in this gen. That is objects that have */ |
| 54 | /* never been condemned (whilst they were in this generation). */ | ||
| 55 | Size newSize; | ||
| 54 | /* newSize when TraceCreate is called. This is for diagnostic */ | 56 | /* newSize when TraceCreate is called. This is for diagnostic */ |
| 55 | /* purposes only. It's used in a DIAG message emitted in TraceStart; */ | 57 | /* purposes only. It's used in a DIAG message emitted in TraceStart; */ |
| 56 | /* at that time, newSize has already been diminished by Whiten so we */ | 58 | /* at that time, newSize has already been diminished by Whiten so we */ |
| 57 | /* can't use that value. This will not work well with multiple */ | 59 | /* can't use that value. This will not work well with multiple */ |
| 58 | /* traces. */ | 60 | /* traces. */ |
| 59 | Size newSizeAtCreate; | 61 | Size newSizeAtCreate; |
| 62 | Size condemned; /* total size of condemned objects */ | ||
| 60 | } PoolGenStruct; | 63 | } PoolGenStruct; |
| 61 | 64 | ||
| 62 | 65 | ||
| @@ -90,6 +93,8 @@ extern size_t ChainGens(Chain chain); | |||
| 90 | extern Bool PoolGenCheck(PoolGen gen); | 93 | extern Bool PoolGenCheck(PoolGen gen); |
| 91 | extern Res PoolGenInit(PoolGen gen, Chain chain, Serial nr, Pool pool); | 94 | extern Res PoolGenInit(PoolGen gen, Chain chain, Serial nr, Pool pool); |
| 92 | extern void PoolGenFinish(PoolGen gen); | 95 | extern void PoolGenFinish(PoolGen gen); |
| 96 | extern void PoolGenNoteCondemned(PoolGen, Size, Size, Size, Size); | ||
| 97 | extern void PoolGenNoteReclaimed(PoolGen, Size, Size, Size, Size); | ||
| 93 | extern void PoolGenFlip(PoolGen gen); | 98 | extern void PoolGenFlip(PoolGen gen); |
| 94 | #define PoolGenNr(gen) ((gen)->nr) | 99 | #define PoolGenNr(gen) ((gen)->nr) |
| 95 | extern void PoolGenUpdateZones(PoolGen gen, Seg seg); | 100 | extern void PoolGenUpdateZones(PoolGen gen, Seg seg); |
| @@ -100,7 +105,7 @@ extern void PoolGenUpdateZones(PoolGen gen, Seg seg); | |||
| 100 | 105 | ||
| 101 | /* C. COPYRIGHT AND LICENSE | 106 | /* C. COPYRIGHT AND LICENSE |
| 102 | * | 107 | * |
| 103 | * Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>. | 108 | * Copyright (C) 2001-2007 Ravenbrook Limited <http://www.ravenbrook.com/>. |
| 104 | * All rights reserved. This is an open source license. Contact | 109 | * All rights reserved. This is an open source license. Contact |
| 105 | * Ravenbrook for commercial licensing options. | 110 | * Ravenbrook for commercial licensing options. |
| 106 | * | 111 | * |
diff --git a/mps/code/locus.c b/mps/code/locus.c index 4f3be3d6f30..943903baff4 100644 --- a/mps/code/locus.c +++ b/mps/code/locus.c | |||
| @@ -377,6 +377,7 @@ Res PoolGenInit(PoolGen gen, Chain chain, Serial nr, Pool pool) | |||
| 377 | RingInit(&gen->genRing); | 377 | RingInit(&gen->genRing); |
| 378 | gen->totalSize = (Size)0; | 378 | gen->totalSize = (Size)0; |
| 379 | gen->newSize = (Size)0; | 379 | gen->newSize = (Size)0; |
| 380 | gen->condemned = (Size)0; | ||
| 380 | gen->sig = PoolGenSig; | 381 | gen->sig = PoolGenSig; |
| 381 | 382 | ||
| 382 | if(nr != chain->genCount) { | 383 | if(nr != chain->genCount) { |
| @@ -411,9 +412,71 @@ Bool PoolGenCheck(PoolGen gen) | |||
| 411 | CHECKU(Chain, gen->chain); | 412 | CHECKU(Chain, gen->chain); |
| 412 | CHECKL(RingCheck(&gen->genRing)); | 413 | CHECKL(RingCheck(&gen->genRing)); |
| 413 | CHECKL(gen->newSize <= gen->totalSize); | 414 | CHECKL(gen->newSize <= gen->totalSize); |
| 415 | CHECKL(gen->condemned <= gen->totalSize); | ||
| 416 | CHECKL(gen->newSize + gen->condemned <= gen->totalSize); | ||
| 414 | return TRUE; | 417 | return TRUE; |
| 415 | } | 418 | } |
| 416 | 419 | ||
| 420 | /* PoolGenNoteCondemned -- maintain accounting of condemned stuff. | ||
| 421 | * | ||
| 422 | * Arguments: | ||
| 423 | * newlyCondemned - number of bytes of objects that are condemned and | ||
| 424 | * have never been condemned before (in this location). | ||
| 425 | * againCondemned - number of bytes of objects that are condemned that | ||
| 426 | * have been condemned before. | ||
| 427 | * notCondemned - number of bytes of objects that are not condemned. | ||
| 428 | * free - number of bytes that are free (that is, not objects, and | ||
| 429 | * available for future allocation). | ||
| 430 | * | ||
| 431 | * It is expected that some pools may not be able to maintain accurate | ||
| 432 | * accounting information and that they therefore will record stuff in | ||
| 433 | * the "againCondemned" category that should have gone in | ||
| 434 | * newlyCondemned or free (and will report those categories as free). | ||
| 435 | */ | ||
| 436 | |||
| 437 | void PoolGenNoteCondemned(PoolGen gen, | ||
| 438 | Size newlyCondemned, | ||
| 439 | Size againCondemned, | ||
| 440 | Size notCondemned, | ||
| 441 | Size free) | ||
| 442 | { | ||
| 443 | AVERT(PoolGen, gen); | ||
| 444 | /* In fact, no current pool uses free. So it's always 0. */ | ||
| 445 | AVER(free == 0); | ||
| 446 | |||
| 447 | gen->newSize -= newlyCondemned; | ||
| 448 | gen->condemned += newlyCondemned + againCondemned; | ||
| 449 | return; | ||
| 450 | } | ||
| 451 | |||
| 452 | /* PoolGenNoteReclaimed -- maintain accounting of reclaimed stuff. | ||
| 453 | * | ||
| 454 | * Arguments: | ||
| 455 | * free - number of bytes that were free already, prior to the call to | ||
| 456 | * reclaim. (should be be "and not reported as free in Whiten with a | ||
| 457 | * call to PoolGenNoteCondemned). | ||
| 458 | * reclaimed - number of bytes that become free as part of reclaim | ||
| 459 | * (previously not free, but now are). Note: do not count unmapped | ||
| 460 | * bytes here. | ||
| 461 | * retained - number of bytes of objects that are still considered | ||
| 462 | * reachable after the reclaim. | ||
| 463 | * unmapped - number of bytes that have been unmapped. | ||
| 464 | */ | ||
| 465 | |||
| 466 | void PoolGenNoteReclaimed(PoolGen gen, | ||
| 467 | Size free, Size reclaimed, Size retained, Size unmapped) | ||
| 468 | { | ||
| 469 | Size sum; | ||
| 470 | |||
| 471 | AVER(gen->totalSize >= unmapped); | ||
| 472 | gen->totalSize -= unmapped; | ||
| 473 | |||
| 474 | sum = free + reclaimed + retained + unmapped; | ||
| 475 | AVER(gen->condemned >= sum); | ||
| 476 | gen->condemned -= sum; | ||
| 477 | return; | ||
| 478 | } | ||
| 479 | |||
| 417 | 480 | ||
| 418 | /* PoolGenUpdateZones -- update the zone of the generation | 481 | /* PoolGenUpdateZones -- update the zone of the generation |
| 419 | * | 482 | * |
diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c index 1a2d2019509..fd3db0a78f1 100644 --- a/mps/code/poolamc.c +++ b/mps/code/poolamc.c | |||
| @@ -1188,11 +1188,17 @@ static Res AMCWhiten(Pool pool, Trace trace, Seg seg) | |||
| 1188 | AMC amc; | 1188 | AMC amc; |
| 1189 | Buffer buffer; | 1189 | Buffer buffer; |
| 1190 | Res res; | 1190 | Res res; |
| 1191 | /* Sizes, in bytes, of stuff that is condemned and not-condemned */ | ||
| 1192 | /* (normally everything is condemned, but not for buffers). */ | ||
| 1193 | Size condemned, notcondemned; | ||
| 1191 | 1194 | ||
| 1192 | AVERT(Pool, pool); | 1195 | AVERT(Pool, pool); |
| 1193 | AVERT(Trace, trace); | 1196 | AVERT(Trace, trace); |
| 1194 | AVERT(Seg, seg); | 1197 | AVERT(Seg, seg); |
| 1195 | 1198 | ||
| 1199 | condemned = SegSize(seg); | ||
| 1200 | notcondemned = 0; | ||
| 1201 | |||
| 1196 | buffer = SegBuffer(seg); | 1202 | buffer = SegBuffer(seg); |
| 1197 | if(buffer != NULL) { | 1203 | if(buffer != NULL) { |
| 1198 | AVERT(Buffer, buffer); | 1204 | AVERT(Buffer, buffer); |
| @@ -1242,23 +1248,28 @@ static Res AMCWhiten(Pool pool, Trace trace, Seg seg) | |||
| 1242 | SegSetNailed(seg, TraceSetAdd(SegNailed(seg), trace)); | 1248 | SegSetNailed(seg, TraceSetAdd(SegNailed(seg), trace)); |
| 1243 | } | 1249 | } |
| 1244 | /* We didn't condemn the buffer, subtract it from the count. */ | 1250 | /* We didn't condemn the buffer, subtract it from the count. */ |
| 1251 | #if 0 | ||
| 1252 | notcondemned = AddrOffset(BufferScanLimit(buffer), | ||
| 1253 | BufferLimit(buffer)); | ||
| 1254 | condemned -= notcondemned; | ||
| 1255 | #endif | ||
| 1245 | /* @@@@ We could subtract all the nailed grains. */ | 1256 | /* @@@@ We could subtract all the nailed grains. */ |
| 1246 | /* Relies on unsigned arithmetic wrapping round */ | ||
| 1247 | /* on under- and overflow (which it does). */ | ||
| 1248 | trace->condemned -= AddrOffset(BufferScanLimit(buffer), | ||
| 1249 | BufferLimit(buffer)); | ||
| 1250 | } | 1257 | } |
| 1251 | } | 1258 | } |
| 1252 | } | 1259 | } |
| 1253 | 1260 | ||
| 1254 | SegSetWhite(seg, TraceSetAdd(SegWhite(seg), trace)); | 1261 | SegSetWhite(seg, TraceSetAdd(SegWhite(seg), trace)); |
| 1255 | trace->condemned += SegSize(seg); | 1262 | trace->condemned += condemned; |
| 1256 | 1263 | ||
| 1257 | gen = amcSegGen(seg); | 1264 | gen = amcSegGen(seg); |
| 1258 | AVERT(amcGen, gen); | 1265 | AVERT(amcGen, gen); |
| 1266 | |||
| 1267 | /* Report accounting to PoolGen. */ | ||
| 1259 | if(Seg2amcSeg(seg)->new) { | 1268 | if(Seg2amcSeg(seg)->new) { |
| 1260 | gen->pgen.newSize -= SegSize(seg); | 1269 | PoolGenNoteCondemned(&gen->pgen, condemned, 0, notcondemned, 0); |
| 1261 | Seg2amcSeg(seg)->new = FALSE; | 1270 | Seg2amcSeg(seg)->new = FALSE; |
| 1271 | } else { | ||
| 1272 | PoolGenNoteCondemned(&gen->pgen, 0, condemned, notcondemned, 0); | ||
| 1262 | } | 1273 | } |
| 1263 | 1274 | ||
| 1264 | /* Ensure we are forwarding into the right generation. */ | 1275 | /* Ensure we are forwarding into the right generation. */ |
| @@ -1896,7 +1907,7 @@ returnRes: | |||
| 1896 | 1907 | ||
| 1897 | /* amcReclaimNailed -- reclaim what you can from a nailed segment */ | 1908 | /* amcReclaimNailed -- reclaim what you can from a nailed segment */ |
| 1898 | 1909 | ||
| 1899 | static void amcReclaimNailed(Pool pool, Trace trace, Seg seg) | 1910 | static void amcReclaimNailed(Pool pool, Trace trace, Seg seg, amcGen gen) |
| 1900 | { | 1911 | { |
| 1901 | Addr p, limit; | 1912 | Addr p, limit; |
| 1902 | Arena arena; | 1913 | Arena arena; |
| @@ -1961,6 +1972,8 @@ static void amcReclaimNailed(Pool pool, Trace trace, Seg seg) | |||
| 1961 | trace->reclaimSize += bytesReclaimed; | 1972 | trace->reclaimSize += bytesReclaimed; |
| 1962 | trace->preservedInPlaceCount += preservedInPlaceCount; | 1973 | trace->preservedInPlaceCount += preservedInPlaceCount; |
| 1963 | trace->preservedInPlaceSize += preservedInPlaceSize; | 1974 | trace->preservedInPlaceSize += preservedInPlaceSize; |
| 1975 | PoolGenNoteReclaimed(&gen->pgen, 0, 0, SegSize(seg), 0); | ||
| 1976 | return; | ||
| 1964 | } | 1977 | } |
| 1965 | 1978 | ||
| 1966 | 1979 | ||
| @@ -1997,13 +2010,13 @@ static void AMCReclaim(Pool pool, Trace trace, Seg seg) | |||
| 1997 | } | 2010 | } |
| 1998 | 2011 | ||
| 1999 | if(SegNailed(seg) != TraceSetEMPTY) { | 2012 | if(SegNailed(seg) != TraceSetEMPTY) { |
| 2000 | amcReclaimNailed(pool, trace, seg); | 2013 | amcReclaimNailed(pool, trace, seg, gen); |
| 2001 | return; | 2014 | return; |
| 2002 | } | 2015 | } |
| 2003 | 2016 | ||
| 2004 | --gen->segs; | 2017 | --gen->segs; |
| 2005 | size = SegSize(seg); | 2018 | size = SegSize(seg); |
| 2006 | gen->pgen.totalSize -= size; | 2019 | PoolGenNoteReclaimed(&gen->pgen, 0, 0, 0, size); |
| 2007 | 2020 | ||
| 2008 | trace->reclaimSize += size; | 2021 | trace->reclaimSize += size; |
| 2009 | 2022 | ||