From f1441b58d151ebb3960f328fa45ea9f7638e5185 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 2 Sep 2015 21:55:24 +0100 Subject: [PATCH] Don't start a trace unless there's work to do. Copied from Perforce Change: 188204 ServerID: perforce.ravenbrook.com --- mps/code/mpm.h | 3 ++- mps/code/policy.c | 2 +- mps/code/trace.c | 31 +++++++++++++++++++++++++++---- mps/code/traceanc.c | 2 +- mps/code/walk.c | 2 +- 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/mps/code/mpm.h b/mps/code/mpm.h index a5ca0a5c300..21eb9d9f5ea 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -393,7 +393,8 @@ extern Bool TraceIdCheck(TraceId id); extern Bool TraceSetCheck(TraceSet ts); extern Bool TraceCheck(Trace trace); extern Res TraceCreate(Trace *traceReturn, Arena arena, int why); -extern void TraceDestroy(Trace trace); +extern void TraceDestroyInit(Trace trace); +extern void TraceDestroyFinished(Trace trace); extern Res TraceAddWhite(Trace trace, Seg seg); extern Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet); diff --git a/mps/code/policy.c b/mps/code/policy.c index 64611a31d11..1052c67f2dc 100644 --- a/mps/code/policy.c +++ b/mps/code/policy.c @@ -258,7 +258,7 @@ Bool PolicyStartTrace(Trace *traceReturn, Arena arena) return FALSE; failCondemn: - TraceDestroy(trace); + TraceDestroyInit(trace); /* This is an unlikely case, but clear the emergency flag so the next attempt starts normally. */ ArenaSetEmergency(arena, FALSE); diff --git a/mps/code/trace.c b/mps/code/trace.c index 005cee87fb2..2896d1af8cb 100644 --- a/mps/code/trace.c +++ b/mps/code/trace.c @@ -158,6 +158,7 @@ Bool TraceCheck(Trace trace) /* Use trace->state to check more invariants. */ switch(trace->state) { case TraceINIT: + CHECKL(!TraceSetIsMember(trace->arena->flippedTraces, trace)); /* @@@@ What can be checked here? */ break; @@ -422,6 +423,9 @@ Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet) } while (SegNext(&seg, arena, seg)); } + if (!haveWhiteSegs) + return ResFAIL; + EVENT3(TraceCondemnZones, trace, condemnedSet, trace->white); /* The trace's white set must be a subset of the condemned set */ @@ -755,7 +759,22 @@ found: } -/* TraceDestroy -- destroy a trace object +/* TraceDestroyInit -- destroy a trace object in state INIT */ + +void TraceDestroyInit(Trace trace) +{ + AVERT(Trace, trace); + AVER(trace->state == TraceINIT); + AVER(trace->condemned == 0); + + EVENT1(TraceDestroy, trace); + + trace->sig = SigInvalid; + trace->arena->busyTraces = TraceSetDel(trace->arena->busyTraces, trace); +} + + +/* TraceDestroyFinished -- destroy a trace object in state FINISHED * * Finish and deallocate a Trace object, freeing up a TraceId. * @@ -764,7 +783,7 @@ found: * etc. would need to be reset to black. This also means the error * paths in this file don't work. @@@@ */ -void TraceDestroy(Trace trace) +void TraceDestroyFinished(Trace trace) { AVERT(Trace, trace); AVER(trace->state == TraceFINISHED); @@ -1555,6 +1574,9 @@ static Res traceCondemnAll(Trace trace) } } + if (!haveWhiteSegs) + return ResFAIL; + /* Notify all the chains. */ RING_FOR(chainNode, &arena->chainRing, nextChainNode) { Chain chain = RING_ELT(Chain, chainRing, chainNode); @@ -1630,6 +1652,7 @@ Res TraceStart(Trace trace, double mortality, double finishingTime) AVER(0.0 <= mortality); AVER(mortality <= 1.0); AVER(finishingTime >= 0.0); + AVER(trace->condemned > 0); arena = trace->arena; @@ -1794,7 +1817,7 @@ failStart: if the assertion isn't hit, so drop through anyway. */ NOTREACHED; failCondemn: - TraceDestroy(trace); + TraceDestroyInit(trace); /* We don't know how long it'll be before another collection. Make sure the next one starts in normal mode. */ ArenaSetEmergency(arena, FALSE); @@ -1841,7 +1864,7 @@ Size TracePoll(Globals globals) && (ArenaEmergency(arena) || traceWorkClock(trace) < pollEnd)); scannedSize = traceWorkClock(trace) - oldScannedSize; if (trace->state == TraceFINISHED) { - TraceDestroy(trace); + TraceDestroyFinished(trace); /* A trace finished, and hopefully reclaimed some memory, so clear any * emergency. */ ArenaSetEmergency(arena, FALSE); diff --git a/mps/code/traceanc.c b/mps/code/traceanc.c index c57500c0b65..aef049ab230 100644 --- a/mps/code/traceanc.c +++ b/mps/code/traceanc.c @@ -583,7 +583,7 @@ void ArenaPark(Globals globals) TRACE_SET_ITER(ti, trace, arena->busyTraces, arena) TraceAdvance(trace); if(trace->state == TraceFINISHED) { - TraceDestroy(trace); + TraceDestroyFinished(trace); } TRACE_SET_ITER_END(ti, trace, arena->busyTraces, arena); } diff --git a/mps/code/walk.c b/mps/code/walk.c index 38278cce1ad..e4542359469 100644 --- a/mps/code/walk.c +++ b/mps/code/walk.c @@ -359,7 +359,7 @@ static Res ArenaRootsWalk(Globals arenaGlobals, mps_roots_stepper_t f, rootsStepClosureFinish(rsc); /* Make this trace look like any other finished trace. */ trace->state = TraceFINISHED; - TraceDestroy(trace); + TraceDestroyFinished(trace); AVER(!ArenaEmergency(arena)); /* There was no allocation. */ return res;