From 886e96ba8e0bc2fbda89ce7c8e417ff5c5df23a8 Mon Sep 17 00:00:00 2001 From: David Lovemore Date: Mon, 3 Sep 2012 17:05:51 +0100 Subject: Fix weak band assert. we now trace weak segments as weak on a fault if we are in the weak band. Copied from Perforce Change: 179210 ServerID: perforce.ravenbrook.com --- mps/code/trace.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 10 deletions(-) (limited to 'mps/code/trace.c') diff --git a/mps/code/trace.c b/mps/code/trace.c index 0f8d84ba3ac..3fddaec8d33 100644 --- a/mps/code/trace.c +++ b/mps/code/trace.c @@ -827,7 +827,75 @@ static void traceReclaim(Trace trace) (void)TraceIdMessagesCreate(arena, trace->ti); } +/* TraceRankForAccess -- Returns rank to scan at if we hit a barrier. + * + * We assume a single trace as otherwise we need to implement rank + * filters on scanning. + * + * .scan.conservative: It's safe to scan at EXACT unless the band is + * WEAK and in that case the segment should be weak. + * + * If the trace band is EXACT then we scan EXACT. This might prevent + * finalisation messages and may preserve objects pointed to only by weak + * references but tough luck -- the mutator wants to look. + * + * If the trace band is FINAL and the segment is FINAL, we scan it FINAL. + * Any objects not yet preserved deserve to die, and we're only giving + * them a temporary reprieve. All the objects on the segment should be FINAL, + * otherwise they might get sent finalization messages. + * + * If the trace band is FINAL, and the segment is not FINAL, we scan at EXACT. + * This is safe to do for FINAL and WEAK references. + * + * If the trace band is WEAK then the segment must be weak only, and we + * scan at WEAK. All other segments for this trace should be scanned by now. + * We must scan at WEAK to avoid bringing any objects back to life. + * + * See the message + * for a description of these semantics. + */ +Rank TraceRankForAccess(Arena arena, Seg seg) +{ + TraceSet ts; + Trace trace; + TraceId ti; + Rank band; + RankSet rankSet; + AVERT(Arena, arena); + AVERT(Seg, seg); + + band = RankAMBIG; /* initialize band to avoid warning */ + ts = arena->flippedTraces; + AVER(TraceSetIsSingle(ts)); + TRACE_SET_ITER(ti, trace, ts, arena) + band = traceBand(trace); + TRACE_SET_ITER_END(ti, trace, ts, arena); + rankSet = SegRankSet(seg); + switch(band) { + case RankAMBIG: + NOTREACHED; + break; + case RankEXACT: + return RankEXACT; + case RankFINAL: + if(rankSet == RankSetSingle(RankFINAL)) { + return RankFINAL; + } + /* It's safe to scan at exact in the final band so do so if there are + * any non-final references. */ + return RankEXACT; + case RankWEAK: + AVER(rankSet == RankSetSingle(RankWEAK)); + return RankWEAK; + default: + NOTREACHED; + break; + } + NOTREACHED; + return RankEXACT; +} + /* traceFindGrey -- find a grey segment * * This function finds the next segment to scan. It does this according @@ -870,7 +938,10 @@ static void traceReclaim(Trace trace) * whilst working in this band. That's what we check, although we * expect to have to change the check if we introduce more ranks, or * start changing the semantics of them. A flag is used to implement - * this check. + * this check. See . + * + * For further discussion on the semantics of rank based tracing see + * */ static Bool traceFindGrey(Seg *segReturn, Rank *rankReturn, @@ -1131,8 +1202,6 @@ static void traceScanSeg(TraceSet ts, Rank rank, Arena arena, Seg seg) void TraceSegAccess(Arena arena, Seg seg, AccessSet mode) { - TraceId ti; - AVERT(Arena, arena); AVERT(Seg, seg); @@ -1149,13 +1218,15 @@ void TraceSegAccess(Arena arena, Seg seg, AccessSet mode) EVENT_PPU(TraceAccess, arena, seg, mode); if((mode & SegSM(seg) & AccessREAD) != 0) { /* read barrier? */ + Trace trace; + TraceId ti; + Rank rank; + /* Pick set of traces to scan for: */ TraceSet traces = arena->flippedTraces; - - /* .scan.conservative: At the moment we scan at RankEXACT. Really */ - /* we should be scanning at the "phase" of the trace, which is the */ - /* minimum rank of all grey segments. (see request.mps.170160) */ - traceScanSeg(traces, RankEXACT, arena, seg); + + rank = TraceRankForAccess(arena, seg); + traceScanSeg(traces, rank, arena, seg); /* The pool should've done the job of removing the greyness that */ /* was causing the segment to be protected, so that the mutator */ @@ -1163,8 +1234,6 @@ void TraceSegAccess(Arena arena, Seg seg, AccessSet mode) AVER(TraceSetInter(SegGrey(seg), traces) == TraceSetEMPTY); STATISTIC_STAT({ - Trace trace; - TRACE_SET_ITER(ti, trace, traces, arena) ++trace->readBarrierHitCount; TRACE_SET_ITER_END(ti, trace, traces, arena); -- cgit v1.2.1