mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-23 22:20:24 -08:00
Indirect formatted scanning through the scanstate.
This will allow us to reuse the scanning protocol with an arbitrary area scanning function (replacing traceFormatScan) in order to implement formatted object walking without an extra segment method. Don't insist on scanning only grey segments: we want to be able to reuse the scan protocol for walking, when the segments are black.
This commit is contained in:
parent
4251abf5c6
commit
0ee4d7ca06
11 changed files with 108 additions and 65 deletions
|
|
@ -191,36 +191,6 @@ 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 */
|
/* FormatDescribe -- describe a format */
|
||||||
|
|
||||||
Res FormatDescribe(Format format, mps_lib_FILE *stream, Count depth)
|
Res FormatDescribe(Format format, mps_lib_FILE *stream, Count depth)
|
||||||
|
|
|
||||||
|
|
@ -354,6 +354,8 @@ extern const char *MessageNoGCStartWhy(Message message);
|
||||||
|
|
||||||
extern void ScanStateInit(ScanState ss, TraceSet ts, Arena arena,
|
extern void ScanStateInit(ScanState ss, TraceSet ts, Arena arena,
|
||||||
Rank rank, ZoneSet white);
|
Rank rank, ZoneSet white);
|
||||||
|
extern void ScanStateInitSeg(ScanState ss, TraceSet ts, Arena arena,
|
||||||
|
Rank rank, ZoneSet white, Seg seg);
|
||||||
extern void ScanStateFinish(ScanState ss);
|
extern void ScanStateFinish(ScanState ss);
|
||||||
extern Bool ScanStateCheck(ScanState ss);
|
extern Bool ScanStateCheck(ScanState ss);
|
||||||
extern void ScanStateSetSummary(ScanState ss, RefSet summary);
|
extern void ScanStateSetSummary(ScanState ss, RefSet summary);
|
||||||
|
|
@ -449,6 +451,7 @@ extern void TraceIdMessagesDestroy(Arena arena, TraceId ti);
|
||||||
} \
|
} \
|
||||||
END
|
END
|
||||||
|
|
||||||
|
extern Res TraceScanFormat(ScanState ss, Addr base, Addr limit);
|
||||||
extern Res TraceScanArea(ScanState ss, Word *base, Word *limit,
|
extern Res TraceScanArea(ScanState ss, Word *base, Word *limit,
|
||||||
mps_area_scan_t scan_area,
|
mps_area_scan_t scan_area,
|
||||||
void *closure);
|
void *closure);
|
||||||
|
|
@ -808,7 +811,6 @@ extern Res FormatCreate(Format *formatReturn, Arena arena, ArgList args);
|
||||||
extern void FormatDestroy(Format format);
|
extern void FormatDestroy(Format format);
|
||||||
extern Arena FormatArena(Format format);
|
extern Arena FormatArena(Format format);
|
||||||
extern Res FormatDescribe(Format format, mps_lib_FILE *stream, Count depth);
|
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 <code/ref.c> */
|
/* Reference Interface -- see <code/ref.c> */
|
||||||
|
|
|
||||||
|
|
@ -402,6 +402,8 @@ typedef struct ScanStateStruct {
|
||||||
Sig sig; /* <design/sig> */
|
Sig sig; /* <design/sig> */
|
||||||
struct mps_ss_s ss_s; /* .ss <http://bash.org/?400459> */
|
struct mps_ss_s ss_s; /* .ss <http://bash.org/?400459> */
|
||||||
Arena arena; /* owning arena */
|
Arena arena; /* owning arena */
|
||||||
|
mps_area_scan_t formatScan; /* formatted area scanning function */
|
||||||
|
void *formatScanClosure; /* closure argument for .formatScan */
|
||||||
SegFixMethod fix; /* third stage fix function */
|
SegFixMethod fix; /* third stage fix function */
|
||||||
void *fixClosure; /* see .ss.fix-closure */
|
void *fixClosure; /* see .ss.fix-closure */
|
||||||
TraceSet traces; /* traces to scan for */
|
TraceSet traces; /* traces to scan for */
|
||||||
|
|
|
||||||
|
|
@ -1277,7 +1277,7 @@ static Res amcSegScanNailedRange(Bool *totalReturn, Bool *moreReturn,
|
||||||
Addr q;
|
Addr q;
|
||||||
q = (*format->skip)(p);
|
q = (*format->skip)(p);
|
||||||
if ((*amc->pinned)(amc, board, p, q)) {
|
if ((*amc->pinned)(amc, board, p, q)) {
|
||||||
Res res = FormatScan(format, ss, p, q);
|
Res res = TraceScanFormat(ss, p, q);
|
||||||
if(res != ResOK) {
|
if(res != ResOK) {
|
||||||
*totalReturn = FALSE;
|
*totalReturn = FALSE;
|
||||||
*moreReturn = TRUE;
|
*moreReturn = TRUE;
|
||||||
|
|
@ -1425,7 +1425,7 @@ static Res amcSegScan(Bool *totalReturn, Seg seg, ScanState ss)
|
||||||
*totalReturn = TRUE;
|
*totalReturn = TRUE;
|
||||||
return ResOK;
|
return ResOK;
|
||||||
}
|
}
|
||||||
res = FormatScan(format, ss, base, limit);
|
res = TraceScanFormat(ss, base, limit);
|
||||||
if(res != ResOK) {
|
if(res != ResOK) {
|
||||||
*totalReturn = FALSE;
|
*totalReturn = FALSE;
|
||||||
return res;
|
return res;
|
||||||
|
|
@ -1438,7 +1438,7 @@ static Res amcSegScan(Bool *totalReturn, Seg seg, ScanState ss)
|
||||||
AVER(SegBase(seg) <= base);
|
AVER(SegBase(seg) <= base);
|
||||||
AVER(base <= AddrAdd(SegLimit(seg), format->headerSize));
|
AVER(base <= AddrAdd(SegLimit(seg), format->headerSize));
|
||||||
if(base < limit) {
|
if(base < limit) {
|
||||||
res = FormatScan(format, ss, base, limit);
|
res = TraceScanFormat(ss, base, limit);
|
||||||
if(res != ResOK) {
|
if(res != ResOK) {
|
||||||
*totalReturn = FALSE;
|
*totalReturn = FALSE;
|
||||||
return res;
|
return res;
|
||||||
|
|
|
||||||
|
|
@ -1305,10 +1305,9 @@ static Res amsScanObject(Seg seg, Index i, Addr p, Addr next, void *clos)
|
||||||
|
|
||||||
/* @@@@ This isn't quite right for multiple traces. */
|
/* @@@@ This isn't quite right for multiple traces. */
|
||||||
if (closure->scanAllObjects || AMS_IS_GREY(seg, i)) {
|
if (closure->scanAllObjects || AMS_IS_GREY(seg, i)) {
|
||||||
res = FormatScan(format,
|
res = TraceScanFormat(closure->ss,
|
||||||
closure->ss,
|
AddrAdd(p, format->headerSize),
|
||||||
AddrAdd(p, format->headerSize),
|
AddrAdd(next, format->headerSize));
|
||||||
AddrAdd(next, format->headerSize));
|
|
||||||
if (res != ResOK)
|
if (res != ResOK)
|
||||||
return res;
|
return res;
|
||||||
if (!closure->scanAllObjects) {
|
if (!closure->scanAllObjects) {
|
||||||
|
|
@ -1393,7 +1392,7 @@ static Res amsSegScan(Bool *totalReturn, Seg seg, ScanState ss)
|
||||||
next = AddrAdd(p, alignment);
|
next = AddrAdd(p, alignment);
|
||||||
}
|
}
|
||||||
j = PoolIndexOfAddr(SegBase(seg), pool, next);
|
j = PoolIndexOfAddr(SegBase(seg), pool, next);
|
||||||
res = FormatScan(format, ss, clientP, clientNext);
|
res = TraceScanFormat(ss, clientP, clientNext);
|
||||||
if (res != ResOK) {
|
if (res != ResOK) {
|
||||||
/* <design/poolams#.marked.scan.fail> */
|
/* <design/poolams#.marked.scan.fail> */
|
||||||
amsseg->marksChanged = TRUE;
|
amsseg->marksChanged = TRUE;
|
||||||
|
|
|
||||||
|
|
@ -852,7 +852,7 @@ static void awlSegBlacken(Seg seg, TraceSet traceSet)
|
||||||
/* base and limit are both offset by the header size */
|
/* base and limit are both offset by the header size */
|
||||||
|
|
||||||
static Res awlScanObject(Arena arena, AWL awl, ScanState ss,
|
static Res awlScanObject(Arena arena, AWL awl, ScanState ss,
|
||||||
Format format, Addr base, Addr limit)
|
Addr base, Addr limit)
|
||||||
{
|
{
|
||||||
Res res;
|
Res res;
|
||||||
Bool dependent; /* is there a dependent object? */
|
Bool dependent; /* is there a dependent object? */
|
||||||
|
|
@ -862,7 +862,6 @@ static Res awlScanObject(Arena arena, AWL awl, ScanState ss,
|
||||||
AVERT(Arena, arena);
|
AVERT(Arena, arena);
|
||||||
AVERT(AWL, awl);
|
AVERT(AWL, awl);
|
||||||
AVERT(ScanState, ss);
|
AVERT(ScanState, ss);
|
||||||
AVERT(Format, format);
|
|
||||||
AVER(base != 0);
|
AVER(base != 0);
|
||||||
AVER(base < limit);
|
AVER(base < limit);
|
||||||
|
|
||||||
|
|
@ -875,7 +874,7 @@ static Res awlScanObject(Arena arena, AWL awl, ScanState ss,
|
||||||
SegSetSummary(dependentSeg, RefSetUNIV);
|
SegSetSummary(dependentSeg, RefSetUNIV);
|
||||||
}
|
}
|
||||||
|
|
||||||
res = FormatScan(format, ss, base, limit);
|
res = TraceScanFormat(ss, base, limit);
|
||||||
|
|
||||||
if (dependent)
|
if (dependent)
|
||||||
ShieldCover(arena, dependentSeg);
|
ShieldCover(arena, dependentSeg);
|
||||||
|
|
@ -931,7 +930,7 @@ static Res awlSegScanSinglePass(Bool *anyScannedReturn, ScanState ss,
|
||||||
/* <design/poolawl#.fun.scan.pass.object> */
|
/* <design/poolawl#.fun.scan.pass.object> */
|
||||||
if (scanAllObjects
|
if (scanAllObjects
|
||||||
|| (BTGet(awlseg->mark, i) && !BTGet(awlseg->scanned, i))) {
|
|| (BTGet(awlseg->mark, i) && !BTGet(awlseg->scanned, i))) {
|
||||||
Res res = awlScanObject(arena, awl, ss, pool->format,
|
Res res = awlScanObject(arena, awl, ss,
|
||||||
hp, objectLimit);
|
hp, objectLimit);
|
||||||
if (res != ResOK)
|
if (res != ResOK)
|
||||||
return res;
|
return res;
|
||||||
|
|
|
||||||
|
|
@ -508,19 +508,17 @@ static void sncSegBufferEmpty(Seg seg, Buffer buffer)
|
||||||
static Res sncSegScan(Bool *totalReturn, Seg seg, ScanState ss)
|
static Res sncSegScan(Bool *totalReturn, Seg seg, ScanState ss)
|
||||||
{
|
{
|
||||||
Addr base, limit;
|
Addr base, limit;
|
||||||
Format format;
|
|
||||||
Res res;
|
Res res;
|
||||||
|
|
||||||
AVER(totalReturn != NULL);
|
AVER(totalReturn != NULL);
|
||||||
AVERT(ScanState, ss);
|
AVERT(ScanState, ss);
|
||||||
AVERT(Seg, seg);
|
AVERT(Seg, seg);
|
||||||
|
|
||||||
format = SegPool(seg)->format;
|
|
||||||
base = SegBase(seg);
|
base = SegBase(seg);
|
||||||
limit = SegBufferScanLimit(seg);
|
limit = SegBufferScanLimit(seg);
|
||||||
|
|
||||||
if (base < limit) {
|
if (base < limit) {
|
||||||
res = FormatScan(format, ss, base, limit);
|
res = TraceScanFormat(ss, base, limit);
|
||||||
if (res != ResOK) {
|
if (res != ResOK) {
|
||||||
*totalReturn = FALSE;
|
*totalReturn = FALSE;
|
||||||
return res;
|
return res;
|
||||||
|
|
|
||||||
|
|
@ -771,9 +771,6 @@ Res SegScan(Bool *totalReturn, Seg seg, ScanState ss)
|
||||||
* See <code/trace.c#scan.conservative> */
|
* See <code/trace.c#scan.conservative> */
|
||||||
AVER(ss->rank == RankEXACT || RankSetIsMember(SegRankSet(seg), ss->rank));
|
AVER(ss->rank == RankEXACT || RankSetIsMember(SegRankSet(seg), ss->rank));
|
||||||
|
|
||||||
/* Should only scan segments which contain grey objects. */
|
|
||||||
AVER(TraceSetInter(SegGrey(seg), ss->traces) != TraceSetEMPTY);
|
|
||||||
|
|
||||||
EVENT5(SegScan, seg, SegPool(seg), ss->arena, ss->traces, ss->rank);
|
EVENT5(SegScan, seg, SegPool(seg), ss->arena, ss->traces, ss->rank);
|
||||||
return Method(Seg, seg, scan)(totalReturn, seg, ss);
|
return Method(Seg, seg, scan)(totalReturn, seg, ss);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,8 @@ Bool ScanStateCheck(ScanState ss)
|
||||||
ZoneSet white;
|
ZoneSet white;
|
||||||
|
|
||||||
CHECKS(ScanState, ss);
|
CHECKS(ScanState, ss);
|
||||||
|
CHECKL(FUNCHECK(ss->formatScan));
|
||||||
|
/* Can't check ss->formatScanClosure. */
|
||||||
CHECKL(FUNCHECK(ss->fix));
|
CHECKL(FUNCHECK(ss->fix));
|
||||||
/* Can't check ss->fixClosure. */
|
/* Can't check ss->fixClosure. */
|
||||||
CHECKL(ScanStateZoneShift(ss) == ss->arena->zoneShift);
|
CHECKL(ScanStateZoneShift(ss) == ss->arena->zoneShift);
|
||||||
|
|
@ -56,6 +58,23 @@ Bool ScanStateCheck(ScanState ss)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* traceNoScan -- Area scan method that must not be called. */
|
||||||
|
|
||||||
|
static mps_res_t traceNoScan(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ScanStateInit -- Initialize a ScanState object */
|
/* ScanStateInit -- Initialize a ScanState object */
|
||||||
|
|
||||||
void ScanStateInit(ScanState ss, TraceSet ts, Arena arena,
|
void ScanStateInit(ScanState ss, TraceSet ts, Arena arena,
|
||||||
|
|
@ -91,6 +110,8 @@ void ScanStateInit(ScanState ss, TraceSet ts, Arena arena,
|
||||||
if (ss->fix == SegFix && ArenaEmergency(arena))
|
if (ss->fix == SegFix && ArenaEmergency(arena))
|
||||||
ss->fix = SegFixEmergency;
|
ss->fix = SegFixEmergency;
|
||||||
|
|
||||||
|
ss->formatScan = traceNoScan;
|
||||||
|
ss->formatScanClosure = UNUSED_POINTER;
|
||||||
ss->rank = rank;
|
ss->rank = rank;
|
||||||
ss->traces = ts;
|
ss->traces = ts;
|
||||||
ScanStateSetZoneShift(ss, arena->zoneShift);
|
ScanStateSetZoneShift(ss, arena->zoneShift);
|
||||||
|
|
@ -114,6 +135,40 @@ 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,
|
||||||
|
Rank rank, ZoneSet white, Seg seg)
|
||||||
|
{
|
||||||
|
Format format;
|
||||||
|
AVERT(Seg, seg);
|
||||||
|
|
||||||
|
ScanStateInit(ss, ts, arena, rank, white);
|
||||||
|
if (PoolFormat(&format, SegPool(seg))) {
|
||||||
|
ss->formatScan = traceFormatScan;
|
||||||
|
ss->formatScanClosure = format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ScanStateFinish -- Finish a ScanState object */
|
/* ScanStateFinish -- Finish a ScanState object */
|
||||||
|
|
||||||
void ScanStateFinish(ScanState ss)
|
void ScanStateFinish(ScanState ss)
|
||||||
|
|
@ -1141,7 +1196,7 @@ static Res traceScanSegRes(TraceSet ts, Rank rank, Arena arena, Seg seg)
|
||||||
} else { /* scan it */
|
} else { /* scan it */
|
||||||
ScanStateStruct ssStruct;
|
ScanStateStruct ssStruct;
|
||||||
ScanState ss = &ssStruct;
|
ScanState ss = &ssStruct;
|
||||||
ScanStateInit(ss, ts, arena, rank, white);
|
ScanStateInitSeg(ss, ts, arena, rank, white, seg);
|
||||||
|
|
||||||
/* Expose the segment to make sure we can scan it. */
|
/* Expose the segment to make sure we can scan it. */
|
||||||
ShieldExpose(arena, seg);
|
ShieldExpose(arena, seg);
|
||||||
|
|
@ -1473,16 +1528,36 @@ void TraceScanSingleRef(TraceSet ts, Rank rank, Arena arena,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TraceScanFormat -- scan a formatted area of memory for references
|
||||||
|
*
|
||||||
|
* This is a wrapper for format 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.
|
||||||
|
*/
|
||||||
|
Res TraceScanFormat(ScanState ss, Addr base, Addr limit)
|
||||||
|
{
|
||||||
|
AVERT_CRITICAL(ScanState, ss);
|
||||||
|
AVER_CRITICAL(base != NULL);
|
||||||
|
AVER_CRITICAL(limit != NULL);
|
||||||
|
AVER_CRITICAL(base < limit);
|
||||||
|
|
||||||
|
/* scannedSize is accumulated whether or not ss->formatScan
|
||||||
|
* succeeds, so it's safe to accumulate now so that we can tail-call
|
||||||
|
* ss->formatScan. */
|
||||||
|
ss->scannedSize += AddrOffset(base, limit);
|
||||||
|
|
||||||
|
return ss->formatScan(&ss->ss_s, base, limit, ss->formatScanClosure);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TraceScanArea -- scan an area of memory for references
|
/* TraceScanArea -- scan an area of memory for references
|
||||||
*
|
*
|
||||||
* This is a wrapper for area scanning functions, which should not
|
* This is a wrapper for area scanning functions, which should not
|
||||||
* otherwise be called directly from within the MPS. This function
|
* otherwise be called directly from within the MPS. This function
|
||||||
* checks arguments and takes care of accounting for the scanned
|
* checks arguments and takes care of accounting for the scanned
|
||||||
* memory.
|
* memory.
|
||||||
*
|
|
||||||
* c.f. FormatScan()
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Res TraceScanArea(ScanState ss, Word *base, Word *limit,
|
Res TraceScanArea(ScanState ss, Word *base, Word *limit,
|
||||||
mps_area_scan_t scan_area,
|
mps_area_scan_t scan_area,
|
||||||
void *closure)
|
void *closure)
|
||||||
|
|
|
||||||
|
|
@ -312,15 +312,15 @@ called via the generic function ``SegBlacken()``.
|
||||||
``typedef Res (*SegScanMethod)(Bool *totalReturn, Seg seg, ScanState ss)``
|
``typedef Res (*SegScanMethod)(Bool *totalReturn, Seg seg, ScanState ss)``
|
||||||
|
|
||||||
_`.method.scan`: The ``scan`` method scans all the grey objects on the
|
_`.method.scan`: The ``scan`` method scans all the grey objects on the
|
||||||
segment ``seg``, passing the scan state ``ss`` to ``FormatScan``. The
|
segment ``seg``, passing the scan state ``ss`` to
|
||||||
segment may additionally accumulate a summary of *all* its objects. If
|
``TraceScanFormat()``. The segment may additionally accumulate a
|
||||||
it succeeds in accumulating such a summary it must indicate that it
|
summary of *all* its objects. If it succeeds in accumulating such a
|
||||||
has done so by setting the ``*totalReturn`` parameter to ``TRUE``.
|
summary it must indicate that it has done so by setting the
|
||||||
Otherwise it must set ``*totalReturn`` to ``FALSE``. Segment classes
|
``*totalReturn`` parameter to ``TRUE``. Otherwise it must set
|
||||||
are not required to provide this method, and not doing so indicates
|
``*totalReturn`` to ``FALSE``. Segment classes are not required to
|
||||||
that all instances of this class will have no fixable or traceable
|
provide this method, and not doing so indicates that all instances of
|
||||||
references in them. This method is called via the generic function
|
this class will have no fixable or traceable references in them. This
|
||||||
``SegScan()``.
|
method is called via the generic function ``SegScan()``.
|
||||||
|
|
||||||
``typedef Res (*SegFixMethod)(Seg seg, ScanState ss, Ref *refIO)``
|
``typedef Res (*SegFixMethod)(Seg seg, ScanState ss, Ref *refIO)``
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,8 @@ Args Locals Function
|
||||||
4 9 ``traceScanSegRes()``
|
4 9 ``traceScanSegRes()``
|
||||||
4 0 ``SegScan()``
|
4 0 ``SegScan()``
|
||||||
4 5 ``amcSegScan()``
|
4 5 ``amcSegScan()``
|
||||||
4 0 ``FormatScan()``
|
3 0 ``TraceScanFormat()``
|
||||||
|
4 1 ``traceFormatScan()``
|
||||||
3 ≤64 ``format->scan()``
|
3 ≤64 ``format->scan()``
|
||||||
3 0 ``SegFix()``
|
3 0 ``SegFix()``
|
||||||
4 15 ``amcSegFix()``
|
4 15 ``amcSegFix()``
|
||||||
|
|
@ -113,12 +114,12 @@ Args Locals Function
|
||||||
3 7 ``SplaySplay()``
|
3 7 ``SplaySplay()``
|
||||||
4 8 ``SplaySplitDown()``
|
4 8 ``SplaySplitDown()``
|
||||||
3 0 ``SplayZig()``
|
3 0 ``SplayZig()``
|
||||||
112 ≤258 **Total**
|
115 ≤259 **Total**
|
||||||
==== ====== ========================
|
==== ====== ========================
|
||||||
|
|
||||||
We expect that a compiler will not need to push all local variables
|
We expect that a compiler will not need to push all local variables
|
||||||
onto the stack, but even in the case where it pushes all of them, this
|
onto the stack, but even in the case where it pushes all of them, this
|
||||||
call requires no more than 370 words of stack space.
|
call requires no more than 374 words of stack space.
|
||||||
|
|
||||||
This isn't necessarily the deepest call into the MPS (the MPS's
|
This isn't necessarily the deepest call into the MPS (the MPS's
|
||||||
modular design and class system makes it hard to do a complete
|
modular design and class system makes it hard to do a complete
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue