From 4e30c7d2b830d4987497d2b60fd204387c4e77f3 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Thu, 10 Apr 2014 18:16:29 +0100 Subject: [PATCH] Don't turn on the alloctable in amsbufferempty when it's shared with nonwhitetable and the colour tables are in use -- this will turn any grey grains in the segment invalid. Add more checking to AMS, including the table use invariant. Copied from Perforce Change: 185434 ServerID: perforce.ravenbrook.com --- mps/code/poolams.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/mps/code/poolams.c b/mps/code/poolams.c index c67a2efd684..7d090b2470b 100644 --- a/mps/code/poolams.c +++ b/mps/code/poolams.c @@ -74,6 +74,11 @@ Bool AMSSegCheck(AMSSeg amsseg) CHECKD_NOSIG(BT, amsseg->nongreyTable); CHECKD_NOSIG(BT, amsseg->nonwhiteTable); + /* If tables are shared, they mustn't both be in use. */ + CHECKL(!(amsseg->ams->shareAllocTable + && amsseg->allocTableInUse + && amsseg->colourTablesInUse)); + return TRUE; } @@ -167,6 +172,10 @@ static Res amsCreateTables(AMS ams, BT *allocReturn, goto failWhite; } + /* Invalidate the colour tables in checking varieties. */ + AVER((BTResRange(nongreyTable, 0, length), TRUE)); + AVER((BTSetRange(nonwhiteTable, 0, length), TRUE)); + *allocReturn = allocTable; *nongreyReturn = nongreyTable; *nonwhiteReturn = nonwhiteTable; @@ -1023,7 +1032,8 @@ static void AMSBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit) AVER(limitIndex <= amsseg->firstFree); if (limitIndex == amsseg->firstFree) /* is it at the end? */ { amsseg->firstFree = initIndex; - } else { /* start using allocTable */ + } else if (!ams->shareAllocTable || !amsseg->colourTablesInUse) { + /* start using allocTable */ amsseg->allocTableInUse = TRUE; BTSetRange(amsseg->allocTable, 0, amsseg->firstFree); if (amsseg->firstFree < amsseg->grains) @@ -1415,16 +1425,20 @@ static Res AMSFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) /* doing that here (this can be called from RootScan, during flip). */ clientRef = *refIO; + AVER_CRITICAL(SegBase(seg) <= clientRef); + AVER_CRITICAL(clientRef < SegLimit(seg)); /* see .ref-limit */ base = AddrSub((Addr)clientRef, format->headerSize); /* can get an ambiguous reference too close to the base of the * segment, so when we subtract the header we are not in the * segment any longer. This isn't a real reference, * so we can just skip it. */ if (base < SegBase(seg)) { - return ResOK; + AVER_CRITICAL(ss->rank == RankAMBIG); + return ResOK; } i = AMS_ADDR_INDEX(seg, base); + AVER_CRITICAL(i < amsseg->grains); AVER_CRITICAL(!AMS_IS_INVALID_COLOUR(seg, i)); ss->wasMarked = TRUE;