mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-03-26 08:41:47 -07:00
Tidying up naming of write barrier deferral.
Copied from Perforce Change: 189960 ServerID: perforce.ravenbrook.com
This commit is contained in:
parent
0b3c65766e
commit
83fc7866c9
4 changed files with 46 additions and 28 deletions
|
|
@ -659,20 +659,32 @@
|
|||
{ 36 * 1024, 0.45 } /* second gen, after which dynamic */ \
|
||||
}
|
||||
|
||||
/* Experimental Scan Barrier threshold
|
||||
/* Write barrier deferral
|
||||
*
|
||||
* Defer using the write barrier for the remembered set until a number
|
||||
* of unnecessary scans have been performed on a segment. Avoids
|
||||
* memory protection costs when scanning might be cheaper. See job003975.
|
||||
*
|
||||
* TODO: These settings were determined by trial and error, but should
|
||||
* be based on measurement of the protection overhead on each
|
||||
* platform. We know it's extremely different between OS X and
|
||||
* Windows, for example.
|
||||
*
|
||||
* TODO: Consider basing the count on the amount of time that has
|
||||
* passed in the mutator rather than the number of scans.
|
||||
*/
|
||||
/* Number of bits needed to keep the seg scan count */
|
||||
#define SEG_SCANS_BITS 10
|
||||
|
||||
/* Number of bits needed to keep the write barrier deferral count */
|
||||
#define WB_DEFER_BITS 3
|
||||
/* The number of unecessary scans performed, before raising the write
|
||||
* barrier to remember the refset summary. */
|
||||
#define SEG_SCANS_INIT 3
|
||||
barrier to maintian the remembered set. */
|
||||
#define WB_DEFER_INIT 3
|
||||
/* The number of unecessary scans performed, before raising the write
|
||||
* barrier to remember the refset summary, after a necessary scan */
|
||||
#define SEG_SCANS_AFTER_NEEDED_SCAN 3
|
||||
barrier to remember the refset summary, after a necessary scan */
|
||||
#define WB_DEFER_DELAY WB_DEFER_INIT
|
||||
/* The number of unecessary scans performed, before raising the write
|
||||
* barrier to remember the refset summary, after a barrier hit */
|
||||
#define SEG_SCANS_AFTER_HIT 1
|
||||
#define WB_DEFER_AFTER_HIT 1
|
||||
|
||||
#endif /* config_h */
|
||||
|
||||
|
|
|
|||
|
|
@ -281,7 +281,7 @@ typedef struct SegStruct { /* segment structure */
|
|||
TraceSet white : TraceLIMIT; /* traces for which seg is white */
|
||||
TraceSet nailed : TraceLIMIT; /* traces for which seg has nailed objects */
|
||||
RankSet rankSet : RankLIMIT; /* ranks of references in this seg */
|
||||
unsigned scans : SEG_SCANS_BITS; /* use write barrier after this many scans */
|
||||
Count defer : WB_DEFER_BITS; /* defer write barrier for this many scans */
|
||||
} SegStruct;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ static Res SegInit(Seg seg, Pool pool, Addr base, Size size,
|
|||
seg->grey = TraceSetEMPTY;
|
||||
seg->pm = AccessSetEMPTY;
|
||||
seg->sm = AccessSetEMPTY;
|
||||
seg->scans = SEG_SCANS_INIT;
|
||||
seg->defer = WB_DEFER_INIT;
|
||||
seg->depth = 0;
|
||||
seg->firstTract = NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -1089,6 +1089,7 @@ static Res traceScanSegRes(TraceSet ts, Rank rank, Arena arena, Seg seg)
|
|||
Bool wasTotal;
|
||||
ZoneSet white;
|
||||
Res res;
|
||||
RefSet summary;
|
||||
|
||||
/* The reason for scanning a segment is that it's grey. */
|
||||
AVER(TraceSetInter(ts, SegGrey(seg)) != TraceSetEMPTY);
|
||||
|
|
@ -1134,28 +1135,33 @@ static Res traceScanSegRes(TraceSet ts, Rank rank, Arena arena, Seg seg)
|
|||
* scan, consistent with the recorded SegSummary?
|
||||
*/
|
||||
AVER(RefSetSub(ScanStateUnfixedSummary(ss), SegSummary(seg)));
|
||||
|
||||
/* Remembered set and write barrier */
|
||||
/* Was the scan necessary? Did the segment refer to the white set */
|
||||
if (ZoneSetInter(ScanStateUnfixedSummary(ss), white) == ZoneSetEMPTY) {
|
||||
/* a scan was not necessary */
|
||||
if (seg->scans > 0)
|
||||
seg->scans--;
|
||||
if (seg->defer > 0)
|
||||
--seg->defer;
|
||||
} else {
|
||||
if (seg->scans < SEG_SCANS_AFTER_NEEDED_SCAN)
|
||||
seg->scans = SEG_SCANS_AFTER_NEEDED_SCAN;
|
||||
if (seg->defer < WB_DEFER_DELAY)
|
||||
seg->defer = WB_DEFER_DELAY;
|
||||
}
|
||||
|
||||
if (seg->scans == 0) {
|
||||
if(res != ResOK || !wasTotal) {
|
||||
/* scan was partial, so... */
|
||||
/* scanned summary should be ORed into segment summary. */
|
||||
SegSetSummary(seg, RefSetUnion(SegSummary(seg), ScanStateSummary(ss)));
|
||||
} else {
|
||||
/* all objects on segment have been scanned, so... */
|
||||
/* scanned summary should replace the segment summary. */
|
||||
SegSetSummary(seg, ScanStateSummary(ss));
|
||||
}
|
||||
|
||||
/* Only apply the write barrier if it is not deferred. */
|
||||
/* TODO: This discards information we collected during
|
||||
scanning. Consider keeping the summary but changing the
|
||||
invariant on shielding instead. */
|
||||
if (seg->defer == 0) {
|
||||
/* If we scanned every reference in the segment then we have a
|
||||
complete summary we can set. Otherwise, we just have
|
||||
information about more zones that the segment refers to. */
|
||||
if (res == ResOK && wasTotal)
|
||||
summary = ScanStateSummary(ss);
|
||||
else
|
||||
summary = RefSetUnion(SegSummary(seg), ScanStateSummary(ss));
|
||||
} else {
|
||||
SegSetSummary(seg, RefSetUNIV);
|
||||
summary = RefSetUNIV;
|
||||
}
|
||||
SegSetSummary(seg, summary);
|
||||
|
||||
ScanStateFinish(ss);
|
||||
}
|
||||
|
|
@ -1215,7 +1221,7 @@ void TraceSegAccess(Arena arena, Seg seg, AccessSet mode)
|
|||
EVENT3(TraceAccess, arena, seg, mode);
|
||||
|
||||
if ((mode & SegSM(seg) & AccessWRITE) != 0) /* write barrier? */
|
||||
seg->scans = SEG_SCANS_AFTER_HIT;
|
||||
seg->defer = WB_DEFER_AFTER_HIT;
|
||||
|
||||
if((mode & SegSM(seg) & AccessREAD) != 0) { /* read barrier? */
|
||||
Trace trace;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue