Short-circuit the cases where we set the greyness or summary of a segment to the same as it was before in all cases, rather than just in a few restricted cases in amc.

This was the result of noticing a large number of SetSetGrey events that set the segment to the same greyness when scanning ambiguous references.

Copied from Perforce
 Change: 179567
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Richard Brooksby 2012-09-19 20:04:41 +01:00
parent 847bd516aa
commit 85f3d6bbb4
3 changed files with 31 additions and 38 deletions

View file

@ -1664,8 +1664,7 @@ static void amcFixInPlace(Pool pool, Seg seg, ScanState ss, Ref *refIO)
return;
}
SegSetNailed(seg, TraceSetUnion(SegNailed(seg), ss->traces));
if(SegRankSet(seg) != RankSetEMPTY)
SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces));
SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces));
}
@ -1727,9 +1726,6 @@ Res AMCFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
Buffer buffer; /* buffer to allocate new copy into */
amcGen gen; /* generation of old copy of object */
TraceSet grey; /* greyness of object being relocated */
TraceSet toGrey; /* greyness of object's destination */
RefSet summary; /* summary of object being relocated */
RefSet toSummary; /* summary of object's destination */
Seg toSeg; /* segment to which object is being relocated */
/* <design/trace/#fix.noaver> */
@ -1786,9 +1782,7 @@ Res AMCFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
/* Segment only needs greying if there are new traces for */
/* which we are nailing. */
if(!TraceSetSub(ss->traces, SegNailed(seg))) {
if(SegRankSet(seg) != RankSetEMPTY) {
SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces));
}
SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces));
SegSetNailed(seg, TraceSetUnion(SegNailed(seg), ss->traces));
}
res = ResOK;
@ -1823,16 +1817,8 @@ Res AMCFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
/* Since we're moving an object from one segment to another, */
/* union the greyness and the summaries together. */
grey = TraceSetUnion(ss->traces, SegGrey(seg));
toGrey = SegGrey(toSeg);
if(TraceSetDiff(grey, toGrey) != TraceSetEMPTY
&& SegRankSet(seg) != RankSetEMPTY) {
SegSetGrey(toSeg, TraceSetUnion(toGrey, grey));
}
summary = SegSummary(seg);
toSummary = SegSummary(toSeg);
if(RefSetDiff(summary, toSummary) != RefSetEMPTY) {
SegSetSummary(toSeg, RefSetUnion(toSummary, summary));
}
SegSetGrey(toSeg, TraceSetUnion(SegGrey(toSeg), grey));
SegSetSummary(toSeg, RefSetUnion(SegSummary(toSeg), SegSummary(seg)));
/* <design/trace/#fix.copy> */
(void)AddrCopy(newRef, ref, length); /* .exposed.seg */
@ -1877,9 +1863,6 @@ static Res AMCHeaderFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
Buffer buffer; /* buffer to allocate new copy into */
amcGen gen; /* generation of old copy of object */
TraceSet grey; /* greyness of object being relocated */
TraceSet toGrey; /* greyness of object's destination */
RefSet summary; /* summary of object being relocated */
RefSet toSummary; /* summary of object's destination */
Seg toSeg; /* segment to which object is being relocated */
/* <design/trace/#fix.noaver> */
@ -1937,8 +1920,7 @@ static Res AMCHeaderFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
/* Segment only needs greying if there are new traces for */
/* which we are nailing. */
if(!TraceSetSub(ss->traces, SegNailed(seg))) {
if(SegRankSet(seg) != RankSetEMPTY)
SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces));
SegSetGrey(seg, TraceSetUnion(SegGrey(seg), ss->traces));
SegSetNailed(seg, TraceSetUnion(SegNailed(seg), ss->traces));
}
res = ResOK;
@ -1976,14 +1958,8 @@ static Res AMCHeaderFix(Pool pool, ScanState ss, Seg seg, Ref *refIO)
/* Since we're moving an object from one segment to another, */
/* union the greyness and the summaries together. */
grey = TraceSetUnion(ss->traces, SegGrey(seg));
toGrey = SegGrey(toSeg);
if(TraceSetDiff(grey, toGrey) != TraceSetEMPTY
&& SegRankSet(seg) != RankSetEMPTY)
SegSetGrey(toSeg, TraceSetUnion(toGrey, grey));
summary = SegSummary(seg);
toSummary = SegSummary(toSeg);
if(RefSetDiff(summary, toSummary) != RefSetEMPTY)
SegSetSummary(toSeg, RefSetUnion(toSummary, summary));
SegSetGrey(toSeg, TraceSetUnion(SegGrey(toSeg), grey));
SegSetSummary(toSeg, RefSetUnion(SegSummary(toSeg), SegSummary(seg)));
/* <design/trace/#fix.copy> */
(void)AddrCopy(newBase, AddrSub(ref, headerSize), length); /* .exposed.seg */

View file

@ -267,7 +267,12 @@ void SegSetGrey(Seg seg, TraceSet grey)
{
AVERT(Seg, seg);
AVER(TraceSetCheck(grey));
seg->class->setGrey(seg, grey);
AVER(SegRankSet(seg) != RankSetEMPTY);
/* Don't dispatch to the class method if there's no actual change in
greyness, or if the segment doesn't contain any references. */
if (grey != SegGrey(seg) && SegRankSet(seg) != RankSetEMPTY)
seg->class->setGrey(seg, grey);
}
@ -295,6 +300,7 @@ void SegSetRankSet(Seg seg, RankSet rankSet)
{
AVERT(Seg, seg);
AVER(RankSetCheck(rankSet));
AVER(rankSet != RankSetEMPTY || SegSummary(seg) == RefSetEMPTY);
seg->class->setRankSet(seg, rankSet);
}
@ -304,11 +310,13 @@ void SegSetRankSet(Seg seg, RankSet rankSet)
void SegSetSummary(Seg seg, RefSet summary)
{
AVERT(Seg, seg);
AVER(summary == RefSetEMPTY || SegRankSet(seg) != RankSetEMPTY);
#ifdef PROTECTION_NONE
summary = RefSetUNIV;
#endif
seg->class->setSummary(seg, summary);
if (summary != SegSummary(seg))
seg->class->setSummary(seg, summary);
}
@ -1150,6 +1158,10 @@ static void gcSegSetGreyInternal(Seg seg, TraceSet oldGrey, TraceSet grey)
AVER(RankSetIsSingle(seg->rankSet));
for(rank = 0; rank < RankLIMIT; ++rank)
if (RankSetIsMember(seg->rankSet, rank)) {
/* NOTE: We push the segment onto the front of the queue, so that
we preserve some locality of scanning, and so that we tend to
forward objects that are closely linked to the same or nearby
segments. */
RingInsert(ArenaGreyRing(arena, rank), &gcseg->greyRing);
break;
}

View file

@ -525,13 +525,15 @@ static Res rootFlip(Root root, void *p)
* The main job of traceFlip is to scan references which can't be protected
* from the mutator, changing the colour of the mutator from grey to black
* with respect to a trace. The mutator threads are suspended while this
* is happening, and the mutator perceives and instantaneous change in all
* is happening, and the mutator perceives an instantaneous change in all
* the references, enforced by the shield (barrier) system.
*
* NOTE: We don't have a way to shield the roots, so they are all scanned
* here. This is a coincidence. There is no particular reason that the
* roots have to be scanned at flip time. (The thread registers are unlikely
* ever to be protectable on stock hardware, however.)
* here. This is a coincidence. There is no theoretical reason that the
* roots have to be scanned at flip time, provided we could protect them
* from the mutator. (The thread registers are unlikely ever to be
* protectable on stock hardware, however, as they were -- kind of -- on
* Lisp machines.)
*
* NOTE: Ambiguous references may only exist in roots, because we can't
* shield the exact roots and defer them for later scanning (after ambiguous
@ -1254,9 +1256,12 @@ void TraceSegAccess(Arena arena, Seg seg, AccessSet mode)
Trace trace;
TraceId ti;
Rank rank;
TraceSet traces;
AVER(SegRankSet(seg) != RankSetEMPTY);
/* Pick set of traces to scan for: */
TraceSet traces = arena->flippedTraces;
traces = arena->flippedTraces;
rank = TraceRankForAccess(arena, seg);
res = traceScanSeg(traces, rank, arena, seg);