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;