diff --git a/mps/code/format.c b/mps/code/format.c index 07a8319082a..26b3e4bb751 100644 --- a/mps/code/format.c +++ b/mps/code/format.c @@ -190,6 +190,36 @@ Arena FormatArena(Format format) } +/* FormatScan -- scan formatted objects for references + * + * This is a wrapper for formatted objects scanning functions, which + * should not otherwise be called directly from within the MPS. This + * function checks arguments and takes care of accounting for the + * scanned memory. + * + * c.f. TraceScanArea() + */ + +Res FormatScan(Format format, ScanState ss, Addr base, Addr limit) +{ + /* TODO: How critical are these? */ + AVERT_CRITICAL(Format, format); + AVERT_CRITICAL(ScanState, ss); + AVER_CRITICAL(base != NULL); + AVER_CRITICAL(limit != NULL); + AVER_CRITICAL(base < limit); + + /* TODO: EVENT here? */ + + /* scannedSize is accumulated whether or not format->scan succeeds, + so it's safe to accumulate now so that we can tail-call + format->scan. */ + ss->scannedSize += AddrOffset(base, limit); + + return format->scan(&ss->ss_s, base, limit); +} + + /* FormatDescribe -- describe a format */ Res FormatDescribe(Format format, mps_lib_FILE *stream, Count depth) diff --git a/mps/code/mpm.h b/mps/code/mpm.h index 3e296dacb2f..214ad8c4cad 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -845,6 +845,7 @@ extern Res FormatCreate(Format *formatReturn, Arena arena, ArgList args); extern void FormatDestroy(Format format); extern Arena FormatArena(Format format); extern Res FormatDescribe(Format format, mps_lib_FILE *stream, Count depth); +extern Res FormatScan(Format format, ScanState ss, Addr base, Addr limit); /* Reference Interface -- see */ diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c index dfe3cfc37d9..28fcbd7e8bd 100644 --- a/mps/code/poolamc.c +++ b/mps/code/poolamc.c @@ -1249,7 +1249,7 @@ static Res AMCWhiten(Pool pool, Trace trace, Seg seg) * addresses in a nailed segment. */ static Res amcScanNailedRange(Bool *totalReturn, Bool *moreReturn, - Size *bytesScanned, ScanState ss, + ScanState ss, AMC amc, Nailboard board, Addr base, Addr limit) { @@ -1265,14 +1265,12 @@ static Res amcScanNailedRange(Bool *totalReturn, Bool *moreReturn, Addr q; q = (*format->skip)(p); if ((*amc->pinned)(amc, board, p, q)) { - Res res; - res = (*format->scan)(&ss->ss_s, p, q); + Res res = FormatScan(format, ss, p, q); if(res != ResOK) { *totalReturn = FALSE; *moreReturn = TRUE; return res; } - *bytesScanned += AddrOffset(p, q); } else { *totalReturn = FALSE; } @@ -1297,7 +1295,6 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn, ScanState ss, Seg seg, AMC amc) { Addr p, limit; - Size bytesScanned = 0; Nailboard board; Res res; @@ -1314,7 +1311,7 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn, AVER(p == limit); goto returnGood; } - res = amcScanNailedRange(totalReturn, moreReturn, &bytesScanned, + res = amcScanNailedRange(totalReturn, moreReturn, ss, amc, board, p, limit); if (res != ResOK) return res; @@ -1323,7 +1320,7 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn, limit = SegLimit(seg); /* @@@@ Shouldn't p be set to BufferLimit here?! */ - res = amcScanNailedRange(totalReturn, moreReturn, &bytesScanned, + res = amcScanNailedRange(totalReturn, moreReturn, ss, amc, board, p, limit); if (res != ResOK) return res; @@ -1331,8 +1328,6 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn, returnGood: EVENT3(AMCScanEnd, amc, seg, ss); /* TODO: consider using own event */ - AVER(bytesScanned <= SegSize(seg)); - ss->scannedSize += bytesScanned; *moreReturn = NailboardNewNails(board); return ResOK; } @@ -1423,12 +1418,11 @@ static Res AMCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) *totalReturn = TRUE; return ResOK; } - res = (*format->scan)(&ss->ss_s, base, limit); + res = FormatScan(format, ss, base, limit); if(res != ResOK) { *totalReturn = FALSE; return res; } - ss->scannedSize += AddrOffset(base, limit); base = limit; } @@ -1437,14 +1431,13 @@ static Res AMCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) AVER(SegBase(seg) <= base); AVER(base <= AddrAdd(SegLimit(seg), format->headerSize)); if(base < limit) { - res = (*format->scan)(&ss->ss_s, base, limit); + res = FormatScan(format, ss, base, limit); if(res != ResOK) { *totalReturn = FALSE; return res; } } - ss->scannedSize += AddrOffset(base, limit); EVENT3(AMCScanEnd, amc, seg, ss); *totalReturn = TRUE; diff --git a/mps/code/poolams.c b/mps/code/poolams.c index 3f7f170ddbc..d3ecfa47028 100644 --- a/mps/code/poolams.c +++ b/mps/code/poolams.c @@ -1318,12 +1318,12 @@ static Res amsScanObject(Seg seg, Index i, Addr p, Addr next, void *clos) /* @@@@ This isn't quite right for multiple traces. */ if (closure->scanAllObjects || AMS_IS_GREY(seg, i)) { - res = (*format->scan)(&closure->ss->ss_s, - AddrAdd(p, format->headerSize), - AddrAdd(next, format->headerSize)); + res = FormatScan(format, + closure->ss, + AddrAdd(p, format->headerSize), + AddrAdd(next, format->headerSize)); if (res != ResOK) return res; - closure->ss->scannedSize += AddrOffset(p, next); if (!closure->scanAllObjects) { Index j = AMS_ADDR_INDEX(seg, next); AVER(!AMS_IS_INVALID_COLOUR(seg, i)); @@ -1412,7 +1412,7 @@ Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) next = AddrAdd(p, alignment); } j = AMS_ADDR_INDEX(seg, next); - res = (*format->scan)(&ss->ss_s, clientP, clientNext); + res = FormatScan(format, ss, clientP, clientNext); if (res != ResOK) { /* */ amsseg->marksChanged = TRUE; @@ -1422,7 +1422,6 @@ Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) /* Check that there haven't been any ambiguous fixes during the */ /* scan, because AMSFindGrey won't work otherwise. */ AVER_CRITICAL(!amsseg->ambiguousFixes); - ss->scannedSize += AddrOffset(p, next); AMS_GREY_BLACKEN(seg, i); if (i+1 < j) AMS_RANGE_WHITE_BLACKEN(seg, i+1, j); diff --git a/mps/code/poolawl.c b/mps/code/poolawl.c index 5bb0e6b9025..738194f26c8 100644 --- a/mps/code/poolawl.c +++ b/mps/code/poolawl.c @@ -901,9 +901,7 @@ static Res awlScanObject(Arena arena, AWL awl, ScanState ss, SegSetSummary(dependentSeg, RefSetUNIV); } - res = (*format->scan)(&ss->ss_s, base, limit); - if (res == ResOK) - ss->scannedSize += AddrOffset(base, limit); + res = FormatScan(format, ss, base, limit); if (dependent) ShieldCover(arena, dependentSeg); diff --git a/mps/code/poolsnc.c b/mps/code/poolsnc.c index f507d41222b..ef295fc7d9a 100644 --- a/mps/code/poolsnc.c +++ b/mps/code/poolsnc.c @@ -527,7 +527,7 @@ static Res SNCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) } if (base < limit) { - res = (*format->scan)(&ss->ss_s, base, limit); + res = FormatScan(format, ss, base, limit); if (res != ResOK) { *totalReturn = FALSE; return res; @@ -536,8 +536,6 @@ static Res SNCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) AVER(base == limit); } - ss->scannedSize += AddrOffset(base, limit); - *totalReturn = TRUE; return ResOK; } diff --git a/mps/code/root.c b/mps/code/root.c index f1212be9eb4..82737e536b0 100644 --- a/mps/code/root.c +++ b/mps/code/root.c @@ -537,7 +537,6 @@ Res RootScan(ScanState ss, Root root) root->the.area.scan_area, root->the.area.the.closure.p, root->the.area.the.closure.s); - ss->scannedSize += AddrOffset(root->the.area.base, root->the.area.limit); if (res != ResOK) goto failScan; break; @@ -549,7 +548,6 @@ Res RootScan(ScanState ss, Root root) root->the.area.scan_area, &root->the.area.the.tag, sizeof(root->the.area.the.tag)); - ss->scannedSize += AddrOffset(root->the.area.base, root->the.area.limit); if (res != ResOK) goto failScan; break; diff --git a/mps/code/trace.c b/mps/code/trace.c index 458106800db..6471488e1e2 100644 --- a/mps/code/trace.c +++ b/mps/code/trace.c @@ -1420,11 +1420,15 @@ void TraceScanSingleRef(TraceSet ts, Rank rank, Arena arena, } -/* TraceScanArea -- scan contiguous area of references +/* TraceScanArea -- scan an area of memory for references * - * This is a convenience function for scanning the contiguous area - * [base, limit). I.e., it calls Fix on all words from base up to - * limit, inclusive of base and exclusive of limit. */ + * This is a wrapper for area scanning functions, which should not + * otherwise be called directly from within the MPS. This function + * checks arguments and takes care of accounting for the scanned + * memory. + * + * c.f. FormatScan() + */ Res TraceScanArea(ScanState ss, Word *base, Word *limit, mps_area_scan_t scan_area, @@ -1437,6 +1441,11 @@ Res TraceScanArea(ScanState ss, Word *base, Word *limit, EVENT3(TraceScanArea, ss, base, limit); + /* scannedSize is accumulated whether or not scan_area succeeds, so + it's safe to accumulate now so that we can tail-call + scan_area. */ + ss->scannedSize += AddrOffset(base, limit); + return scan_area(&ss->ss_s, base, limit, closure, closure_size); }