From b4460043e6a9f0fcc6b513094c68c3835a7b8b0d Mon Sep 17 00:00:00 2001
From: David Lovemore
Date: Wed, 27 Aug 2014 11:21:18 +0100
Subject: [PATCH] Added more control over write barrier. in particular
separated scans after a hit.
Copied from Perforce
Change: 186988
ServerID: perforce.ravenbrook.com
---
mps/code/config.h | 14 +++++++++++---
mps/code/mpmst.h | 2 +-
mps/code/seg.c | 2 +-
mps/code/trace.c | 16 ++++++++--------
4 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/mps/code/config.h b/mps/code/config.h
index 59a44ee3780..f9ce6fb9396 100644
--- a/mps/code/config.h
+++ b/mps/code/config.h
@@ -637,10 +637,18 @@
/* Experimental Scan Barrier threshold
*
- * The number of unecessary scans performed, before raising the write
- * barrier to remember the refset summary.
*/
-#define TRACE_SCAN_BARRIER_THRESHOLD 3
+/* Number of bits needed to keep the seg scan count */
+#define SEG_SCANS_BITS 10
+/* The number of unecessary scans performed, before raising the write
+ * barrier to remember the refset summary. */
+#define SEG_SCANS_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
+/* 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
#endif /* config_h */
diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h
index ba0be7aba58..39625a470f6 100644
--- a/mps/code/mpmst.h
+++ b/mps/code/mpmst.h
@@ -285,6 +285,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 */
} SegStruct;
@@ -300,7 +301,6 @@ typedef struct GCSegStruct { /* GC segment structure */
RingStruct greyRing; /* link in list of grey segs */
RefSet summary; /* summary of references out of seg */
Buffer buffer; /* non-NULL if seg is buffered */
- unsigned unnecessaryScans; /* consecutive unnecessary scans performed */
Sig sig; /* */
} GCSegStruct;
diff --git a/mps/code/seg.c b/mps/code/seg.c
index e5923c170f7..99e3c48e47c 100644
--- a/mps/code/seg.c
+++ b/mps/code/seg.c
@@ -160,6 +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->depth = 0;
seg->firstTract = NULL;
@@ -1082,7 +1083,6 @@ static Res gcSegInit(Seg seg, Pool pool, Addr base, Size size,
gcseg->summary = RefSetEMPTY;
gcseg->buffer = NULL;
- gcseg->unnecessaryScans = 0;
RingInit(&gcseg->greyRing);
gcseg->sig = GCSegSig;
diff --git a/mps/code/trace.c b/mps/code/trace.c
index bbe09b2d2c6..2856d3339cb 100644
--- a/mps/code/trace.c
+++ b/mps/code/trace.c
@@ -1105,7 +1105,6 @@ static Res traceScanSegRes(TraceSet ts, Rank rank, Arena arena, Seg seg)
} else { /* scan it */
ScanStateStruct ssStruct;
ScanState ss = &ssStruct;
- Bool considerBarrier = FALSE;
ScanStateInit(ss, ts, arena, rank, white);
/* Expose the segment to make sure we can scan it. */
@@ -1138,16 +1137,14 @@ static Res traceScanSegRes(TraceSet ts, Rank rank, Arena arena, Seg seg)
AVER(RefSetSub(ScanStateUnfixedSummary(ss), SegSummary(seg)));
if (ZoneSetInter(ScanStateUnfixedSummary(ss), white) == ZoneSetEMPTY) {
/* a scan was not necessary */
- if (((GCSeg)seg)->unnecessaryScans < TRACE_SCAN_BARRIER_THRESHOLD) {
- ((GCSeg)seg)->unnecessaryScans++;
- } else {
- considerBarrier = TRUE;
- }
+ if (seg->scans > 0)
+ seg->scans--;
} else {
- ((GCSeg)seg)->unnecessaryScans = 0;
+ if (seg->scans < SEG_SCANS_AFTER_NEEDED_SCAN)
+ seg->scans = SEG_SCANS_AFTER_NEEDED_SCAN;
}
- if (considerBarrier) {
+ if (seg->scans == 0) {
if(res != ResOK || !wasTotal) {
/* scan was partial, so... */
/* scanned summary should be ORed into segment summary. */
@@ -1217,6 +1214,9 @@ 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;
+
if((mode & SegSM(seg) & AccessREAD) != 0) { /* read barrier? */
Trace trace;
TraceId ti;