New generic function segflip allows the segment to decide how to handle a trace that’s about to flip.

Copied from Perforce
 Change: 194000
This commit is contained in:
Gareth Rees 2018-06-20 10:23:16 +01:00
parent e93949aeef
commit a5ddfca39b
6 changed files with 64 additions and 6 deletions

View file

@ -658,6 +658,7 @@ extern Bool SegNext(Seg *segReturn, Arena arena, Seg seg);
extern Bool SegNextOfRing(Seg *segReturn, Arena arena, Pool pool, Ring next);
extern void SegSetWhite(Seg seg, TraceSet white);
extern void SegSetGrey(Seg seg, TraceSet grey);
extern void SegFlip(Seg seg, Trace trace);
extern void SegSetRankSet(Seg seg, RankSet rankSet);
extern void SegSetRankAndSummary(Seg seg, RankSet rankSet, RefSet summary);
extern Res SegMerge(Seg *mergedSegReturn, Seg segLo, Seg segHi);

View file

@ -223,6 +223,7 @@ typedef struct SegClassStruct {
SegSetBufferMethod setBuffer; /* set the segment buffer */
SegUnsetBufferMethod unsetBuffer; /* unset the segment buffer */
SegSetGreyMethod setGrey; /* change greyness of segment */
SegFlipMethod flip; /* raise barrier for a flipped trace */
SegSetWhiteMethod setWhite; /* change whiteness of segment */
SegSetRankSetMethod setRankSet; /* change rank set of segment */
SegSetRankSummaryMethod setRankSummary; /* change rank set & summary */

View file

@ -152,6 +152,7 @@ typedef void (*FreeBlockVisitor)(Addr base, Addr limit, Pool pool, void *p);
typedef Res (*SegInitMethod)(Seg seg, Pool pool, Addr base, Size size,
ArgList args);
typedef void (*SegSetGreyMethod)(Seg seg, TraceSet grey);
typedef void (*SegFlipMethod)(Seg seg, Trace trace);
typedef void (*SegSetWhiteMethod)(Seg seg, TraceSet white);
typedef void (*SegSetRankSetMethod)(Seg seg, RankSet rankSet);
typedef void (*SegSetRankSummaryMethod)(Seg seg, RankSet rankSet,

View file

@ -257,6 +257,20 @@ void SegSetGrey(Seg seg, TraceSet grey)
}
/* SegFlip -- update barriers for trace that's about to flip */
void SegFlip(Seg seg, Trace trace)
{
AVERT(Seg, seg);
AVERT(Trace, trace);
/* Don't dispatch to the class method unless the segment is grey for
the trace that's about to flip, and contains references. */
if (TraceSetIsMember(SegGrey(seg), trace) && SegRankSet(seg) != RankSetEMPTY)
Method(Seg, seg, flip)(seg, trace);
}
/* SegSetWhite -- change the whiteness of a segment
*
* Sets the segment whiteness to the trace set ts.
@ -788,6 +802,16 @@ static void segNoSetGrey(Seg seg, TraceSet grey)
}
/* segTrivFlip -- ignore trace that's about to flip */
static void segTrivFlip(Seg seg, Trace trace)
{
AVERT(Seg, seg);
AVERT(Trace, trace);
AVER(seg->rankSet != RankSetEMPTY);
}
/* segNoSetWhite -- non-method to change the whiteness of a segment */
static void segNoSetWhite(Seg seg, TraceSet white)
@ -1216,6 +1240,29 @@ static void mutatorSegSetGrey(Seg seg, TraceSet grey)
}
}
/* mutatorSegFlip -- update barriers for a trace that's about to flip */
static void mutatorSegFlip(Seg seg, Trace trace)
{
TraceSet flippedTraces;
Arena arena;
NextMethod(Seg, MutatorSeg, flip)(seg, trace);
/* Raise the read barrier if the segment was not grey for any
currently flipped trace. */
arena = PoolArena(SegPool(seg));
flippedTraces = arena->flippedTraces;
if (TraceSetInter(SegGrey(seg), flippedTraces) == TraceSetEMPTY) {
ShieldRaise(arena, seg, AccessREAD);
} else {
/* If the segment is grey for some currently flipped trace then
the read barrier must already have been raised, either in this
method or in mutatorSegSetGrey. */
AVER(SegSM(seg) & AccessREAD);
}
}
/* gcSegSetWhite -- GCSeg method to change whiteness of a segment
*
@ -1644,6 +1691,7 @@ DEFINE_CLASS(Seg, Seg, klass)
klass->setBuffer = segNoSetBuffer;
klass->unsetBuffer = segNoUnsetBuffer;
klass->setGrey = segNoSetGrey;
klass->flip = segTrivFlip;
klass->setWhite = segNoSetWhite;
klass->setRankSet = segNoSetRankSet;
klass->setRankSummary = segNoSetRankSummary;
@ -1688,6 +1736,7 @@ DEFINE_CLASS(Seg, MutatorSeg, klass)
INHERIT_CLASS(klass, MutatorSeg, GCSeg);
klass->setSummary = mutatorSegSetSummary;
klass->setGrey = mutatorSegSetGrey;
klass->flip = mutatorSegFlip;
klass->setRankSet = mutatorSegSetRankSet;
klass->setRankSummary = mutatorSegSetRankSummary;
AVERT(SegClass, klass);

View file

@ -590,15 +590,11 @@ static Res traceFlip(Trace trace)
/* drj 2003-02-19) */
/* Now that the mutator is black we must prevent it from reading */
/* grey objects so that it can't obtain white pointers. This is */
/* achieved by read protecting all segments containing objects */
/* which are grey for any of the flipped traces. */
/* grey objects so that it can't obtain white pointers. */
for(rank = RankMIN; rank < RankLIMIT; ++rank)
RING_FOR(node, ArenaGreyRing(arena, rank), nextNode) {
Seg seg = SegOfGreyRing(node);
if(TraceSetInter(SegGrey(seg), arena->flippedTraces) == TraceSetEMPTY
&& TraceSetIsMember(SegGrey(seg), trace))
ShieldRaise(arena, seg, AccessREAD);
SegFlip(seg, trace);
}
/* @@@@ When write barrier collection is implemented, this is where */

View file

@ -233,6 +233,16 @@ of ``segLo`` and ``segHi``.
Extensibility
-------------
Garbage collection
..................
``typedef void (*SegFlipMethod)(Seg seg, Trace trace)``
_`.method.flip`: Raise the read barrier, if necessary, for a trace
that's about to flip and for which the segment is grey and potentially
contains references.
Splitting and merging
.....................