diff --git a/code/format.c b/code/format.c index 1ae0e97696..8d513578e7 100644 --- a/code/format.c +++ b/code/format.c @@ -40,8 +40,7 @@ Bool FormatCheck(Format format) /* FormatNo methods -- default values for format keyword arguments */ -static mps_res_t FormatNoScan(mps_ss_t mps_ss, mps_addr_t base, - mps_addr_t limit) +mps_res_t FormatNoScan(mps_ss_t mps_ss, mps_addr_t base, mps_addr_t limit) { UNUSED(mps_ss); UNUSED(base); diff --git a/code/mpm.h b/code/mpm.h index fcaf2f9ce1..139e8c1e09 100644 --- a/code/mpm.h +++ b/code/mpm.h @@ -811,6 +811,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 mps_res_t FormatNoScan(mps_ss_t mps_ss, mps_addr_t base, mps_addr_t limit); /* Reference Interface -- see */ diff --git a/code/mpmst.h b/code/mpmst.h index 80cb62d9aa..09a7a411fe 100644 --- a/code/mpmst.h +++ b/code/mpmst.h @@ -402,8 +402,9 @@ typedef struct ScanStateStruct { Sig sig; /* */ struct mps_ss_s ss_s; /* .ss */ Arena arena; /* owning arena */ - mps_area_scan_t formatScan; /* formatted area scanning function */ - void *formatScanClosure; /* closure argument for .formatScan */ + mps_fmt_scan_t formatScan; /* callback for scanning formatted objects */ + mps_area_scan_t areaScan; /* ditto via the area scanning interface */ + void *areaScanClosure; /* closure argument for areaScan */ SegFixMethod fix; /* third stage fix function */ void *fixClosure; /* see .ss.fix-closure */ TraceSet traces; /* traces to scan for */ diff --git a/code/trace.c b/code/trace.c index 6919c4f8a0..afd5f7ab24 100644 --- a/code/trace.c +++ b/code/trace.c @@ -38,7 +38,8 @@ Bool ScanStateCheck(ScanState ss) CHECKS(ScanState, ss); CHECKL(FUNCHECK(ss->formatScan)); - /* Can't check ss->formatScanClosure. */ + CHECKL(FUNCHECK(ss->areaScan)); + /* Can't check ss->areaScanClosure. */ CHECKL(FUNCHECK(ss->fix)); /* Can't check ss->fixClosure. */ CHECKL(ScanStateZoneShift(ss) == ss->arena->zoneShift); @@ -58,20 +59,12 @@ Bool ScanStateCheck(ScanState ss) } -/* traceNoScan -- Area scan method that must not be called. */ +/* traceNoAreaScan -- area scan function that must not be called */ -static mps_res_t traceNoScan(mps_ss_t ss, void *base, void *limit, void *closure) +static mps_res_t traceNoAreaScan(mps_ss_t ss, void *base, void *limit, void *closure) { - UNUSED(ss); - - AVER(base != NULL); - AVER(limit != NULL); - AVER(base < limit); - AVER(closure == UNUSED_POINTER); - - NOTREACHED; - - return MPS_RES_UNIMPL; + UNUSED(closure); + return FormatNoScan(ss, base, limit); } @@ -110,8 +103,8 @@ void ScanStateInit(ScanState ss, TraceSet ts, Arena arena, if (ss->fix == SegFix && ArenaEmergency(arena)) ss->fix = SegFixEmergency; - ss->formatScan = traceNoScan; - ss->formatScanClosure = UNUSED_POINTER; + ss->formatScan = FormatNoScan; + ss->areaScan = traceNoAreaScan; ss->rank = rank; ss->traces = ts; ScanStateSetZoneShift(ss, arena->zoneShift); @@ -135,24 +128,6 @@ void ScanStateInit(ScanState ss, TraceSet ts, Arena arena, } -/* traceFormatScan -- Area scan method that dispatches to a format scan. - * - * This is a wrapper for formatted object scanning functions, which - * should not otherwise be called directly from within the MPS. - */ -static mps_res_t traceFormatScan(mps_ss_t mps_ss, void *base, void *limit, void *closure) -{ - Format format = closure; - - AVER_CRITICAL(base != NULL); - AVER_CRITICAL(limit != NULL); - AVER_CRITICAL(base < limit); - AVERT_CRITICAL(Format, format); - - return format->scan(mps_ss, base, limit); -} - - /* ScanStateInitSeg -- Initialize a ScanState object for scanning a segment */ void ScanStateInitSeg(ScanState ss, TraceSet ts, Arena arena, @@ -163,8 +138,7 @@ void ScanStateInitSeg(ScanState ss, TraceSet ts, Arena arena, ScanStateInit(ss, ts, arena, rank, white); if (PoolFormat(&format, SegPool(seg))) { - ss->formatScan = traceFormatScan; - ss->formatScanClosure = format; + ss->formatScan = format->scan; } } @@ -1561,7 +1535,7 @@ Res TraceScanFormat(ScanState ss, Addr base, Addr limit) * ss->formatScan. */ ss->scannedSize += AddrOffset(base, limit); - return ss->formatScan(&ss->ss_s, base, limit, ss->formatScanClosure); + return ss->formatScan(&ss->ss_s, base, limit); } diff --git a/code/walk.c b/code/walk.c index 1f97c8387a..0b3d96baf9 100644 --- a/code/walk.c +++ b/code/walk.c @@ -398,6 +398,21 @@ static Res walkNoFix(Seg seg, ScanState ss, Addr *refIO) } +/* poolWalkScan -- format scanner for poolWalk */ + +static mps_res_t poolWalkScan(mps_ss_t mps_ss, void *base, void *limit) +{ + ScanState ss = PARENT(ScanStateStruct, ss_s, mps_ss); + + AVERT(ScanState, ss); + AVER(base != NULL); + AVER(limit != NULL); + AVER(base < limit); + + return ss->areaScan(mps_ss, base, limit, ss->areaScanClosure); +} + + /* poolWalk -- walk formatted areas in a pool * * See . @@ -432,8 +447,9 @@ static Res poolWalk(Arena arena, Pool pool, mps_area_scan_t area_scan, void *clo ts = TraceSetSingle(trace); ScanStateInit(&ss, ts, arena, RankEXACT, trace->white); - ss.formatScan = area_scan; - ss.formatScanClosure = closure; + ss.formatScan = poolWalkScan; + ss.areaScan = area_scan; + ss.areaScanClosure = closure; ss.fix = walkNoFix; RING_FOR(node, &pool->segRing, nextNode) { diff --git a/design/walk.txt b/design/walk.txt index 56ae8ca10b..e92e6b416a 100644 --- a/design/walk.txt +++ b/design/walk.txt @@ -92,7 +92,7 @@ _`.sol.walk.perf`: The callback uses the scanning protocol so that every reference is fixed and the summary is maintained. _`.sol.walk.closure`: ``mps_pool_walk()`` takes a closure pointer -which is passed to the callback. +which is stored in the ``ScanState`` and passed to the callback. _`.sol.walk.maint`: We reuse the scanning protocol and provide a generic implementation that iterates over the ring of segments in the