From c3fd9d5ba78b50c088802e8bf1ba5e473a1787dc Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 11 Jul 2018 21:14:43 +0100 Subject: [PATCH] Represent the set of generations condemned for a trace. Eliminate duplication between policyCondemnChain and traceCondemnAll. Compute better mortality estimate for collection of the world. Copied from Perforce Change: 194611 --- mps/code/locus.c | 149 +++++++++++++++------------------ mps/code/locus.h | 18 ++-- mps/code/mpm.h | 7 +- mps/code/mpmst.h | 2 +- mps/code/policy.c | 34 ++------ mps/code/poolmfs.c | 2 +- mps/code/trace.c | 200 ++++++++++++++++++++++----------------------- 7 files changed, 181 insertions(+), 231 deletions(-) diff --git a/mps/code/locus.c b/mps/code/locus.c index ae6c762c85d..5a6cb9b8395 100644 --- a/mps/code/locus.c +++ b/mps/code/locus.c @@ -133,13 +133,19 @@ static Bool GenParamCheck(GenParamStruct *params) static void GenDescInit(GenDesc gen, GenParamStruct *params) { + TraceId ti; + AVER(gen != NULL); AVER(GenParamCheck(params)); + gen->zones = ZoneSetEMPTY; gen->capacity = params->capacity; gen->mortality = params->mortality; RingInit(&gen->locusRing); RingInit(&gen->segRing); + gen->activeTraces = TraceSetEMPTY; + for (ti = 0; ti < TraceLIMIT; ++ti) + RingInit(&gen->trace[ti].traceRing); gen->sig = GenDescSig; AVERT(GenDesc, gen); } @@ -149,10 +155,16 @@ static void GenDescInit(GenDesc gen, GenParamStruct *params) static void GenDescFinish(GenDesc gen) { + TraceId ti; + AVERT(GenDesc, gen); + + gen->sig = SigInvalid; RingFinish(&gen->locusRing); RingFinish(&gen->segRing); - gen->sig = SigInvalid; + AVER(gen->activeTraces == TraceSetEMPTY); + for (ti = 0; ti < TraceLIMIT; ++ti) + RingFinish(&gen->trace[ti].traceRing); } @@ -176,40 +188,47 @@ Size GenDescNewSize(GenDesc gen) /* genDescTraceStart -- notify generation of start of a trace */ -static void genDescStartTrace(GenDesc gen, Trace trace) +void GenDescStartTrace(GenDesc gen, Trace trace) { - GenTraceStats stats; + GenTrace genTrace; AVERT(GenDesc, gen); AVERT(Trace, trace); - stats = &gen->trace[trace->ti]; - stats->condemned = 0; - stats->forwarded = 0; - stats->preservedInPlace = 0; + AVER(!TraceSetIsMember(gen->activeTraces, trace)); + gen->activeTraces = TraceSetAdd(gen->activeTraces, trace); + genTrace = &gen->trace[trace->ti]; + AVER(RingIsSingle(&genTrace->traceRing)); + RingAppend(&trace->genRing, &genTrace->traceRing); + genTrace->condemned = 0; + genTrace->forwarded = 0; + genTrace->preservedInPlace = 0; } /* genDescEndTrace -- notify generation of end of a trace */ -static void genDescEndTrace(GenDesc gen, Trace trace) +void GenDescEndTrace(GenDesc gen, Trace trace) { - GenTraceStats stats; + GenTrace genTrace; Size survived; AVERT(GenDesc, gen); AVERT(Trace, trace); - stats = &gen->trace[trace->ti]; - survived = stats->forwarded + stats->preservedInPlace; - AVER(survived <= stats->condemned); + AVER(TraceSetIsMember(gen->activeTraces, trace)); + gen->activeTraces = TraceSetDel(gen->activeTraces, trace); + genTrace = &gen->trace[trace->ti]; + RingRemove(&genTrace->traceRing); + survived = genTrace->forwarded + genTrace->preservedInPlace; + AVER(survived <= genTrace->condemned); - if (stats->condemned > 0) { - double mortality = 1.0 - survived / (double)stats->condemned; + if (genTrace->condemned > 0) { + double mortality = 1.0 - survived / (double)genTrace->condemned; double alpha = LocusMortalityALPHA; gen->mortality = gen->mortality * (1 - alpha) + mortality * alpha; - EVENT6(TraceEndGen, trace, gen, stats->condemned, stats->forwarded, - stats->preservedInPlace, gen->mortality); + EVENT6(TraceEndGen, trace, gen, genTrace->condemned, genTrace->forwarded, + genTrace->preservedInPlace, gen->mortality); } } @@ -218,13 +237,13 @@ static void genDescEndTrace(GenDesc gen, Trace trace) void GenDescCondemned(GenDesc gen, Trace trace, Size size) { - GenTraceStats stats; + GenTrace genTrace; AVERT(GenDesc, gen); AVERT(Trace, trace); - stats = &gen->trace[trace->ti]; - stats->condemned += size; + genTrace = &gen->trace[trace->ti]; + genTrace->condemned += size; trace->condemned += size; } @@ -234,14 +253,14 @@ void GenDescCondemned(GenDesc gen, Trace trace, Size size) void GenDescSurvived(GenDesc gen, Trace trace, Size forwarded, Size preservedInPlace) { - GenTraceStats stats; + GenTrace genTrace; AVERT(GenDesc, gen); AVERT(Trace, trace); - stats = &gen->trace[trace->ti]; - stats->forwarded += forwarded; - stats->preservedInPlace += preservedInPlace; + genTrace = &gen->trace[trace->ti]; + genTrace->forwarded += forwarded; + genTrace->preservedInPlace += preservedInPlace; trace->forwardedSize += forwarded; trace->preservedInPlaceSize += preservedInPlace; } @@ -283,17 +302,18 @@ Res GenDescDescribe(GenDesc gen, mps_lib_FILE *stream, Count depth) " zones $B\n", (WriteFB)gen->zones, " capacity $W\n", (WriteFW)gen->capacity, " mortality $D\n", (WriteFD)gen->mortality, + " activeTraces $B\n", (WriteFB)gen->activeTraces, NULL); if (res != ResOK) return res; for (i = 0; i < NELEMS(gen->trace); ++i) { - GenTraceStats stats = &gen->trace[i]; + GenTrace genTrace = &gen->trace[i]; res = WriteF(stream, depth + 2, "trace $W {\n", (WriteFW)i, - " condemned $W\n", (WriteFW)stats->condemned, - " forwarded $W\n", (WriteFW)stats->forwarded, - " preservedInPlace $W\n", (WriteFW)stats->preservedInPlace, + " condemned $W\n", (WriteFW)genTrace->condemned, + " forwarded $W\n", (WriteFW)genTrace->forwarded, + " preservedInPlace $W\n", (WriteFW)genTrace->preservedInPlace, "}\n", NULL); if (res != ResOK) return res; @@ -323,7 +343,6 @@ static void ChainInit(ChainStruct *chain, Arena arena, GenDescStruct *gens, chain->arena = arena; RingInit(&chain->chainRing); - chain->activeTraces = TraceSetEMPTY; chain->genCount = genCount; chain->gens = gens; chain->sig = ChainSig; @@ -376,7 +395,6 @@ Bool ChainCheck(Chain chain) CHECKS(Chain, chain); CHECKU(Arena, chain->arena); CHECKD_NOSIG(Ring, &chain->chainRing); - CHECKL(TraceSetCheck(chain->activeTraces)); CHECKL(chain->genCount > 0); for (i = 0; i < chain->genCount; ++i) { CHECKD(GenDesc, &chain->gens[i]); @@ -395,7 +413,6 @@ void ChainDestroy(Chain chain) size_t i; AVERT(Chain, chain); - AVER(chain->activeTraces == TraceSetEMPTY); /* */ arena = chain->arena; genCount = chain->genCount; @@ -443,51 +460,20 @@ double ChainDeferral(Chain chain) AVERT(Chain, chain); - if (chain->activeTraces == TraceSetEMPTY) { - for (i = 0; i < chain->genCount; ++i) { - double genTime = chain->gens[i].capacity * 1024.0 - - (double)GenDescNewSize(&chain->gens[i]); - if (genTime < time) - time = genTime; - } + for (i = 0; i < chain->genCount; ++i) { + double genTime; + GenDesc gen = &chain->gens[i]; + if (gen->activeTraces != TraceSetEMPTY) + return DBL_MAX; + genTime = gen->capacity * 1024.0 - (double)GenDescNewSize(&chain->gens[i]); + if (genTime < time) + time = genTime; } return time; } -/* ChainStartTrace -- called to notify start of GC for this chain */ - -void ChainStartTrace(Chain chain, Trace trace) -{ - Index i; - - AVERT(Chain, chain); - AVERT(Trace, trace); - - chain->activeTraces = TraceSetAdd(chain->activeTraces, trace); - - for (i = 0; i < chain->genCount; ++i) - genDescStartTrace(&chain->gens[i], trace); -} - - -/* ChainEndTrace -- called to notify end of GC for this chain */ - -void ChainEndTrace(Chain chain, Trace trace) -{ - Index i; - - AVERT(Chain, chain); - AVERT(Trace, trace); - - chain->activeTraces = TraceSetDel(chain->activeTraces, trace); - - for (i = 0; i < chain->genCount; ++i) - genDescEndTrace(&chain->gens[i], trace); -} - - /* ChainDescribe -- describe a chain */ Res ChainDescribe(Chain chain, mps_lib_FILE *stream, Count depth) @@ -503,7 +489,6 @@ Res ChainDescribe(Chain chain, mps_lib_FILE *stream, Count depth) res = WriteF(stream, depth, "Chain $P {\n", (WriteFP)chain, " arena $P\n", (WriteFP)chain->arena, - " activeTraces $B\n", (WriteFB)chain->activeTraces, NULL); if (res != ResOK) return res; @@ -875,17 +860,14 @@ Res PoolGenDescribe(PoolGen pgen, mps_lib_FILE *stream, Count depth) void LocusInit(Arena arena) { - GenDesc gen = &arena->topGen; + GenParamStruct params; - /* Can't check arena, because it's not been inited. */ - - gen->zones = ZoneSetEMPTY; - gen->capacity = 0; /* unused */ - gen->mortality = 0.5; - RingInit(&gen->locusRing); - RingInit(&gen->segRing); - gen->sig = GenDescSig; - AVERT(GenDesc, gen); + AVER(arena != NULL); /* not initialized yet. */ + + params.capacity = 1; /* unused */ + params.mortality = 0.5; + + GenDescInit(&arena->topGen, ¶ms); } @@ -893,12 +875,9 @@ void LocusInit(Arena arena) void LocusFinish(Arena arena) { - GenDesc gen = &arena->topGen; - /* Can't check arena, because it's being finished. */ - - gen->sig = SigInvalid; - RingFinish(&gen->locusRing); + AVER(arena != NULL); + GenDescFinish(&arena->topGen); } diff --git a/mps/code/locus.h b/mps/code/locus.h index 1608c62dd7b..5525f242457 100644 --- a/mps/code/locus.h +++ b/mps/code/locus.h @@ -22,15 +22,16 @@ typedef struct GenParamStruct { } GenParamStruct; -/* GenTraceStats -- per-generation per-trace statistics */ +/* GenTrace -- per-generation per-trace structure */ -typedef struct GenTraceStatsStruct *GenTraceStats; +typedef struct GenTraceStruct *GenTrace; -typedef struct GenTraceStatsStruct { +typedef struct GenTraceStruct { + RingStruct traceRing; /* link in ring of generations condemned by trace */ Size condemned; /* size of objects condemned by the trace */ Size forwarded; /* size of objects that were forwarded by the trace */ Size preservedInPlace; /* size of objects preserved in place by the trace */ -} GenTraceStatsStruct; +} GenTraceStruct; /* GenDesc -- descriptor of a generation in a chain */ @@ -46,7 +47,8 @@ typedef struct GenDescStruct { double mortality; /* predicted mortality */ RingStruct locusRing; /* Ring of all PoolGen's in this GenDesc (locus) */ RingStruct segRing; /* Ring of GCSegs in this generation */ - GenTraceStatsStruct trace[TraceLIMIT]; + TraceSet activeTraces; /* set of traces collecting this generation */ + GenTraceStruct trace[TraceLIMIT]; } GenDescStruct; @@ -81,7 +83,6 @@ typedef struct mps_chain_s { Sig sig; Arena arena; RingStruct chainRing; /* list of chains in the arena */ - TraceSet activeTraces; /* set of traces collecting this chain */ size_t genCount; /* number of generations */ GenDesc gens; /* the array of generations */ } ChainStruct; @@ -90,9 +91,12 @@ typedef struct mps_chain_s { extern Bool GenDescCheck(GenDesc gen); extern Size GenDescNewSize(GenDesc gen); extern Size GenDescTotalSize(GenDesc gen); +extern void GenDescStartTrace(GenDesc gen, Trace trace); +extern void GenDescEndTrace(GenDesc gen, Trace trace); extern void GenDescCondemned(GenDesc gen, Trace trace, Size size); extern void GenDescSurvived(GenDesc gen, Trace trace, Size forwarded, Size preservedInPlace); extern Res GenDescDescribe(GenDesc gen, mps_lib_FILE *stream, Count depth); +#define GenDescOfTraceRing(node, trace) PARENT(GenDescStruct, trace[trace->ti], RING_ELT(GenTrace, traceRing, node)) extern Res ChainCreate(Chain *chainReturn, Arena arena, size_t genCount, GenParam params); @@ -100,8 +104,6 @@ extern void ChainDestroy(Chain chain); extern Bool ChainCheck(Chain chain); extern double ChainDeferral(Chain chain); -extern void ChainStartTrace(Chain chain, Trace trace); -extern void ChainEndTrace(Chain chain, Trace trace); extern size_t ChainGens(Chain chain); extern GenDesc ChainGen(Chain chain, Index gen); extern Res ChainDescribe(Chain chain, mps_lib_FILE *stream, Count depth); diff --git a/mps/code/mpm.h b/mps/code/mpm.h index dabf090ea2b..c5d61176890 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -374,7 +374,7 @@ extern void TraceDestroyFinished(Trace trace); extern Bool TraceIsEmpty(Trace trace); extern Res TraceAddWhite(Trace trace, Seg seg); extern void TraceCondemnStart(Trace trace); -extern void TraceCondemnEnd(Trace trace); +extern Res TraceCondemnEnd(double *mortalityReturn, Trace trace); extern Res TraceStart(Trace trace, double mortality, double finishingTime); extern Bool TracePoll(Work *workReturn, Bool *collectWorldReturn, Globals globals, Bool collectWorldAllowed); @@ -397,11 +397,6 @@ extern Bool TraceIdMessagesCheck(Arena arena, TraceId ti); extern Res TraceIdMessagesCreate(Arena arena, TraceId ti); extern void TraceIdMessagesDestroy(Arena arena, TraceId ti); -/* Collection control parameters */ - -extern double TraceWorkFactor; - - /* Equivalent to MPS_SCAN_BEGIN */ #define TRACE_SCAN_BEGIN(ss) \ diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index 804f31d4eba..ea6054bcdce 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -434,7 +434,7 @@ typedef struct TraceStruct { Bool firstStretch; /* in first stretch of band (see accessor) */ SegFixMethod fix; /* fix method to apply to references */ void *fixClosure; /* see .ss.fix-closure */ - Chain chain; /* chain being incrementally collected */ + RingStruct genRing; /* ring of generations condemned by trace */ STATISTIC_DECL(Size preTraceArenaReserved) /* ArenaReserved before this trace */ Size condemned; /* condemned bytes */ Size notCondemned; /* collectable but not condemned */ diff --git a/mps/code/policy.c b/mps/code/policy.c index 77176853e5f..eabb43d2e5d 100644 --- a/mps/code/policy.c +++ b/mps/code/policy.c @@ -210,11 +210,10 @@ Bool PolicyShouldCollectWorld(Arena arena, double availableTime, static Res policyCondemnChain(double *mortalityReturn, Chain chain, Trace trace) { - Res res; size_t topCondemnedGen, i; GenDesc gen; - Size condemnedSize = 0, survivorSize = 0, genNewSize, genTotalSize; + AVER(mortalityReturn != NULL); AVERT(Chain, chain); AVERT(Trace, trace); @@ -230,8 +229,7 @@ static Res policyCondemnChain(double *mortalityReturn, Chain chain, Trace trace) -- topCondemnedGen; gen = &chain->gens[topCondemnedGen]; AVERT(GenDesc, gen); - genNewSize = GenDescNewSize(gen); - if (genNewSize >= gen->capacity * (Size)1024) + if (GenDescNewSize(gen) >= gen->capacity * (Size)1024) break; } @@ -239,33 +237,12 @@ static Res policyCondemnChain(double *mortalityReturn, Chain chain, Trace trace) * lower generations. */ TraceCondemnStart(trace); for (i = 0; i <= topCondemnedGen; ++i) { - Ring node, next; gen = &chain->gens[i]; AVERT(GenDesc, gen); - RING_FOR(node, &gen->segRing, next) { - GCSeg gcseg = RING_ELT(GCSeg, genRing, node); - res = TraceAddWhite(trace, &gcseg->segStruct); - if (res != ResOK) - goto failBegin; - } - genTotalSize = GenDescTotalSize(gen); - genNewSize = GenDescNewSize(gen); - condemnedSize += genTotalSize; - survivorSize += (Size)(genNewSize * (1.0 - gen->mortality)) - /* predict survivors will survive again */ - + (genTotalSize - genNewSize); + GenDescStartTrace(gen, trace); } - TraceCondemnEnd(trace); - EVENT3(ChainCondemnAuto, chain, topCondemnedGen, chain->genCount); - - *mortalityReturn = 1.0 - (double)survivorSize / condemnedSize; - return ResOK; - -failBegin: - AVER(TraceIsEmpty(trace)); /* See */ - TraceCondemnEnd(trace); - return res; + return TraceCondemnEnd(mortalityReturn, trace); } @@ -287,6 +264,7 @@ Bool PolicyStartTrace(Trace *traceReturn, Bool *collectWorldReturn, { Res res; Trace trace; + double TraceWorkFactor = 0.25; AVER(traceReturn != NULL); AVERT(Arena, arena); @@ -340,8 +318,6 @@ Bool PolicyStartTrace(Trace *traceReturn, Bool *collectWorldReturn, res = TraceCreate(&trace, arena, TraceStartWhyCHAIN_GEN0CAP); AVER(res == ResOK); - trace->chain = firstChain; - ChainStartTrace(firstChain, trace); res = policyCondemnChain(&mortality, firstChain, trace); if (res != ResOK) /* should try some other trace, really @@@@ */ goto failCondemn; diff --git a/mps/code/poolmfs.c b/mps/code/poolmfs.c index 21f87ad448a..9123a44b9af 100644 --- a/mps/code/poolmfs.c +++ b/mps/code/poolmfs.c @@ -387,7 +387,7 @@ Bool MFSCheck(MFS mfs) CHECKL(SizeIsArenaGrains(mfs->extendBy, arena)); CHECKL(SizeAlignUp(mfs->unroundedUnitSize, PoolAlignment(MFSPool(mfs))) == mfs->unitSize); - CHECKL(RingCheck(&mfs->extentRing)); + CHECKD_NOSIG(Ring, &mfs->extentRing); CHECKL(mfs->free <= mfs->total); CHECKL((mfs->total - mfs->free) % mfs->unitSize == 0); return TRUE; diff --git a/mps/code/trace.c b/mps/code/trace.c index 35762ef2668..1b6ede3a2b8 100644 --- a/mps/code/trace.c +++ b/mps/code/trace.c @@ -153,6 +153,7 @@ Bool TraceCheck(Trace trace) CHECKL(trace == &trace->arena->trace[trace->ti]); CHECKL(TraceSetIsMember(trace->arena->busyTraces, trace)); CHECKL(ZoneSetSub(trace->mayMove, trace->white)); + CHECKD_NOSIG(Ring, &trace->genRing); /* Use trace->state to check more invariants. */ switch(trace->state) { case TraceINIT: @@ -161,16 +162,20 @@ Bool TraceCheck(Trace trace) break; case TraceUNFLIPPED: + CHECKL(!RingIsSingle(&trace->genRing)); CHECKL(!TraceSetIsMember(trace->arena->flippedTraces, trace)); /* @@@@ Assert that mutator is grey for trace. */ break; case TraceFLIPPED: + CHECKL(!RingIsSingle(&trace->genRing)); CHECKL(TraceSetIsMember(trace->arena->flippedTraces, trace)); + CHECKL(RankCheck(trace->band)); /* @@@@ Assert that mutator is black for trace. */ break; case TraceRECLAIM: + CHECKL(!RingIsSingle(&trace->genRing)); CHECKL(TraceSetIsMember(trace->arena->flippedTraces, trace)); /* @@@@ Assert that grey set is empty for trace. */ break; @@ -184,13 +189,6 @@ Bool TraceCheck(Trace trace) NOTREACHED; break; } - /* Valid values for band depend on state. */ - if(trace->state == TraceFLIPPED) { - CHECKL(RankCheck(trace->band)); - } - if(trace->chain != NULL) { - CHECKU(Chain, trace->chain); - } CHECKL(FUNCHECK(trace->fix)); /* Can't check trace->fixClosure. */ @@ -389,7 +387,23 @@ Res TraceAddWhite(Trace trace, Seg seg) } -/* TraceCondemnStart -- start condemning objects for a trace +/* TraceCondemnStart -- start selecting generations to condemn for a trace */ + +void TraceCondemnStart(Trace trace) +{ + AVERT(Trace, trace); + AVER(trace->state == TraceINIT); + AVER(trace->white == ZoneSetEMPTY); + AVER(RingIsSingle(&trace->genRing)); +} + + +/* TraceCondemnEnd -- condemn segments for trace + * + * Condemn the segments in the generations that were selected since + * TraceCondemnStart, and compute the predicted mortality of the + * condemned memory. If successful, update *mortalityReturn and return + * ResOK. * * We suspend the mutator threads so that the PoolWhiten methods can * calculate white sets without the mutator allocating in buffers @@ -400,24 +414,55 @@ Res TraceAddWhite(Trace trace, Seg seg) * incremental condemn. */ -void TraceCondemnStart(Trace trace) +Res TraceCondemnEnd(double *mortalityReturn, Trace trace) { + Size condemnedSize = 0, survivorSize = 0; + Ring genNode, genNext; + Res res; + + AVER(mortalityReturn != NULL); AVERT(Trace, trace); AVER(trace->state == TraceINIT); AVER(trace->white == ZoneSetEMPTY); ShieldHold(trace->arena); -} - - -/* TraceCondemnEnd -- stop condemning objects for a trace */ - -void TraceCondemnEnd(Trace trace) -{ - AVERT(Trace, trace); - AVER(trace->state == TraceINIT); - + RING_FOR(genNode, &trace->genRing, genNext) { + Size genNewSize, genTotalSize; + Ring segNode, segNext; + GenDesc gen = GenDescOfTraceRing(genNode, trace); + AVERT(GenDesc, gen); + RING_FOR(segNode, &gen->segRing, segNext) { + GCSeg gcseg = RING_ELT(GCSeg, genRing, segNode); + res = TraceAddWhite(trace, &gcseg->segStruct); + if (res != ResOK) + goto failBegin; + } + genTotalSize = GenDescTotalSize(gen); + genNewSize = GenDescNewSize(gen); + condemnedSize += genTotalSize; + survivorSize += (Size)(genNewSize * (1.0 - gen->mortality)) + /* predict survivors will survive again */ + + (genTotalSize - genNewSize); + } ShieldRelease(trace->arena); + + if (TraceIsEmpty(trace)) + return ResFAIL; + + *mortalityReturn = 1.0 - (double)survivorSize / condemnedSize; + return ResOK; + +failBegin: + /* If we successfully whitened one or more segments, but failed to + whiten them all, then the white sets would now be inconsistent. + This can't happen in practice (at time of writing) because all + PoolWhiten methods always succeed. If we ever have a pool class + that fails to whiten a segment, then this assertion will be + triggered. In that case, we'll have to recover here by blackening + the segments again. */ + AVER(TraceIsEmpty(trace)); + ShieldRelease(trace->arena); + return res; } @@ -671,7 +716,7 @@ found: trace->band = RankMIN; trace->fix = SegFix; trace->fixClosure = NULL; - trace->chain = NULL; + RingInit(&trace->genRing); STATISTIC(trace->preTraceArenaReserved = ArenaReserved(arena)); trace->condemned = (Size)0; /* nothing condemned yet */ trace->notCondemned = (Size)0; @@ -726,7 +771,7 @@ found: traceCreatePoolGen(&arena->topGen); }); - *traceReturn = trace; + *traceReturn = trace; return ResOK; } @@ -735,17 +780,13 @@ found: static void traceDestroyCommon(Trace trace) { - Ring chainNode, nextChainNode; + Ring node, nextNode; - if (trace->chain != NULL) { - ChainEndTrace(trace->chain, trace); - } else { - /* Notify all the chains. */ - RING_FOR(chainNode, &trace->arena->chainRing, nextChainNode) { - Chain chain = RING_ELT(Chain, chainRing, chainNode); - ChainEndTrace(chain, trace); - } + RING_FOR(node, &trace->genRing, nextNode) { + GenDesc gen = GenDescOfTraceRing(node, trace); + GenDescEndTrace(gen, trace); } + RingFinish(&trace->genRing); /* Ensure that address space is returned to the operating system for * traces that don't have any condemned objects (there might be @@ -1467,65 +1508,6 @@ Res TraceScanArea(ScanState ss, Word *base, Word *limit, } -/* traceCondemnAll -- condemn everything and notify all the chains */ - -static Res traceCondemnAll(Trace trace) -{ - Res res; - Arena arena; - Ring poolNode, nextPoolNode; - - arena = trace->arena; - AVERT(Arena, arena); - - TraceCondemnStart(trace); - - /* Condemn all segments in pools with the GC attribute. */ - RING_FOR(poolNode, &ArenaGlobals(arena)->poolRing, nextPoolNode) { - Pool pool = RING_ELT(Pool, arenaRing, poolNode); - AVERT(Pool, pool); - - if (PoolHasAttr(pool, AttrGC)) { - Ring segNode, nextSegNode; - RING_FOR(segNode, PoolSegRing(pool), nextSegNode) { - Seg seg = SegOfPoolRing(segNode); - - AVERT(Seg, seg); - - res = TraceAddWhite(trace, seg); - if (res != ResOK) - goto failBegin; - - } - } - } - - TraceCondemnEnd(trace); - - if (TraceIsEmpty(trace)) - return ResFAIL; - - return ResOK; - -failBegin: - /* .whiten.fail: If we successfully whitened one or more segments, - * but failed to whiten them all, then the white sets would now be - * inconsistent. This can't happen in practice (at time of writing) - * because all PoolWhiten methods always succeed. If we ever have a - * pool class that fails to whiten a segment, then this assertion - * will be triggered. In that case, we'll have to recover here by - * blackening the segments again. */ - AVER(TraceIsEmpty(trace)); - TraceCondemnEnd(trace); - return res; -} - - -/* Collection control parameters */ - -double TraceWorkFactor = 0.25; - - /* TraceStart -- condemn a set of objects and start collection * * TraceStart should be passed a trace with state TraceINIT, i.e., @@ -1720,8 +1702,8 @@ Res TraceStartCollectAll(Trace *traceReturn, Arena arena, int why) { Trace trace = NULL; Res res; - double finishingTime; - Ring chainNode, nextChainNode; + double mortality, finishingTime; + Ring chainNode, chainNext; AVERT(Arena, arena); AVER(arena->busyTraces == TraceSetEMPTY); @@ -1729,22 +1711,30 @@ Res TraceStartCollectAll(Trace *traceReturn, Arena arena, int why) res = TraceCreate(&trace, arena, why); AVER(res == ResOK); /* succeeds because no other trace is busy */ - /* Notify all the chains. */ - RING_FOR(chainNode, &arena->chainRing, nextChainNode) { - Chain chain = RING_ELT(Chain, chainRing, chainNode); - ChainStartTrace(chain, trace); - } + TraceCondemnStart(trace); - res = traceCondemnAll(trace); + /* Condemn all generations in all chains, plus the top generation. */ + RING_FOR(chainNode, &arena->chainRing, chainNext) { + size_t i; + Chain chain = RING_ELT(Chain, chainRing, chainNode); + AVERT(Chain, chain); + for (i = 0; i < chain->genCount; ++i) { + GenDesc gen = &chain->gens[i]; + AVERT(GenDesc, gen); + GenDescStartTrace(gen, trace); + } + } + GenDescStartTrace(&arena->topGen, trace); + + res = TraceCondemnEnd(&mortality, trace); if(res != ResOK) /* should try some other trace, really @@@@ */ goto failCondemn; - finishingTime = ArenaAvail(arena) - - trace->condemned * (1.0 - arena->topGen.mortality); + finishingTime = ArenaAvail(arena) - trace->condemned * (1.0 - mortality); if(finishingTime < 0) { /* Run out of time, should really try a smaller collection. @@@@ */ finishingTime = 0.0; } - res = TraceStart(trace, arena->topGen.mortality, finishingTime); + res = TraceStart(trace, mortality, finishingTime); if (res != ResOK) goto failStart; *traceReturn = trace; @@ -1815,6 +1805,7 @@ Bool TracePoll(Work *workReturn, Bool *collectWorldReturn, Globals globals, Res TraceDescribe(Trace trace, mps_lib_FILE *stream, Count depth) { + Ring node, next; Res res; const char *state; @@ -1841,7 +1832,6 @@ Res TraceDescribe(Trace trace, mps_lib_FILE *stream, Count depth) " band $U\n", (WriteFU)trace->band, " white $B\n", (WriteFB)trace->white, " mayMove $B\n", (WriteFB)trace->mayMove, - " chain $P\n", (WriteFP)trace->chain, " condemned $U\n", (WriteFU)trace->condemned, " notCondemned $U\n", (WriteFU)trace->notCondemned, " foundation $U\n", (WriteFU)trace->foundation, @@ -1856,6 +1846,14 @@ Res TraceDescribe(Trace trace, mps_lib_FILE *stream, Count depth) " preservedInPlaceSize $U\n", (WriteFU)trace->preservedInPlaceSize, "} Trace $P\n", (WriteFP)trace, NULL); + + RING_FOR(node, &trace->genRing, next) { + GenDesc gen = GenDescOfTraceRing(node, trace); + res = GenDescDescribe(gen, stream, depth + 2); + if (res != ResOK) + return res; + } + return res; }