diff --git a/mps/code/config.h b/mps/code/config.h index ac5d7a849ec..59a44ee3780 100644 --- a/mps/code/config.h +++ b/mps/code/config.h @@ -635,6 +635,12 @@ { 36 * 1024, 0.45 } /* second gen, after which dynamic */ \ } +/* 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 #endif /* config_h */ diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index 219858f0f54..ba0be7aba58 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -300,6 +300,7 @@ 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 ef930071850..e5923c170f7 100644 --- a/mps/code/seg.c +++ b/mps/code/seg.c @@ -1082,6 +1082,7 @@ 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 4f5b1477d81..bbe09b2d2c6 100644 --- a/mps/code/trace.c +++ b/mps/code/trace.c @@ -1105,6 +1105,7 @@ 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. */ @@ -1135,8 +1136,18 @@ static Res traceScanSegRes(TraceSet ts, Rank rank, Arena arena, Seg seg) * scan, consistent with the recorded SegSummary? */ 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; + } + } else { + ((GCSeg)seg)->unnecessaryScans = 0; + } - if (arena->incremental) { + if (considerBarrier) { if(res != ResOK || !wasTotal) { /* scan was partial, so... */ /* scanned summary should be ORed into segment summary. */