diff --git a/mps/code/mpm.h b/mps/code/mpm.h index a031792ffc4..2ecef0b1852 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -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); diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index 57e0f4a24cc..c63ca4320f1 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -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 */ diff --git a/mps/code/mpmtypes.h b/mps/code/mpmtypes.h index 9d6e54c990e..15786d6244a 100644 --- a/mps/code/mpmtypes.h +++ b/mps/code/mpmtypes.h @@ -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, diff --git a/mps/code/seg.c b/mps/code/seg.c index 3debf913d67..b5b2a46b76a 100644 --- a/mps/code/seg.c +++ b/mps/code/seg.c @@ -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); diff --git a/mps/code/trace.c b/mps/code/trace.c index 33f94efb55d..0a493e89bdb 100644 --- a/mps/code/trace.c +++ b/mps/code/trace.c @@ -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 */ diff --git a/mps/design/seg.txt b/mps/design/seg.txt index 70c62a2c7dd..e4f64404dbc 100644 --- a/mps/design/seg.txt +++ b/mps/design/seg.txt @@ -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 .....................