1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-04-27 16:51:06 -07:00

Merge branch/2016-04-20/seghasbuffer.

Copied from Perforce
 Change: 192173
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2016-09-05 15:24:24 +01:00
commit fa7547e296
11 changed files with 131 additions and 83 deletions

View file

@ -1135,7 +1135,7 @@ static void segBufAttach(Buffer buffer, Addr base, Addr limit,
found = SegOfAddr(&seg, arena, base);
AVER(found);
AVER(segbuf->seg == NULL);
AVER(SegBuffer(seg) == NULL);
AVER(!SegHasBuffer(seg));
AVER(SegBase(seg) <= base);
AVER(limit <= SegLimit(seg));
@ -1152,11 +1152,8 @@ static void segBufAttach(Buffer buffer, Addr base, Addr limit,
static void segBufDetach(Buffer buffer)
{
SegBuf segbuf = MustBeA(SegBuf, buffer);
Seg seg;
seg = segbuf->seg;
AVER(seg != NULL);
SegSetBuffer(seg, NULL);
Seg seg = segbuf->seg;
SegUnsetBuffer(seg);
segbuf->seg = NULL;
}

View file

@ -672,8 +672,10 @@ extern Res SegSplit(Seg *segLoReturn, Seg *segHiReturn, Seg seg, Addr at);
extern Res SegAbsDescribe(Seg seg, mps_lib_FILE *stream, Count depth);
extern Res SegDescribe(Seg seg, mps_lib_FILE *stream, Count depth);
extern void SegSetSummary(Seg seg, RefSet summary);
extern Buffer SegBuffer(Seg seg);
extern Bool SegHasBuffer(Seg seg);
extern Bool SegBuffer(Buffer *bufferReturn, Seg seg);
extern void SegSetBuffer(Seg seg, Buffer buffer);
extern void SegUnsetBuffer(Seg seg);
extern Addr SegBufferScanLimit(Seg seg);
extern Bool SegCheck(Seg seg);
extern Bool GCSegCheck(GCSeg gcseg);

View file

@ -225,6 +225,7 @@ typedef struct SegClassStruct {
SegSetSummaryMethod setSummary; /* set the segment summary */
SegBufferMethod buffer; /* get the segment buffer */
SegSetBufferMethod setBuffer; /* set the segment buffer */
SegUnsetBufferMethod unsetBuffer; /* unset the segment buffer */
SegSetGreyMethod setGrey; /* change greyness of segment */
SegSetWhiteMethod setWhite; /* change whiteness of segment */
SegSetRankSetMethod setRankSet; /* change rank set of segment */

View file

@ -160,8 +160,9 @@ typedef void (*SegSetRankSetMethod)(Seg seg, RankSet rankSet);
typedef void (*SegSetRankSummaryMethod)(Seg seg, RankSet rankSet,
RefSet summary);
typedef void (*SegSetSummaryMethod)(Seg seg, RefSet summary);
typedef Buffer (*SegBufferMethod)(Seg seg);
typedef Bool (*SegBufferMethod)(Buffer *bufferReturn, Seg seg);
typedef void (*SegSetBufferMethod)(Seg seg, Buffer buffer);
typedef void (*SegUnsetBufferMethod)(Seg seg);
typedef Res (*SegDescribeMethod)(Seg seg, mps_lib_FILE *stream, Count depth);
typedef Res (*SegMergeMethod)(Seg seg, Seg segHi,
Addr base, Addr mid, Addr limit);

View file

@ -197,8 +197,7 @@ static void AMCSegSketch(Seg seg, char *pbSketch, size_t cbSketch)
pbSketch[2] = 'W'; /* White */
}
buffer = SegBuffer(seg);
if(buffer == NULL) {
if (!SegBuffer(&buffer, seg)) {
pbSketch[3] = '_';
} else {
Bool mut = BufferIsMutator(buffer);
@ -243,6 +242,7 @@ static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
Align step;
Size row;
char abzSketch[5];
Buffer buffer;
if (!TESTC(amcSeg, amcseg))
return ResPARAM;
@ -277,8 +277,8 @@ static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
if (res != ResOK)
return res;
if (SegBuffer(seg) != NULL)
init = BufferGetInit(SegBuffer(seg));
if (SegBuffer(&buffer, seg))
init = BufferGetInit(buffer);
else
init = limit;
@ -1100,8 +1100,7 @@ static Res AMCWhiten(Pool pool, Trace trace, Seg seg)
AVERT(Trace, trace);
buffer = SegBuffer(seg);
if(buffer != NULL) {
if (SegBuffer(&buffer, seg)) {
AVERT(Buffer, buffer);
if(!BufferIsMutator(buffer)) { /* forwarding buffer */
@ -1250,6 +1249,7 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn,
Addr p, limit;
Nailboard board;
Res res;
Buffer buffer;
EVENT3(AMCScanBegin, amc, seg, ss); /* TODO: consider using own event */
@ -1258,8 +1258,8 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn,
NailboardClearNewNails(board);
p = SegBase(seg);
while(SegBuffer(seg) != NULL) {
limit = BufferScanLimit(SegBuffer(seg));
while (SegBuffer(&buffer, seg)) {
limit = BufferScanLimit(buffer);
if(p >= limit) {
AVER(p == limit);
goto returnGood;
@ -1342,6 +1342,7 @@ static Res AMCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
Format format;
AMC amc = MustBeA(AMCZPool, pool);
Res res;
Buffer buffer;
AVER(totalReturn != NULL);
AVERT(ScanState, ss);
@ -1358,8 +1359,8 @@ static Res AMCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg)
base = AddrAdd(SegBase(seg), format->headerSize);
/* <design/poolamc/#seg-scan.loop> */
while(SegBuffer(seg) != NULL) {
limit = AddrAdd(BufferScanLimit(SegBuffer(seg)),
while (SegBuffer(&buffer, seg)) {
limit = AddrAdd(BufferScanLimit(buffer),
format->headerSize);
if(base >= limit) {
/* @@@@ Are we sure we don't need scan the rest of the */
@ -1719,13 +1720,13 @@ static void amcReclaimNailed(Pool pool, Trace trace, Seg seg)
/* Free the seg if we can; fixes .nailboard.limitations.middle. */
if(preservedInPlaceCount == 0
&& (SegBuffer(seg) == NULL)
&& (!SegHasBuffer(seg))
&& (SegNailed(seg) == TraceSetEMPTY)) {
amcGen gen = amcSegGen(seg);
/* We may not free a buffered seg. */
AVER(SegBuffer(seg) == NULL);
AVER(!SegHasBuffer(seg));
PoolGenFree(&gen->pgen, seg, 0, SegSize(seg), 0, MustBeA(amcSeg, seg)->deferred);
}
@ -1767,7 +1768,7 @@ static void AMCReclaim(Pool pool, Trace trace, Seg seg)
/* We may not free a buffered seg. (But all buffered + condemned */
/* segs should have been nailed anyway). */
AVER(SegBuffer(seg) == NULL);
AVER(!SegHasBuffer(seg));
STATISTIC(trace->reclaimSize += SegSize(seg));
@ -1884,6 +1885,7 @@ static Res AMCAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr)
Res res;
Arena arena;
Addr base, limit; /* range of objects on segment */
Buffer buffer;
AVER(pReturn != NULL);
AVERT(Pool, pool);
@ -1894,7 +1896,7 @@ static Res AMCAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr)
arena = PoolArena(pool);
base = SegBase(seg);
if (SegBuffer(seg) != NULL) {
if (SegBuffer(&buffer, seg)) {
/* We use BufferGetInit here (and not BufferScanLimit) because we
* want to be able to find objects that have been allocated and
* committed since the last flip. These objects lie between the
@ -1906,7 +1908,7 @@ static Res AMCAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr)
* *must* point inside a live object and we stop skipping once we
* have found it. The init pointer serves this purpose.
*/
limit = BufferGetInit(SegBuffer(seg));
limit = BufferGetInit(buffer);
} else {
limit = SegLimit(seg);
}

View file

@ -287,7 +287,7 @@ static void AMSSegFinish(Seg seg)
ams = amsseg->ams;
AVERT(AMS, ams);
arena = PoolArena(AMSPool(ams));
AVER(SegBuffer(seg) == NULL);
AVER(!SegHasBuffer(seg));
/* keep the destructions in step with AMSSegInit failure cases */
amsDestroyTables(ams, amsseg->allocTable, amsseg->nongreyTable,
@ -514,10 +514,9 @@ failCreateTablesLo:
/* AMSSegDescribe -- describe an AMS segment */
#define WRITE_BUFFER_LIMIT(stream, seg, i, buffer, accessor, code) \
#define WRITE_BUFFER_LIMIT(i, accessor, code) \
BEGIN \
if ((buffer) != NULL \
&& (i) == AMS_ADDR_INDEX(seg, accessor(buffer))) { \
if (hasBuffer && (i) == AMS_ADDR_INDEX(seg, accessor(buffer))) { \
Res _res = WriteF(stream, 0, code, NULL); \
if (_res != ResOK) return _res; \
} \
@ -527,7 +526,8 @@ static Res AMSSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
{
AMSSeg amsseg = CouldBeA(AMSSeg, seg);
Res res;
Buffer buffer; /* the segment's buffer, if it has one */
Buffer buffer;
Bool hasBuffer;
Index i;
if (!TESTC(AMSSeg, amsseg))
@ -540,7 +540,7 @@ static Res AMSSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
if (res != ResOK)
return res;
buffer = SegBuffer(seg);
hasBuffer = SegBuffer(&buffer, seg);
res = WriteF(stream, depth + 2,
"AMS $P\n", (WriteFP)amsseg->ams,
@ -583,9 +583,9 @@ static Res AMSSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
return res;
}
WRITE_BUFFER_LIMIT(stream, seg, i, buffer, BufferBase, "[");
WRITE_BUFFER_LIMIT(stream, seg, i, buffer, BufferGetInit, "|");
WRITE_BUFFER_LIMIT(stream, seg, i, buffer, BufferAlloc, ">");
WRITE_BUFFER_LIMIT(i, BufferBase, "[");
WRITE_BUFFER_LIMIT(i, BufferGetInit, "|");
WRITE_BUFFER_LIMIT(i, BufferAlloc, ">");
if (AMS_ALLOCED(seg, i)) {
if (amsseg->colourTablesInUse) {
@ -605,8 +605,8 @@ static Res AMSSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth)
if (res != ResOK)
return res;
WRITE_BUFFER_LIMIT(stream, seg, i+1, buffer, BufferScanLimit, "<");
WRITE_BUFFER_LIMIT(stream, seg, i+1, buffer, BufferLimit, "]");
WRITE_BUFFER_LIMIT(i+1, BufferScanLimit, "<");
WRITE_BUFFER_LIMIT(i+1, BufferLimit, "]");
}
return ResOK;
@ -730,7 +730,7 @@ static void AMSSegsDestroy(AMS ams)
RING_FOR(node, ring, next) {
Seg seg = SegOfPoolRing(node);
AMSSeg amsseg = Seg2AMSSeg(seg);
AVER(SegBuffer(seg) == NULL);
AVER(!SegHasBuffer(seg));
AVERT(AMSSeg, amsseg);
AVER(amsseg->ams == ams);
AVER(amsseg->bufferedGrains == 0);
@ -965,7 +965,7 @@ static Res AMSBufferFill(Addr *baseReturn, Addr *limitReturn,
seg = AMSSeg2Seg(amsseg);
if (SegRankSet(seg) == rankSet
&& SegBuffer(seg) == NULL
&& !SegHasBuffer(seg)
/* Can't use a white or grey segment, see d.m.p.fill.colour. */
&& SegWhite(seg) == TraceSetEMPTY
&& SegGrey(seg) == TraceSetEMPTY)
@ -1140,8 +1140,7 @@ static Res AMSWhiten(Pool pool, Trace trace, Seg seg)
amsseg->allocTableInUse = TRUE;
}
buffer = SegBuffer(seg);
if (buffer != NULL) { /* <design/poolams/#condemn.buffer> */
if (SegBuffer(&buffer, seg)) { /* <design/poolams/#condemn.buffer> */
Index scanLimitIndex, limitIndex;
scanLimitIndex = AMS_ADDR_INDEX(seg, BufferScanLimit(buffer));
limitIndex = AMS_ADDR_INDEX(seg, BufferLimit(buffer));
@ -1208,6 +1207,7 @@ static Res amsIterate(Seg seg, AMSObjectFunction f, void *closure)
Index i;
Addr p, next, limit;
Buffer buffer;
Bool hasBuffer;
AVERT(Seg, seg);
AVERT(AMSObjectFunction, f);
@ -1227,16 +1227,15 @@ static Res amsIterate(Seg seg, AMSObjectFunction f, void *closure)
p = SegBase(seg);
limit = SegLimit(seg);
buffer = SegBuffer(seg);
hasBuffer = SegBuffer(&buffer, seg);
while (p < limit) { /* loop over the objects in the segment */
if (buffer != NULL
&& p == BufferScanLimit(buffer) && p != BufferLimit(buffer)) {
if (hasBuffer && p == BufferScanLimit(buffer) && p != BufferLimit(buffer)) {
/* skip buffer */
next = BufferLimit(buffer);
AVER(AddrIsAligned(next, alignment));
} else {
AVER((buffer == NULL)
AVER(!hasBuffer
|| (p < BufferScanLimit(buffer))
|| (p >= BufferLimit(buffer))); /* not in the buffer */
@ -1634,7 +1633,7 @@ static void AMSReclaim(Pool pool, Trace trace, Seg seg)
amsseg->colourTablesInUse = FALSE;
SegSetWhite(seg, TraceSetDel(SegWhite(seg), trace));
if (amsseg->freeGrains == grains && SegBuffer(seg) == NULL) {
if (amsseg->freeGrains == grains && !SegHasBuffer(seg)) {
/* No survivors */
AVER(amsseg->bufferedGrains == 0);
PoolGenFree(ams->pgen, seg,

View file

@ -589,7 +589,7 @@ static void AWLFinish(Pool pool)
RING_FOR(node, ring, nextNode) {
Seg seg = SegOfPoolRing(node);
AWLSeg awlseg = MustBeA(AWLSeg, seg);
AVER(SegBuffer(seg) == NULL);
AVER(!SegHasBuffer(seg));
AVERT(AWLSeg, awlseg);
AVER(awlseg->bufferedGrains == 0);
PoolGenFree(awl->pgen, seg,
@ -627,7 +627,7 @@ static Res AWLBufferFill(Addr *baseReturn, Addr *limitReturn,
/* Only try to allocate in the segment if it is not already */
/* buffered, and has the same ranks as the buffer. */
if (SegBuffer(seg) == NULL
if (!SegHasBuffer(seg)
&& SegRankSet(seg) == BufferRankSet(buffer)
&& AWLGrainsSize(awl, awlseg->freeGrains) >= size
&& AWLSegAlloc(&base, &limit, awlseg, awl, size))
@ -715,7 +715,7 @@ static Res AWLWhiten(Pool pool, Trace trace, Seg seg)
{
AWL awl = MustBeA(AWLPool, pool);
AWLSeg awlseg = MustBeA(AWLSeg, seg);
Buffer buffer = SegBuffer(seg);
Buffer buffer;
Count agedGrains, uncondemnedGrains;
/* All parameters checked by generic PoolWhiten. */
@ -724,7 +724,7 @@ static Res AWLWhiten(Pool pool, Trace trace, Seg seg)
/* see <design/poolawl/#fun.condemn> */
AVER(SegWhite(seg) == TraceSetEMPTY);
if(buffer == NULL) {
if (!SegBuffer(&buffer, seg)) {
awlRangeWhiten(awlseg, 0, awlseg->grains);
uncondemnedGrains = (Count)0;
} else {
@ -781,6 +781,8 @@ static void AWLRangeGrey(AWLSeg awlseg, Index base, Index limit)
static void AWLGrey(Pool pool, Trace trace, Seg seg)
{
Buffer buffer;
AVERT(Pool, pool);
AVERT(Trace, trace);
AVERT(Seg, seg);
@ -790,9 +792,8 @@ static void AWLGrey(Pool pool, Trace trace, Seg seg)
AWLSeg awlseg = MustBeA(AWLSeg, seg);
SegSetGrey(seg, TraceSetAdd(SegGrey(seg), trace));
if (SegBuffer(seg) != NULL) {
if (SegBuffer(&buffer, seg)) {
Addr base = SegBase(seg);
Buffer buffer = SegBuffer(seg);
AWLRangeGrey(awlseg,
0,
@ -866,7 +867,7 @@ static Res awlScanSinglePass(Bool *anyScannedReturn,
AWL awl = MustBeA(AWLPool, pool);
AWLSeg awlseg = MustBeA(AWLSeg, seg);
Arena arena = PoolArena(pool);
Buffer buffer = SegBuffer(seg);
Buffer buffer;
Format format = pool->format;
Addr base = SegBase(seg);
Addr limit = SegLimit(seg);
@ -879,7 +880,7 @@ static Res awlScanSinglePass(Bool *anyScannedReturn,
*anyScannedReturn = FALSE;
p = base;
if (buffer != NULL && BufferScanLimit(buffer) != BufferLimit(buffer))
if (SegBuffer(&buffer, seg) && BufferScanLimit(buffer) != BufferLimit(buffer))
bufferScanLimit = BufferScanLimit(buffer);
else
bufferScanLimit = limit;
@ -1027,7 +1028,8 @@ static void AWLReclaim(Pool pool, Trace trace, Seg seg)
AWL awl = MustBeA(AWLPool, pool);
AWLSeg awlseg = MustBeA(AWLSeg, seg);
Addr base = SegBase(seg);
Buffer buffer = SegBuffer(seg);
Buffer buffer;
Bool hasBuffer = SegBuffer(&buffer, seg);
Format format = pool->format;
Count reclaimedGrains = (Count)0;
Count preservedInPlaceCount = (Count)0;
@ -1046,7 +1048,7 @@ static void AWLReclaim(Pool pool, Trace trace, Seg seg)
continue;
}
p = awlAddrOfIndex(base, awl, i);
if (buffer != NULL
if (hasBuffer
&& p == BufferScanLimit(buffer)
&& BufferScanLimit(buffer) != BufferLimit(buffer))
{
@ -1085,7 +1087,7 @@ static void AWLReclaim(Pool pool, Trace trace, Seg seg)
trace->preservedInPlaceSize += preservedInPlaceSize;
SegSetWhite(seg, TraceSetDel(SegWhite(seg), trace));
if (awlseg->freeGrains == awlseg->grains && buffer == NULL) {
if (awlseg->freeGrains == awlseg->grains && !hasBuffer) {
/* No survivors */
AVER(awlseg->bufferedGrains == 0);
PoolGenFree(awl->pgen, seg,
@ -1158,9 +1160,9 @@ static void AWLWalk(Pool pool, Seg seg, FormattedObjectsVisitor f,
/* free grain */
Addr next;
Index i;
Buffer buffer;
if (SegBuffer(seg) != NULL) {
Buffer buffer = SegBuffer(seg);
if (SegBuffer(&buffer, seg)) {
if (object == BufferScanLimit(buffer)
&& BufferScanLimit(buffer) != BufferLimit(buffer)) {
/* skip over buffered area */

View file

@ -231,7 +231,7 @@ static Bool loSegFindFree(Addr *bReturn, Addr *lReturn,
AVER(agrains <= loseg->freeGrains);
AVER(size <= SegSize(seg));
if(SegBuffer(seg) != NULL)
if (SegHasBuffer(seg))
/* Don't bother trying to allocate from a buffered segment */
return FALSE;
@ -312,11 +312,12 @@ static void loSegReclaim(LOSeg loseg, Trace trace)
*/
p = base;
while(p < limit) {
Buffer buffer = SegBuffer(seg);
Buffer buffer;
Bool hasBuffer = SegBuffer(&buffer, seg);
Addr q;
Index i;
if(buffer != NULL) {
if (hasBuffer) {
marked = TRUE;
if (p == BufferScanLimit(buffer)
&& BufferScanLimit(buffer) != BufferLimit(buffer)) {
@ -403,9 +404,9 @@ static void LOWalk(Pool pool, Seg seg, FormattedObjectsVisitor f,
Addr object = loAddrOfIndex(base, lo, i);
Addr next;
Index j;
Buffer buffer;
if(SegBuffer(seg) != NULL) {
Buffer buffer = SegBuffer(seg);
if (SegBuffer(&buffer, seg)) {
if(object == BufferScanLimit(buffer) &&
BufferScanLimit(buffer) != BufferLimit(buffer)) {
/* skip over buffered area */
@ -518,7 +519,7 @@ static void LOFinish(Pool pool)
RING_FOR(node, &pool->segRing, nextNode) {
Seg seg = SegOfPoolRing(node);
LOSeg loseg = MustBeA(LOSeg, seg);
AVER(SegBuffer(seg) == NULL);
AVER(!SegHasBuffer(seg));
AVERT(LOSeg, loseg);
AVER(loseg->bufferedGrains == 0);
PoolGenFree(lo->pgen, seg,
@ -658,8 +659,7 @@ static Res LOWhiten(Pool pool, Trace trace, Seg seg)
grains = loSegGrains(loseg);
/* Whiten allocated objects; leave free areas black. */
buffer = SegBuffer(seg);
if (buffer != NULL) {
if (SegBuffer(&buffer, seg)) {
Addr base = SegBase(seg);
Index scanLimitIndex = loIndexOfAddr(base, lo, BufferScanLimit(buffer));
Index limitIndex = loIndexOfAddr(base, lo, BufferLimit(buffer));

View file

@ -560,6 +560,7 @@ static Res SNCFramePop(Pool pool, Buffer buf, AllocFrame frame)
Arena arena;
Seg seg = NULL; /* suppress "may be used uninitialized" */
Bool foundSeg;
Buffer segBuf;
arena = PoolArena(pool);
addr = (Addr)frame;
@ -567,7 +568,7 @@ static Res SNCFramePop(Pool pool, Buffer buf, AllocFrame frame)
AVER(foundSeg); /* <design/check/#.common> */
AVER(SegPool(seg) == pool);
if (SegBuffer(seg) == buf) {
if (SegBuffer(&segBuf, seg) && segBuf == buf) {
/* don't need to change the segment - just the alloc pointers */
AVER(addr <= BufferScanLimit(buf)); /* check direction of pop */
BufferSetAllocAddr(buf, addr);

View file

@ -332,12 +332,21 @@ void SegSetRankAndSummary(Seg seg, RankSet rankSet, RefSet summary)
}
/* SegBuffer -- return the buffer of a segment */
/* SegHasBuffer -- segment has a buffer? */
Buffer SegBuffer(Seg seg)
Bool SegHasBuffer(Seg seg)
{
Buffer buffer;
return SegBuffer(&buffer, seg);
}
/* SegBuffer -- get the buffer of a segment */
Bool SegBuffer(Buffer *bufferReturn, Seg seg)
{
AVERT_CRITICAL(Seg, seg); /* .seg.critical */
return Method(Seg, seg, buffer)(seg);
return Method(Seg, seg, buffer)(bufferReturn, seg);
}
@ -346,12 +355,20 @@ Buffer SegBuffer(Seg seg)
void SegSetBuffer(Seg seg, Buffer buffer)
{
AVERT(Seg, seg);
if (buffer != NULL)
AVERT(Buffer, buffer);
AVERT(Buffer, buffer);
Method(Seg, seg, setBuffer)(seg, buffer);
}
/* SegUnsetBuffer -- remove the buffer from a segment */
void SegUnsetBuffer(Seg seg)
{
AVERT(Seg, seg);
Method(Seg, seg, unsetBuffer)(seg);
}
/* SegBufferScanLimit -- limit of scannable objects in segment */
Addr SegBufferScanLimit(Seg seg)
@ -361,8 +378,7 @@ Addr SegBufferScanLimit(Seg seg)
AVERT(Seg, seg);
buf = SegBuffer(seg);
if (buf == NULL) {
if (!SegBuffer(&buf, seg)) {
/* Segment is unbuffered: entire segment scannable */
limit = SegLimit(seg);
} else {
@ -627,6 +643,7 @@ Res SegSplit(Seg *segLoReturn, Seg *segHiReturn, Seg seg, Addr at)
Arena arena;
Res res;
void *p;
Buffer buffer;
AVER(NULL != segLoReturn);
AVER(NULL != segHiReturn);
@ -642,7 +659,7 @@ Res SegSplit(Seg *segLoReturn, Seg *segHiReturn, Seg seg, Addr at)
/* Can only split a buffered segment if the entire buffer is below
* the split point. */
AVER(SegBuffer(seg) == NULL || BufferLimit(SegBuffer(seg)) <= at);
AVER(!SegBuffer(&buffer, seg) || BufferLimit(buffer) <= at);
if (seg->queued)
ShieldFlush(arena); /* see <design/seg/#split-merge.shield> */
@ -824,11 +841,12 @@ static void segNoSetRankSummary(Seg seg, RankSet rankSet, RefSet summary)
/* segNoBuffer -- non-method to return the buffer of a segment */
static Buffer segNoBuffer(Seg seg)
static Bool segNoBuffer(Buffer *bufferReturn, Seg seg)
{
AVERT(Seg, seg);
AVER(bufferReturn != NULL);
NOTREACHED;
return NULL;
return FALSE;
}
@ -837,8 +855,16 @@ static Buffer segNoBuffer(Seg seg)
static void segNoSetBuffer(Seg seg, Buffer buffer)
{
AVERT(Seg, seg);
if (buffer != NULL)
AVERT(Buffer, buffer);
AVERT(Buffer, buffer);
NOTREACHED;
}
/* segNoSetBuffer -- non-method to set the buffer of a segment */
static void segNoUnsetBuffer(Seg seg)
{
AVERT(Seg, seg);
NOTREACHED;
}
@ -1345,7 +1371,7 @@ static void gcSegSetRankSummary(Seg seg, RankSet rankSet, RefSet summary)
/* gcSegBuffer -- GCSeg method to return the buffer of a segment */
static Buffer gcSegBuffer(Seg seg)
static Bool gcSegBuffer(Buffer *bufferReturn, Seg seg)
{
GCSeg gcseg;
@ -1354,7 +1380,12 @@ static Buffer gcSegBuffer(Seg seg)
AVERT_CRITICAL(GCSeg, gcseg); /* .seg.method.check */
AVER_CRITICAL(&gcseg->segStruct == seg);
return gcseg->buffer;
if (gcseg->buffer != NULL) {
*bufferReturn = gcseg->buffer;
return TRUE;
}
return FALSE;
}
@ -1375,6 +1406,15 @@ static void gcSegSetBuffer(Seg seg, Buffer buffer)
}
/* gcSegUnsetBuffer -- GCSeg method to remove the buffer from a segment */
static void gcSegUnsetBuffer(Seg seg)
{
GCSeg gcseg = MustBeA_CRITICAL(GCSeg, seg); /* .seg.method.check */
gcseg->buffer = NULL;
}
/* gcSegMerge -- GCSeg merge method
*
* .buffer: Can't merge two segments both with buffers.
@ -1582,7 +1622,8 @@ DEFINE_CLASS(Seg, Seg, klass)
klass->finish = SegAbsFinish;
klass->setSummary = segNoSetSummary;
klass->buffer = segNoBuffer;
klass->setBuffer = segNoSetBuffer;
klass->setBuffer = segNoSetBuffer;
klass->unsetBuffer = segNoUnsetBuffer;
klass->setGrey = segNoSetGrey;
klass->setWhite = segNoSetWhite;
klass->setRankSet = segNoSetRankSet;
@ -1607,7 +1648,8 @@ DEFINE_CLASS(Seg, GCSeg, klass)
klass->finish = gcSegFinish;
klass->setSummary = gcSegSetSummary;
klass->buffer = gcSegBuffer;
klass->setBuffer = gcSegSetBuffer;
klass->setBuffer = gcSegSetBuffer;
klass->unsetBuffer = gcSegUnsetBuffer;
klass->setGrey = gcSegSetGrey;
klass->setWhite = gcSegSetWhite;
klass->setRankSet = gcSegSetRankSet;

View file

@ -536,7 +536,7 @@ static Res AMSTBufferFill(Addr *baseReturn, Addr *limitReturn,
if (SegLimit(seg) == limit && SegBase(seg) == base) {
if (amstseg->prev != NULL) {
Seg segLo = AMSTSeg2Seg(amstseg->prev);
if (SegBuffer(segLo) == NULL &&
if (!SegHasBuffer(segLo) &&
SegGrey(segLo) == SegGrey(seg) &&
SegWhite(segLo) == SegWhite(seg)) {
/* .merge */
@ -599,10 +599,11 @@ static void AMSTStressBufferedSeg(Seg seg, Buffer buffer)
AMST amst;
Arena arena;
Addr limit;
Buffer segBuf;
AVERT(Seg, seg);
AVERT(Buffer, buffer);
AVER(SegBuffer(seg) == buffer);
AVER(SegBuffer(&segBuf, seg) && segBuf == buffer);
amstseg = Seg2AMSTSeg(seg);
AVERT(AMSTSeg, amstseg);
limit = BufferLimit(buffer);