From 36b227c0c7ab3db0a6d44949c3db3c401b57e58a Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 20 Apr 2016 13:25:07 +0100 Subject: [PATCH 01/52] Branching master to branch/2016-04-20/seghasbuffer. Copied from Perforce Change: 191342 ServerID: perforce.ravenbrook.com From 1f3b71ef3c3c13b54b079a8c2233f4f18301abff Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Thu, 21 Apr 2016 14:04:20 +0100 Subject: [PATCH 02/52] Branching master to branch/2016-04-21/amswalk. Copied from Perforce Change: 191459 ServerID: perforce.ravenbrook.com From 4c0150b783af41c3eec32b5950a75f18b1ef98cf Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Thu, 21 Apr 2016 14:11:44 +0100 Subject: [PATCH 03/52] Implement amswalk. Copied from Perforce Change: 191463 ServerID: perforce.ravenbrook.com --- mps/code/poolams.c | 62 +++++++++++++++++++++++++++++++++++++++++++++- mps/code/walkt0.c | 2 +- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/mps/code/poolams.c b/mps/code/poolams.c index c362ded31c9..07bc54ac391 100644 --- a/mps/code/poolams.c +++ b/mps/code/poolams.c @@ -1662,6 +1662,66 @@ static void AMSReclaim(Pool pool, Trace trace, Seg seg) } +/* AMSWalk -- walk formatted objects in AMC pool */ + +static void AMSWalk(Pool pool, Seg seg, FormattedObjectsVisitor f, + void *p, size_t s) +{ + AMS ams; + AMSSeg amsseg; + Addr object, base, limit; + Format format; + + AVERT(Pool, pool); + AVERT(Seg, seg); + AVER(FUNCHECK(f)); + /* p and s are arbitrary closures and can't be checked */ + + ams = PoolAMS(pool); + AVERT(AMS, ams); + amsseg = Seg2AMSSeg(seg); + AVERT(AMSSeg, amsseg); + + format = pool->format; + + base = SegBase(seg); + object = base; + limit = SegLimit(seg); + + while (object < limit) { + /* object is a slight misnomer because it might point to a free grain */ + Addr next; + Index i; + + if (SegBuffer(seg) != NULL) { + Buffer buffer = SegBuffer(seg); + if (object == BufferScanLimit(buffer) + && BufferScanLimit(buffer) != BufferLimit(buffer)) { + /* skip over buffered area */ + object = BufferLimit(buffer); + continue; + } + /* since we skip over the buffered area we are always */ + /* either before the buffer, or after it, never in it */ + AVER(object < BufferGetInit(buffer) || BufferLimit(buffer) <= object); + } + i = AMS_ADDR_INDEX(seg, object); + if (!AMS_ALLOCED(seg, i)) { + /* This grain is free */ + object = AddrAdd(object, PoolAlignment(pool)); + continue; + } + object = AddrAdd(object, format->headerSize); + next = format->skip(object); + next = AddrSub(next, format->headerSize); + AVER(AddrIsAligned(next, PoolAlignment(pool))); + if (!AMS_IS_WHITE(seg, i)) + (*f)(object, pool->format, pool, p, s); + object = next; + } +} + + /* AMSFreeWalk -- free block walking method of the pool class */ static void AMSFreeWalk(Pool pool, FreeBlockVisitor f, void *p) @@ -1781,7 +1841,7 @@ DEFINE_CLASS(AMSPoolClass, this) this->fix = AMSFix; this->fixEmergency = AMSFix; this->reclaim = AMSReclaim; - this->walk = PoolNoWalk; /* TODO: job003738 */ + this->walk = AMSWalk; this->freewalk = AMSFreeWalk; this->totalSize = AMSTotalSize; this->freeSize = AMSFreeSize; diff --git a/mps/code/walkt0.c b/mps/code/walkt0.c index 3c0ef5d5c25..b05c9134436 100644 --- a/mps/code/walkt0.c +++ b/mps/code/walkt0.c @@ -236,7 +236,7 @@ int main(int argc, char *argv[]) test(arena, mps_class_amc()); test(arena, mps_class_amcz()); - /* TODO: test(arena, mps_class_ams()); -- see job003738 */ + test(arena, mps_class_ams()); test(arena, mps_class_awl()); test(arena, mps_class_lo()); test(arena, mps_class_snc()); From 454cb57840a0f4f659032e7e513b6daa7ec4f32b Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Thu, 21 Apr 2016 17:23:40 +0100 Subject: [PATCH 04/52] Must check that colour tables are in use before consulting them. Copied from Perforce Change: 191502 ServerID: perforce.ravenbrook.com --- mps/code/poolams.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mps/code/poolams.c b/mps/code/poolams.c index 07bc54ac391..a5c22533841 100644 --- a/mps/code/poolams.c +++ b/mps/code/poolams.c @@ -1715,7 +1715,7 @@ static void AMSWalk(Pool pool, Seg seg, FormattedObjectsVisitor f, next = format->skip(object); next = AddrSub(next, format->headerSize); AVER(AddrIsAligned(next, PoolAlignment(pool))); - if (!AMS_IS_WHITE(seg, i)) + if (!amsseg->colourTablesInUse || !AMS_IS_WHITE(seg, i)) (*f)(object, pool->format, pool, p, s); object = next; } From 82690aa532efb5d8d61d72cb3e5f5e95d48ffd7c Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Thu, 21 Apr 2016 20:50:45 +0100 Subject: [PATCH 05/52] Untabify. Copied from Perforce Change: 191528 ServerID: perforce.ravenbrook.com --- mps/code/buffer.c | 10 +++---- mps/code/event.c | 12 ++++---- mps/code/mpm.c | 22 +++++++-------- mps/code/mpm.h | 8 +++--- mps/code/pool.c | 10 +++---- mps/code/protocol.c | 4 +-- mps/code/protocol.h | 20 +++++++------- mps/code/segsmss.c | 4 +-- mps/code/shield.c | 2 +- mps/design/diag.txt | 4 +-- mps/design/index.txt | 28 +++++++++---------- mps/design/protocol.txt | 38 +++++++++++++------------- mps/example/scheme/scheme-advanced.c | 8 +++--- mps/example/scheme/scheme.c | 10 +++---- mps/manual/source/topic/deprecated.rst | 4 +-- 15 files changed, 92 insertions(+), 92 deletions(-) diff --git a/mps/code/buffer.c b/mps/code/buffer.c index 779d31e448b..f16897a3c2c 100644 --- a/mps/code/buffer.c +++ b/mps/code/buffer.c @@ -1,7 +1,7 @@ /* buffer.c: ALLOCATION BUFFER IMPLEMENTATION * * $Id$ - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * * .purpose: This is (part of) the implementation of allocation buffers. * Several macros which also form part of the implementation are in @@ -1248,9 +1248,9 @@ static Res segBufDescribe(Buffer buffer, mps_lib_FILE *stream, Count depth) return res; return WriteF(stream, depth + 2, - "Seg $P\n", (WriteFP)segbuf->seg, - "rankSet $U\n", (WriteFU)segbuf->rankSet, - NULL); + "Seg $P\n", (WriteFP)segbuf->seg, + "rankSet $U\n", (WriteFU)segbuf->rankSet, + NULL); } @@ -1333,7 +1333,7 @@ DEFINE_CLASS(Buffer, RankBuf, klass) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2014 Ravenbrook Limited . + * Copyright (C) 2001-2016 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/event.c b/mps/code/event.c index 0a15e064db3..e2825b5334f 100644 --- a/mps/code/event.c +++ b/mps/code/event.c @@ -205,17 +205,17 @@ void EventInit(void) if (!eventInited) { EventKind kind; for (kind = 0; kind < EventKindLIMIT; ++kind) { - AVER(EventLast[kind] == NULL); - AVER(EventWritten[kind] == NULL); - EventLast[kind] = EventWritten[kind] = EventBuffer[kind] + EventBufferSIZE; + AVER(EventLast[kind] == NULL); + AVER(EventWritten[kind] == NULL); + EventLast[kind] = EventWritten[kind] = EventBuffer[kind] + EventBufferSIZE; } eventInited = TRUE; EventKindControl = (Word)mps_lib_telemetry_control(); EventInternSerial = (Serial)1; /* 0 is reserved */ (void)EventInternString(MPSVersion()); /* emit version */ EVENT7(EventInit, EVENT_VERSION_MAJOR, EVENT_VERSION_MEDIAN, - EVENT_VERSION_MINOR, EventCodeMAX, EventNameMAX, MPS_WORD_WIDTH, - mps_clocks_per_sec()); + EVENT_VERSION_MINOR, EventCodeMAX, EventNameMAX, MPS_WORD_WIDTH, + mps_clocks_per_sec()); /* flush these initial events to get the first ClockSync out. */ EventSync(); } @@ -520,7 +520,7 @@ extern void EventDump(mps_lib_FILE *stream) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2014 Ravenbrook Limited . + * Copyright (C) 2001-2016 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/mpm.c b/mps/code/mpm.c index f49f05bb517..71072b67c9d 100644 --- a/mps/code/mpm.c +++ b/mps/code/mpm.c @@ -1,7 +1,7 @@ /* mpm.c: GENERAL MPM SUPPORT * * $Id$ - * Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * * .purpose: Miscellaneous support for the implementation of the MPM * and pool classes. @@ -711,7 +711,7 @@ static Bool quickSorted(void *array[], Count length, void QuickSort(void *array[], Count length, QuickSortCompare compare, void *closure, - SortStruct *sortStruct) + SortStruct *sortStruct) { Index left, right, sp, lo, hi, leftLimit, rightBase; void *pivot, *temp; @@ -770,15 +770,15 @@ void QuickSort(void *array[], Count length, for later. */ AVER_CRITICAL(sp < sizeof sortStruct->stack / sizeof sortStruct->stack[0]); if (leftLimit - left < right - rightBase) { - sortStruct->stack[sp].left = rightBase; - sortStruct->stack[sp].right = right; - ++sp; - right = leftLimit; + sortStruct->stack[sp].left = rightBase; + sortStruct->stack[sp].right = right; + ++sp; + right = leftLimit; } else { - sortStruct->stack[sp].left = left; - sortStruct->stack[sp].right = leftLimit; - ++sp; - left = rightBase; + sortStruct->stack[sp].left = left; + sortStruct->stack[sp].right = leftLimit; + ++sp; + left = rightBase; } } @@ -799,7 +799,7 @@ void QuickSort(void *array[], Count length, /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2015 Ravenbrook Limited . + * Copyright (C) 2001-2016 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/mpm.h b/mps/code/mpm.h index e8ba89c5ed8..1dc05e95177 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -1,7 +1,7 @@ /* mpm.h: MEMORY POOL MANAGER DEFINITIONS * * $Id$ - * Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * Portions copyright (C) 2002 Global Graphics Software. * * .trans.bufferinit: The Buffer data structure has an Init field and @@ -177,8 +177,8 @@ extern Word RandomWord(void); typedef Compare QuickSortCompare(void *left, void *right, void *closure); extern void QuickSort(void *array[], Count length, - QuickSortCompare compare, void *closure, - SortStruct *sortStruct); + QuickSortCompare compare, void *closure, + SortStruct *sortStruct); /* Version Determination @@ -1016,7 +1016,7 @@ DECLARE_CLASS(Land, Land, Inst); /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2015 Ravenbrook Limited . + * Copyright (C) 2001-2016 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/pool.c b/mps/code/pool.c index 85c904d88aa..43cb1fbe342 100644 --- a/mps/code/pool.c +++ b/mps/code/pool.c @@ -1,7 +1,7 @@ /* pool.c: POOL IMPLEMENTATION * * $Id$ - * Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * Portions copyright (C) 2001 Global Graphics Software. * * DESIGN @@ -73,11 +73,11 @@ Bool PoolClassCheck(PoolClass klass) /* Check that pool classes overide sets of related methods. */ CHECKL((klass->init == PoolAbsInit) == (klass->finish == PoolAbsFinish)); CHECKL((klass->bufferFill == PoolNoBufferFill) == - (klass->bufferEmpty == PoolNoBufferEmpty)); + (klass->bufferEmpty == PoolNoBufferEmpty)); CHECKL((klass->framePush == PoolNoFramePush) == - (klass->framePop == PoolNoFramePop)); + (klass->framePop == PoolNoFramePop)); CHECKL((klass->rampBegin == PoolNoRampBegin) == - (klass->rampEnd == PoolNoRampEnd)); + (klass->rampEnd == PoolNoRampEnd)); /* Check that pool classes that set attributes also override the methods they imply. */ @@ -651,7 +651,7 @@ Bool PoolHasRange(Pool pool, Addr base, Addr limit) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2015 Ravenbrook Limited . + * Copyright (C) 2001-2016 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/protocol.c b/mps/code/protocol.c index 84f8002f506..7a749afd9bf 100644 --- a/mps/code/protocol.c +++ b/mps/code/protocol.c @@ -143,8 +143,8 @@ Res InstDescribe(Inst inst, mps_lib_FILE *stream, Count depth) klass = ClassOfPoly(Inst, inst); return WriteF(stream, depth, - "$S $P\n", (WriteFS)ClassName(klass), inst, - NULL); + "$S $P\n", (WriteFS)ClassName(klass), inst, + NULL); } diff --git a/mps/code/protocol.h b/mps/code/protocol.h index 071e31e7a7d..3b469d690e9 100644 --- a/mps/code/protocol.h +++ b/mps/code/protocol.h @@ -117,13 +117,13 @@ typedef void *ClassId; LockClaimGlobalRecursive(); \ if (CLASS_GUARDIAN(className) == FALSE) { \ CLASS_INIT(className)(klass); \ - /* Prevent infinite regress. */ \ - if (CLASS_ID(className) != CLASS_ID(InstClass) && \ - CLASS_ID(className) != CLASS_ID(Inst)) \ + /* Prevent infinite regress. */ \ + if (CLASS_ID(className) != CLASS_ID(InstClass) && \ + CLASS_ID(className) != CLASS_ID(Inst)) \ SetClassOfPoly(klass, CLASS(KIND_CLASS(kind))); \ AVER(CLASS_CHECK(kind)(klass)); \ CLASS_GUARDIAN(className) = TRUE; \ - ClassRegister(MustBeA(InstClass, klass)); \ + ClassRegister(MustBeA(InstClass, klass)); \ } \ LockReleaseGlobalRecursive(); \ } \ @@ -248,15 +248,15 @@ extern void ClassRegister(InstClass klass); #define MustBeA(_class, inst) \ CouldBeA(_class, \ - AVERPC(IsNonNullAndA(_class, inst), \ - "MustBeA " #_class ": " #inst, \ - inst)) + AVERPC(IsNonNullAndA(_class, inst), \ + "MustBeA " #_class ": " #inst, \ + inst)) #define MustBeA_CRITICAL(_class, inst) \ CouldBeA(_class, \ - AVERPC_CRITICAL(IsNonNullAndA(_class, inst), \ - "MustBeA " #_class ": " #inst, \ - inst)) + AVERPC_CRITICAL(IsNonNullAndA(_class, inst), \ + "MustBeA " #_class ": " #inst, \ + inst)) /* Protocol introspection interface diff --git a/mps/code/segsmss.c b/mps/code/segsmss.c index 5e0e63d4510..a4f9ebab030 100644 --- a/mps/code/segsmss.c +++ b/mps/code/segsmss.c @@ -537,8 +537,8 @@ static Res AMSTBufferFill(Addr *baseReturn, Addr *limitReturn, if (amstseg->prev != NULL) { Seg segLo = AMSTSeg2Seg(amstseg->prev); if (SegBuffer(segLo) == NULL && - SegGrey(segLo) == SegGrey(seg) && - SegWhite(segLo) == SegWhite(seg)) { + SegGrey(segLo) == SegGrey(seg) && + SegWhite(segLo) == SegWhite(seg)) { /* .merge */ Seg mergedSeg; Res mres; diff --git a/mps/code/shield.c b/mps/code/shield.c index 64ab135ff1e..84b7c0d9c70 100644 --- a/mps/code/shield.c +++ b/mps/code/shield.c @@ -409,7 +409,7 @@ static void shieldFlushEntries(Shield shield) QuickSort((void *)shield->queue, shield->limit, shieldQueueEntryCompare, UNUSED_POINTER, - &shield->sortStruct); + &shield->sortStruct); mode = AccessSetEMPTY; limit = NULL; diff --git a/mps/design/diag.txt b/mps/design/diag.txt index 90918307a6c..f4da8c41724 100644 --- a/mps/design/diag.txt +++ b/mps/design/diag.txt @@ -78,7 +78,7 @@ There are two mechanism for getting diagnostic output: 0x00007fff83e42d46 in __kill () (gdb) frame 12 #12 0x000000010000b1fc in MVTFree (pool=0x103ffe160, base=0x101dfd000, size=5024) at poolmv2.c:711 - 711 Res res = CBSInsert(MVTCBS(mvt), base, limit); + 711 Res res = CBSInsert(MVTCBS(mvt), base, limit); (gdb) p MVTDescribe(mvt, mps_lib_get_stdout(), 0) MVT 0000000103FFE160 { minSize: 8 @@ -238,7 +238,7 @@ Document History Copyright and License --------------------- -Copyright © 2013-2014 Ravenbrook Limited . +Copyright © 2013-2016 Ravenbrook Limited . All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options. diff --git a/mps/design/index.txt b/mps/design/index.txt index e486020574d..decfb0fe66d 100644 --- a/mps/design/index.txt +++ b/mps/design/index.txt @@ -213,20 +213,20 @@ References Document History ---------------- -- 2002-05-23 RB_ Created empty catalogue based on P4DTI design document catalogue. -- 2002-06-07 RB_ Added a bunch of design documents referenced by the source code. -- 2002-06-21 NB_ Remove P4DTI reference, which doesn't fit here. Maybe one day we'll have a corporate design document procedure. -- 2002-06-24 RB_ Added fix, object-debug, thread-manager, and thread-safety. -- 2007-02-08 RHSK Added message-gc and shield. -- 2007-06-12 RHSK Added cstyle. -- 2007-06-28 RHSK Added diag. -- 2008-12-04 RHSK Added tests. -- 2008-12-10 RHSK Correct description of message-gc: gc begin or end. -- 2012-09-14 RB_ Added link to critical-path -- 2013-05-10 RB_ Fixed link to sig and added guide.hex.trans -- 2013-05-22 GDR_ Add link to keyword-arguments. -- 2013-05-25 RB_ Replacing "cstyle" with reworked "guide.impl.c.format". -- 2013-06-07 RB_ Converting to reST_. Linking to [RB_2002-06-18]_. +- 2002-05-23 RB_ Created empty catalogue based on P4DTI design document catalogue. +- 2002-06-07 RB_ Added a bunch of design documents referenced by the source code. +- 2002-06-21 NB_ Remove P4DTI reference, which doesn't fit here. Maybe one day we'll have a corporate design document procedure. +- 2002-06-24 RB_ Added fix, object-debug, thread-manager, and thread-safety. +- 2007-02-08 RHSK Added message-gc and shield. +- 2007-06-12 RHSK Added cstyle. +- 2007-06-28 RHSK Added diag. +- 2008-12-04 RHSK Added tests. +- 2008-12-10 RHSK Correct description of message-gc: gc begin or end. +- 2012-09-14 RB_ Added link to critical-path +- 2013-05-10 RB_ Fixed link to sig and added guide.hex.trans +- 2013-05-22 GDR_ Add link to keyword-arguments. +- 2013-05-25 RB_ Replacing "cstyle" with reworked "guide.impl.c.format". +- 2013-06-07 RB_ Converting to reST_. Linking to [RB_2002-06-18]_. - 2014-01-29 RB_ The arena no longer manages generation zonesets. - 2014-01-17 GDR_ Add abq, nailboard, range. - 2016-03-22 RB_ Add write-barier. diff --git a/mps/design/protocol.txt b/mps/design/protocol.txt index 8b6735effc9..b2bd308adeb 100644 --- a/mps/design/protocol.txt +++ b/mps/design/protocol.txt @@ -129,21 +129,21 @@ class is extended, it becomes a member of a different kind. Kinds allow subtype checking to be applied to classes as well as instances, to determine whether methods are available. :: - instance class kind + instance class kind (e.g. CBS) (e.g. CBSClass) (e.g. LandClassClass) - .----------. .----------. .----------. + .----------. .----------. .----------. | class |----->| class |----->| class |-->InstClassClass - ------------ ------------ ------------ - | ... | | sig | | sig | - ------------ ------------ ------------ - | ... | | name | | name | - ------------ ------------ ------------ - | ... | |superclass|-. |superclass|-->InstClassClass - ------------ ------------ | ------------ - | | | ... | | | ... | - | - | - LandClass<-' + ------------ ------------ ------------ + | ... | | sig | | sig | + ------------ ------------ ------------ + | ... | | name | | name | + ------------ ------------ ------------ + | ... | |superclass|-. |superclass|-->InstClassClass + ------------ ------------ | ------------ + | | | ... | | | ... | + | + | + LandClass<-' _`.overview.sig.inherit`: Instances (and therefore classes) will @@ -490,7 +490,7 @@ anti-method to clean-up a subsequent failure. :: static Res AMSSegInit(Seg seg, Pool pool, Addr base, Size size, - ArgList args) + ArgList args) { AMS ams = MustBeA(AMSPool, pool); Arena arena = PoolArena(pool); @@ -500,7 +500,7 @@ anti-method to clean-up a subsequent failure. :: /* Initialize the superclass fields first via next-method call */ res = NextMethod(Seg, AMSSeg, init)(seg, pool, base, size, args); if (res != ResOK) - goto failNextMethod; + goto failNextMethod; amsseg = CouldBeA(AMSSeg, seg); amsseg->grains = size >> ams->grainShift; @@ -511,10 +511,10 @@ anti-method to clean-up a subsequent failure. :: amsseg->ambiguousFixes = FALSE; res = amsCreateTables(ams, &amsseg->allocTable, - &amsseg->nongreyTable, &amsseg->nonwhiteTable, - arena, amsseg->grains); + &amsseg->nongreyTable, &amsseg->nonwhiteTable, + arena, amsseg->grains); if (res != ResOK) - goto failCreateTables; + goto failCreateTables; /* start off using firstFree, see */ amsseg->allocTableInUse = FALSE; @@ -524,7 +524,7 @@ anti-method to clean-up a subsequent failure. :: amsseg->ams = ams; RingInit(&amsseg->segRing); RingAppend((ams->allocRing)(ams, SegRankSet(seg), size), - &amsseg->segRing); + &amsseg->segRing); SetClassOfPoly(seg, CLASS(AMSSeg)); amsseg->sig = AMSSegSig; diff --git a/mps/example/scheme/scheme-advanced.c b/mps/example/scheme/scheme-advanced.c index 707390b2962..49672f6a0a3 100644 --- a/mps/example/scheme/scheme-advanced.c +++ b/mps/example/scheme/scheme-advanced.c @@ -1,6 +1,6 @@ /* scheme.c -- SCHEME INTERPRETER EXAMPLE FOR THE MEMORY POOL SYSTEM * - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * * This is a toy interpreter for a subset of the Scheme programming * language . @@ -4330,8 +4330,8 @@ static int start(int argc, char *argv[]) topic/root. */ symtab = NULL; res = mps_root_create_area(&symtab_root, arena, mps_rank_exact(), 0, - &symtab, &symtab + 1, - mps_scan_area, NULL); + &symtab, &symtab + 1, + mps_scan_area, NULL); if(res != MPS_RES_OK) error("Couldn't register symtab root"); /* The symbol table is strong-key weak-value. */ @@ -4619,7 +4619,7 @@ int main(int argc, char *argv[]) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2014 Ravenbrook Limited . + * Copyright (C) 2001-2016 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/example/scheme/scheme.c b/mps/example/scheme/scheme.c index 4a10b5c9b10..1ba280c7d59 100644 --- a/mps/example/scheme/scheme.c +++ b/mps/example/scheme/scheme.c @@ -1,6 +1,6 @@ /* scheme.c -- SCHEME INTERPRETER EXAMPLE FOR THE MEMORY POOL SYSTEM * - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * * This is a toy interpreter for a subset of the Scheme programming * language . @@ -776,8 +776,8 @@ static void rehash(void) { that both copies are updated atomically to the mutator (this interpreter). */ res = mps_root_create_area(&symtab_root, arena, mps_rank_exact(), 0, - symtab, symtab + symtab_size, - mps_scan_area, NULL); + symtab, symtab + symtab_size, + mps_scan_area, NULL); if(res != MPS_RES_OK) error("Couldn't register new symtab root"); for(i = 0; i < old_symtab_size; ++i) @@ -4262,7 +4262,7 @@ static int start(int argc, char *argv[]) assertion failures). See topic/root. */ res = mps_root_create_area(&symtab_root, arena, mps_rank_exact(), 0, symtab, symtab + symtab_size, - mps_scan_area, NULL); + mps_scan_area, NULL); if(res != MPS_RES_OK) error("Couldn't register symtab root"); error_handler = &jb; @@ -4507,7 +4507,7 @@ int main(int argc, char *argv[]) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2014 Ravenbrook Limited . + * Copyright (C) 2001-2016 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/manual/source/topic/deprecated.rst b/mps/manual/source/topic/deprecated.rst index 2bdced17215..cb1cbc6d8f4 100644 --- a/mps/manual/source/topic/deprecated.rst +++ b/mps/manual/source/topic/deprecated.rst @@ -274,14 +274,14 @@ Deprecated in version 1.115 .. c:function:: mps_res_t mps_root_create_table_masked(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_addr_t *base, size_t count, mps_word_t mask) .. deprecated:: - + This function is equivalent to:: mps_root_create_area_tagged(root_o, arena, rank, rm, base, base + size, mps_scan_area_tagged, mask, 0) - + Use :c:func:`mps_root_create_area_masked` instead, passing zero for the ``pattern`` argument. From 8e518349f4eef93097fba0c24a63f9de8fcfacaa Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Fri, 22 Apr 2016 10:08:29 +0100 Subject: [PATCH 06/52] New function seghasbuffer. Copied from Perforce Change: 191537 ServerID: perforce.ravenbrook.com --- mps/code/buffer.c | 2 +- mps/code/mpm.h | 1 + mps/code/poolamc.c | 14 +++++++------- mps/code/poolams.c | 6 +++--- mps/code/poolawl.c | 6 +++--- mps/code/poollo.c | 4 ++-- mps/code/seg.c | 10 +++++++++- mps/code/segsmss.c | 2 +- 8 files changed, 27 insertions(+), 18 deletions(-) diff --git a/mps/code/buffer.c b/mps/code/buffer.c index fd88e101f2a..c888e351709 100644 --- a/mps/code/buffer.c +++ b/mps/code/buffer.c @@ -1195,7 +1195,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)); diff --git a/mps/code/mpm.h b/mps/code/mpm.h index a5f1eaf94a0..c5ad136f4a7 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -693,6 +693,7 @@ extern Res SegMerge(Seg *mergedSegReturn, Seg segLo, Seg segHi); extern Res SegSplit(Seg *segLoReturn, Seg *segHiReturn, Seg seg, Addr at); extern Res SegDescribe(Seg seg, mps_lib_FILE *stream, Count depth); extern void SegSetSummary(Seg seg, RefSet summary); +extern Bool SegHasBuffer(Seg seg); extern Buffer SegBuffer(Seg seg); extern void SegSetBuffer(Seg seg, Buffer buffer); extern Addr SegBufferScanLimit(Seg seg); diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c index e7d0d48561c..d513e863972 100644 --- a/mps/code/poolamc.c +++ b/mps/code/poolamc.c @@ -287,7 +287,7 @@ static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) if(res != ResOK) return res; - if(SegBuffer(seg) != NULL) + if(SegHasBuffer(seg)) init = BufferGetInit(SegBuffer(seg)); else init = limit; @@ -1303,7 +1303,7 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn, NailboardClearNewNails(board); p = SegBase(seg); - while(SegBuffer(seg) != NULL) { + while (SegHasBuffer(seg)) { limit = BufferScanLimit(SegBuffer(seg)); if(p >= limit) { AVER(p == limit); @@ -1406,7 +1406,7 @@ static Res AMCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) base = AddrAdd(SegBase(seg), format->headerSize); /* */ - while(SegBuffer(seg) != NULL) { + while (SegHasBuffer(seg)) { limit = AddrAdd(BufferScanLimit(SegBuffer(seg)), format->headerSize); if(base >= limit) { @@ -1773,13 +1773,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, Seg2amcSeg(seg)->deferred); } @@ -1824,7 +1824,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)); @@ -1954,7 +1954,7 @@ static Res AMCAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr) arena = PoolArena(pool); base = SegBase(seg); - if (SegBuffer(seg) != NULL) { + if (SegHasBuffer(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 diff --git a/mps/code/poolams.c b/mps/code/poolams.c index c6d6cdf2d81..22bc614418a 100644 --- a/mps/code/poolams.c +++ b/mps/code/poolams.c @@ -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, @@ -975,7 +975,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) @@ -1637,7 +1637,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 */ PoolGenFree(&ams->pgen, seg, AMSGrainsSize(ams, amsseg->freeGrains), diff --git a/mps/code/poolawl.c b/mps/code/poolawl.c index d77e64ec14a..884c33699b4 100644 --- a/mps/code/poolawl.c +++ b/mps/code/poolawl.c @@ -658,7 +658,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)) @@ -833,7 +833,7 @@ static void AWLGrey(Pool pool, Trace trace, Seg seg) AVERT(AWLSeg, awlseg); SegSetGrey(seg, TraceSetAdd(SegGrey(seg), trace)); - if (SegBuffer(seg) != NULL) { + if (SegHasBuffer(seg)) { Addr base = SegBase(seg); Buffer buffer = SegBuffer(seg); @@ -1259,7 +1259,7 @@ static void AWLWalk(Pool pool, Seg seg, FormattedObjectsVisitor f, Addr next; Index i; - if (SegBuffer(seg) != NULL) { + if (SegHasBuffer(seg)) { Buffer buffer = SegBuffer(seg); if (object == BufferScanLimit(buffer) && BufferScanLimit(buffer) != BufferLimit(buffer)) { diff --git a/mps/code/poollo.c b/mps/code/poollo.c index d950eb6074e..11b5fd8a683 100644 --- a/mps/code/poollo.c +++ b/mps/code/poollo.c @@ -251,7 +251,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; @@ -429,7 +429,7 @@ static void LOWalk(Pool pool, Seg seg, FormattedObjectsVisitor f, Addr next; Index j; - if(SegBuffer(seg) != NULL) { + if (SegHasBuffer(seg)) { Buffer buffer = SegBuffer(seg); if(object == BufferScanLimit(buffer) && BufferScanLimit(buffer) != BufferLimit(buffer)) { diff --git a/mps/code/seg.c b/mps/code/seg.c index 33e181093f3..5595275d7bd 100644 --- a/mps/code/seg.c +++ b/mps/code/seg.c @@ -328,6 +328,14 @@ void SegSetRankAndSummary(Seg seg, RankSet rankSet, RefSet summary) } +/* SegHasBuffer -- segment has a buffer? */ + +Bool SegHasBuffer(Seg seg) +{ + return SegBuffer(seg) != NULL; +} + + /* SegBuffer -- return the buffer of a segment */ Buffer SegBuffer(Seg seg) @@ -640,7 +648,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(!SegHasBuffer(seg) || BufferLimit(SegBuffer(seg)) <= at); if (seg->queued) ShieldFlush(arena); /* see */ diff --git a/mps/code/segsmss.c b/mps/code/segsmss.c index 1de5ccf0612..e51a97947f9 100644 --- a/mps/code/segsmss.c +++ b/mps/code/segsmss.c @@ -551,7 +551,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 */ From 1d47d8f232f1e1a180b16980bc5ba3de9ed20dfb Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Fri, 22 Apr 2016 15:00:27 +0100 Subject: [PATCH 07/52] Get the mmqa test system working on windows. in detail: 1. Document how to run it on Windows from a Cygwin shell. 2. Ignore trailing spaces when analyzing test output. 3. Use the directory separator "/" since we're running under Cygwin. 4. No need for cat.exe, strings.exe, or tee.exe (these are supplied by Cygwin). 5. Microsoft Visual C/C++ needs /D_CRT_SECURE_NO_WARNINGS to avoid a warning about scanf. 6. The Microsoft Visual C/C++ linker no longer takes the options /debugtype:both or /debug:full. Replace with /debug. 7. Remove /pdb:none option (we want the PDB so that we can debug the result). 8. windows.h defines an UNALIGNED macro, so need to #undef it. 9. The long int type is 32 bits on 64-bit Windows, so we need size_t instead. 10. The values in the LPEXCEPTION_RECORD structure have type ULONG_PTR. 11. Test cases are expecting access violations to report abort=true, but on Windows they are caught by the exception handler, so report abort=true in this case. 12. mpsw3.h has gone, but we do need mpswin.h. Fix some of the test cases: 1. Avoid compiler warning about overflowed multiplication in argerr/153.c. 2. In conerr/2.c, conerr/8.c and conerr/13.c, malloc enough space so that the signature check doesn't cause an access violation. 3. In conerr/25.c, allocate an object whose size is aligned to the platform alignment, which is 16 bytes on w3i6mv. 4. In connerr/18.c, conerr/53.c and conerr/54.c, update the location and text of the expected assertions. Copied from Perforce Change: 191564 ServerID: perforce.ravenbrook.com --- mps/test/README | 38 ++++++++++++++++++++++ mps/test/argerr/153.c | 2 +- mps/test/conerr/13.c | 2 +- mps/test/conerr/18.c | 4 +-- mps/test/conerr/2.c | 2 +- mps/test/conerr/25.c | 8 ++--- mps/test/conerr/53.c | 2 +- mps/test/conerr/54.c | 2 +- mps/test/conerr/8.c | 2 +- mps/test/test/script/headread | 2 +- mps/test/test/script/ntx86bin/cat.exe | Bin 28672 -> 0 bytes mps/test/test/script/ntx86bin/strings.exe | Bin 28160 -> 0 bytes mps/test/test/script/ntx86bin/tee.exe | Bin 8704 -> 0 bytes mps/test/test/script/platform | 16 ++++----- mps/test/test/testlib/arg.h | 1 + mps/test/test/testlib/lofmt.c | 2 +- mps/test/test/testlib/lofmt.h | 2 +- mps/test/test/testlib/platform.c | 4 +-- mps/test/test/testlib/platform.h | 6 +--- 19 files changed, 65 insertions(+), 30 deletions(-) delete mode 100644 mps/test/test/script/ntx86bin/cat.exe delete mode 100644 mps/test/test/script/ntx86bin/strings.exe delete mode 100644 mps/test/test/script/ntx86bin/tee.exe diff --git a/mps/test/README b/mps/test/README index 51bdc59a581..a0be0814742 100644 --- a/mps/test/README +++ b/mps/test/README @@ -43,3 +43,41 @@ From the test directory, build mpslib.a using the Xcode project:: perl test/qa -i ../code -l ../code/xc/Debug/libmps.a run function/232.c etc. See "Testing on Unix" above. + + +Testing on Windows +------------------ + +In a Cygwin shell, from the test directory:: + + PLATFORM=w3i6mv # substitute your platform + VARIETY=cool # or hot + CODE=../code # code directory of the branch you are testing + pushd $CODE + nmake /f $PLATFORM.nmk VARIETY=$VARIETY $PLATFORM/$VARIETY/mps.obj + popd + export LANG=C # avoid locale warnings from Perl. + alias qa="perl test/qa -i $CODE -l $CODE/$PLATFORM/$VARIETY/mps.obj" + qa clib + qa run function/5.c + qa runset testsets/passing + +The runset command can result in this error:: + + LINK : fatal error LNK1168: cannot open test/obj/nt_AMD64__pc/tmp_test.exe for writing + +You may be able to avoid this by running "View Local Services" from +the Windows Control Panel, double-clicking the "Application +Experience" service, and switching "Startup type" to "Automatic". See +the documentation for LNK1168_. + +.. _LNK1168: https://msdn.microsoft.com/en-us/library/hhbdtt6d.aspx + +At present, the easiest way to debug a test case is to edit +test/test/script/platform and set:: + + $comwrap = "vsjitdebugger \""; + +But see job004020_. + +.. _job004020: https://www.ravenbrook.com/project/mps/issue/job004020/ diff --git a/mps/test/argerr/153.c b/mps/test/argerr/153.c index b6d1d6791fa..095a855d1cc 100644 --- a/mps/test/argerr/153.c +++ b/mps/test/argerr/153.c @@ -23,7 +23,7 @@ static void test(void) { cdie(mps_pool_create(&pool, arena, mps_class_mv(), 1024*32, 1024*16, 1024*256), "pool"); - cdie(mps_alloc(&q, pool, (size_t) -100 * mmqaArenaSIZE), "alloc"); + cdie(mps_alloc(&q, pool, ((size_t)-1) - 100 * mmqaArenaSIZE), "alloc"); mps_pool_destroy(pool); mps_arena_destroy(arena); diff --git a/mps/test/conerr/13.c b/mps/test/conerr/13.c index b3712a99e44..b05fe424aa1 100644 --- a/mps/test/conerr/13.c +++ b/mps/test/conerr/13.c @@ -28,7 +28,7 @@ static void test(void) /* cdie(mps_arena_create(&arena, mps_arena_class_vm(), mmqaArenaSIZE), "create arena"); */ - arena=malloc(64); + arena=malloc(4096); cdie( mps_pool_create(&pool, arena, mps_class_mv(), diff --git a/mps/test/conerr/18.c b/mps/test/conerr/18.c index 4d13dede9b9..d6ea9e923b5 100644 --- a/mps/test/conerr/18.c +++ b/mps/test/conerr/18.c @@ -6,8 +6,8 @@ TEST_HEADER link = testlib.o OUTPUT_SPEC assert = true - assertfile P= poollo.c - assertcond = FormatArena(pool->format) == arena + assertfile P= poolabs.c + assertcond = FormatArena(format) == arena END_HEADER */ diff --git a/mps/test/conerr/2.c b/mps/test/conerr/2.c index 78738d5bc85..ba18c963be0 100644 --- a/mps/test/conerr/2.c +++ b/mps/test/conerr/2.c @@ -17,7 +17,7 @@ static void test(void) { mps_arena_t arena; - arena = malloc(64); + arena = malloc(4096); mps_arena_destroy(arena); comment("Destroy arena."); } diff --git a/mps/test/conerr/25.c b/mps/test/conerr/25.c index 35e4c5c03c7..c4cfc508eea 100644 --- a/mps/test/conerr/25.c +++ b/mps/test/conerr/25.c @@ -30,13 +30,13 @@ static void test(void) cdie(mps_ap_create(&ap, pool), "create ap"); - cdie(mps_reserve(&obj, ap, 152), "reserve"); - (void)mps_commit(ap, &obj, 152); + cdie(mps_reserve(&obj, ap, 256), "reserve"); + (void)mps_commit(ap, &obj, 256); - mps_free(pool, obj, 152); + mps_free(pool, obj, 256); comment("Freed."); - mps_free(pool, obj, 152); + mps_free(pool, obj, 256); comment("Freed again."); mps_pool_destroy(pool); diff --git a/mps/test/conerr/53.c b/mps/test/conerr/53.c index d156e3d7f05..ac072dfda0d 100644 --- a/mps/test/conerr/53.c +++ b/mps/test/conerr/53.c @@ -7,7 +7,7 @@ TEST_HEADER OUTPUT_SPEC assert = true assertfile P= ld.c - assertcond = ld->_epoch <= arena->epoch + assertcond = ld->_epoch <= ArenaHistory(arena)->epoch END_HEADER */ diff --git a/mps/test/conerr/54.c b/mps/test/conerr/54.c index f5474c6e318..3439f22cb71 100644 --- a/mps/test/conerr/54.c +++ b/mps/test/conerr/54.c @@ -7,7 +7,7 @@ TEST_HEADER OUTPUT_SPEC assert = true assertfile P= ld.c - assertcond = ld->_epoch <= arena->epoch + assertcond = ld->_epoch <= history->epoch END_HEADER */ diff --git a/mps/test/conerr/8.c b/mps/test/conerr/8.c index ba37375ea93..63bfc1577e7 100644 --- a/mps/test/conerr/8.c +++ b/mps/test/conerr/8.c @@ -19,7 +19,7 @@ static void test(void) mps_arena_t arena; mps_fmt_t format; - arena=malloc(64); + arena=malloc(4096); cdie(mps_fmt_create_k(&format, arena, mps_args_none), "create format"); diff --git a/mps/test/test/script/headread b/mps/test/test/script/headread index 794027763b2..99c1d0f1359 100644 --- a/mps/test/test/script/headread +++ b/mps/test/test/script/headread @@ -149,7 +149,7 @@ sub read_results { &debug($_); if (/^!/) { # result variable - if (/^!(\w+)\s*=\s*(.+)\s*/) { + if (/^!(\w+)\s*=\s*(.+?)\s*$/) { $real_output{$1} = $2 } else { die "Badly formatted result line in output:\n$_\n"; diff --git a/mps/test/test/script/ntx86bin/cat.exe b/mps/test/test/script/ntx86bin/cat.exe deleted file mode 100644 index 66e26ec6d865d3741224d982cb477fb20e210a14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28672 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 diff --git a/mps/test/test/script/ntx86bin/strings.exe b/mps/test/test/script/ntx86bin/strings.exe deleted file mode 100644 index 80bfe2e3f89db8d641530b1f1def1b336de1283a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28160 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

    jWfU;zX zK4#zqfwF@@P=+@sMZ>!rhdDqlh2+kF7osp{F|vZZ1&w)o1_p+gexN3Q?H30AmP?GF z+VDlE>l27PILH|ITaJKh$uG?nEDR<5-L-$*J8eP9=jAeR0ReGWEwZ~hFEG3E^alLt zW^w?P^s1oBO#tT1OcZCzK%Dv77F<6I1YtLZe;-`?G!*T3*+IS(fyB`ZeXwCHod+Pk z+yVAq9y0^O%jKXJWw$HH4~+b+GeIR2C{2S(7DZ$$K|v`ZfSf&E=TCrzy)m*%gdai8 zpl*SnjKe4{a|XK%7XDMgJh;ocT?HB}tV%g{STQg#yk?sKc4_B_EP#k{g4&dp$@UobRfnfqD z$CX$iJ00RlaDG$*+Xe|?YPB?=^lOR*bKstPs&76>m<0>O?A6g>j3 zEhj(}VHyF+*gT-{0S4}Ag21uF&ht$hijL>lE66gqh{2#1_f1m4P zNExx_E7TXAt}np$f?Aer5dF=yFBnQV8fqU~l`y@|g2k*KtdXGtH3jS-Effb8u|oW! zGyz$S3yK;)h#HWB#R3iv3=r3X%A;=A7Y+>;R{X8k!I|kr^8qGM3NVAYuS5vUS`5lq z5SPB@LR7<$PyiKEFQ}nsvf4*T?p+<-jK5tUnNLHxYj-+q|y$Aq1ngu$H!k~=3sUI>FlSUL{`WU!)`)C4gJruV-W zM{^YiLv2B~D7cJu;(;=}c)A@pEFC549bihknT|1VAvg^dTqS%6?tiA&!Z2P?7T1ee zV0$=Ti%dWkZGnnP!9~$b{m%qf{=y!tn57vs_{0MaV*ST^?^=T4n*r8>J|>Tp9C06nO}QPKuLVA zU=w*jCW6Md7;42|9AX6Zhe1OL%&$*P=nnnSdEvDzXv~Wd)Oh&8=*rXW`a{!I;PqOB z>wC@I{X!LrGjvN!GINR*4D}3+AZhot@Py_AEQ=K!92gdYh;D~J|1W@9%@z!$Pr&`x z;BL_~>JALezy6m>8D46(y`T;n`Q_gMqCvWyKuW)NUT8f~BGxO@3R2t6{QpAp;XjSP zL7dW$87EX77+y4js_WQ4U^AO-RX{y1P^SvS05v6EO#J`Ap>O8i!}_OQSe@~|EgO892h1{_^)~bO0R&@SD^F)C_Mv8 zAA!~voLXGW5XS^jZO;%NUtFG4 zn#RDukjIpkmQz}s0WzbODXpL=Gp__B-pG_zl$y%GFpViawInsK3?%=ADHk-}lMG`2 zXUZ=~&0}ETWQJ>D5Ml-m=rb^gf#{r^e2_wCX2|RkNKY7ZaY<2fZUKlL4Prxv{uyFH z>>QA33=9b%b{<60ROT|cgBCD@C$<JorNZ02m?6 A*#H0l diff --git a/mps/test/test/script/platform b/mps/test/test/script/platform index 88b3320db76..9dba51fdef7 100644 --- a/mps/test/test/script/platform +++ b/mps/test/test/script/platform @@ -46,12 +46,12 @@ sub platform_settings { sub settings_nt { - $dirsep = "\\"; + $dirsep = "/"; $cc_command = "cl"; # following line used to include /DMMQA_VERS_$MPS_INTERFACE_VERSION - $cc_opts = "/nologo /DWIN32 /D_WINDOWS /W3 /Zi /Oy- /MD /DMMQA_PROD_$MPS_PRODUCT"; + $cc_opts = "/nologo /DWIN32 /D_WINDOWS /D_CRT_SECURE_NO_WARNINGS /W3 /Zi /Oy- /MD /DMMQA_PROD_$MPS_PRODUCT"; $cc_link = "$obj_dir/platform.obj"; - $cc_link_opts = "/link /NODEFAULTLIB:LIBCMT /NODEFAULTLIB:LIBCMTD /NODEFAULTLIB:LIBC /NODEFAULTLIB:LIBCD /NODEFAULTLIB:MSVCRTD /DEFAULTLIB:MSVCRT /debugtype:both /pdb:none /debug:full"; + $cc_link_opts = "/link /NODEFAULTLIB:LIBCMT /NODEFAULTLIB:LIBCMTD /NODEFAULTLIB:LIBC /NODEFAULTLIB:LIBCD /NODEFAULTLIB:MSVCRTD /DEFAULTLIB:MSVCRT /debug"; $cc_include = "/I$testlib_dir /I$MPS_INCLUDE_DIR /I$obj_dir"; $cc_def = "/D"; $cc_defeq = "="; @@ -62,16 +62,16 @@ sub settings_nt { $cc_objandexe = 1; $obj_suffix = ".obj"; $try_command = ""; - $catcommand = "$script_dir/ntx86bin/cat.exe"; + $catcommand = "cat"; $comwrap = "\""; $comwrapend = "\""; $stdout_red = ">"; - $stdout_dup = "| $script_dir/ntx86bin/tee.exe"; + $stdout_dup = "| tee"; $stdin_red = "<"; $stdboth_red = ">%s 2>&1"; $quotestring = \&nt_quotestring; $platmailfile = \&nt_mailfile; - $stringscommand = "$script_dir/ntx86bin/strings.exe -20 -c"; + $stringscommand = "strings"; $preprocommand = "$cc_command /nologo $cc_preonly"; $exesuff = ".exe"; %ignored_headers = (); @@ -80,11 +80,11 @@ sub settings_nt { sub settings_nt_cap { $cc_opts = "$cc_opts /Gh"; $cc_link = "$cc_link CAP.lib"; - $cc_link_opts = "/link /NODEFAULTLIB:LIBCMT /NODEFAULTLIB:LIBCMTD /NODEFAULTLIB:LIBC /NODEFAULTLIB:LIBCD /NODEFAULTLIB:MSVCRTD /DEFAULTLIB:MSVCRT /debug:full /debugtype:both /pdb:none"; + $cc_link_opts = "/link /NODEFAULTLIB:LIBCMT /NODEFAULTLIB:LIBCMTD /NODEFAULTLIB:LIBC /NODEFAULTLIB:LIBCD /NODEFAULTLIB:MSVCRTD /DEFAULTLIB:MSVCRT /debug"; } sub settings_nt_coff { - $cc_link_opts = "/link /NODEFAULTLIB:LIBCMT /NODEFAULTLIB:LIBCMTD /NODEFAULTLIB:LIBC /NODEFAULTLIB:LIBCD /NODEFAULTLIB:MSVCRTD /DEFAULTLIB:MSVCRT /debugtype:coff /debug:full"; + $cc_link_opts = "/link /NODEFAULTLIB:LIBCMT /NODEFAULTLIB:LIBCMTD /NODEFAULTLIB:LIBC /NODEFAULTLIB:LIBCD /NODEFAULTLIB:MSVCRTD /DEFAULTLIB:MSVCRT /debug"; } diff --git a/mps/test/test/testlib/arg.h b/mps/test/test/testlib/arg.h index 95fa4996f3f..f2f07b81501 100644 --- a/mps/test/test/testlib/arg.h +++ b/mps/test/test/testlib/arg.h @@ -8,6 +8,7 @@ arg.h #include "testlib.h" +#undef UNALIGNED #define UNALIGNED ((mps_addr_t) (((char *) NULL) + 1)) #define MPS_RANK_MIN 0 diff --git a/mps/test/test/testlib/lofmt.c b/mps/test/test/testlib/lofmt.c index 51697c00bdf..35567c8f314 100644 --- a/mps/test/test/testlib/lofmt.c +++ b/mps/test/test/testlib/lofmt.c @@ -186,7 +186,7 @@ long int getlocopycount(locell *obj) return obj->data.copycount; } -long int getlosize(locell *obj) +size_t getlosize(locell *obj) { asserts(obj->tag == LOdata, "getlosize: non-data object."); return obj->data.size - offsetof(struct lodata, data); diff --git a/mps/test/test/testlib/lofmt.h b/mps/test/test/testlib/lofmt.h index 14b9ce2a2c5..e8e2c17d02d 100644 --- a/mps/test/test/testlib/lofmt.h +++ b/mps/test/test/testlib/lofmt.h @@ -56,7 +56,7 @@ locell *alloclo(mps_ap_t ap, size_t bytes); long int getloid(locell *obj); long int getlocopycount(locell *obj); -long int getlosize(locell *obj); +size_t getlosize(locell *obj); #endif diff --git a/mps/test/test/testlib/platform.c b/mps/test/test/testlib/platform.c index 23ffd36f234..83badbf2759 100644 --- a/mps/test/test/testlib/platform.c +++ b/mps/test/test/testlib/platform.c @@ -8,8 +8,7 @@ LONG mySEHFilter(LPEXCEPTION_POINTERS info) { LPEXCEPTION_RECORD er; - int write; - unsigned long address; + ULONG_PTR write, address; er = info->ExceptionRecord; @@ -23,6 +22,7 @@ LONG mySEHFilter(LPEXCEPTION_POINTERS info) { report("memoryop", "read"); } report("memoryaddr", "%ld", address); + report("abort", "true"); myabort(); } diff --git a/mps/test/test/testlib/platform.h b/mps/test/test/testlib/platform.h index c10eb1b103d..86224174957 100644 --- a/mps/test/test/testlib/platform.h +++ b/mps/test/test/testlib/platform.h @@ -4,12 +4,8 @@ */ #ifdef MPS_OS_W3 -#ifdef MMQA_HEADER_mpsw3 -/* we may be required to include mpsw3.h on windows platforms */ -#include "mpsw3.h" -#endif +#include "mpswin.h" /* to trap access violations in the test harness */ LONG mySEHFilter(LPEXCEPTION_POINTERS); #endif - From fd3136bb30d59fad528f427be6099811c9a860b4 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Fri, 22 Apr 2016 15:44:58 +0100 Subject: [PATCH 08/52] Fix mmqa function test cases so that they run on windows. in detail: 1. On w3i6mv, int and long are 32 bits, so these types can't be used to hold a size_t or an mps_word_t. See 26.c, 38.c, 47.c, 66.c, 123.c, 136.c, 164.c, 165.c, 200.c, 203.c, 204.c, 205.c, 206.c, 207.c, 215.c, 223.c. 2. The Windows command line doesn't cope with parentheses. See 170.c. 3. The natural platform alignment is 16 bytes on w3i6mv, so allocations into pools using the default alignment need to be rounded up. See 21.c, 22.c, 203.c, 204.c, 205.c. 4. Microsoft Visual C/C++ is fussy about signed/unsigned comparison. See 226.c. 5. windows.h defines a SIZE macro so you can't use it as a parameter. See 232.c. Copied from Perforce Change: 191569 ServerID: perforce.ravenbrook.com --- mps/test/function/123.c | 2 +- mps/test/function/136.c | 2 +- mps/test/function/140.c | 12 ++++++------ mps/test/function/164.c | 12 ++++++------ mps/test/function/165.c | 2 +- mps/test/function/167.c | 2 +- mps/test/function/170.c | 2 +- mps/test/function/200.c | 12 ++++++------ mps/test/function/203.c | 14 +++++++------- mps/test/function/204.c | 14 +++++++------- mps/test/function/205.c | 14 +++++++------- mps/test/function/206.c | 14 +++++++------- mps/test/function/207.c | 12 ++++++------ mps/test/function/21.c | 4 ++-- mps/test/function/215.c | 2 +- mps/test/function/22.c | 4 ++-- mps/test/function/223.c | 2 +- mps/test/function/226.c | 2 +- mps/test/function/232.c | 10 +++++----- mps/test/function/26.c | 3 ++- mps/test/function/38.c | 3 ++- mps/test/function/47.c | 3 ++- mps/test/function/66.c | 3 ++- 23 files changed, 77 insertions(+), 73 deletions(-) diff --git a/mps/test/function/123.c b/mps/test/function/123.c index 4166f30f685..0e354e29bed 100644 --- a/mps/test/function/123.c +++ b/mps/test/function/123.c @@ -35,7 +35,7 @@ static void test(void) mps_fmt_t format; mps_ap_t apamc, apawl; - unsigned int i, c; + mps_word_t i, c; cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t) (60ul*1024*1024)), "create arena"); diff --git a/mps/test/function/136.c b/mps/test/function/136.c index b76a2fcf59a..f333a206f4d 100644 --- a/mps/test/function/136.c +++ b/mps/test/function/136.c @@ -55,7 +55,7 @@ static void do_test(size_t extendBy, size_t avgSize, size_t align, mps_addr_t p; unsigned int i; unsigned long nLargeObjects = 0, nSmallObjects = 0; - unsigned long largeObjectSize, smallObjectSize; + size_t largeObjectSize, smallObjectSize; largeObjectSize = extendBy; smallObjectSize = align; diff --git a/mps/test/function/140.c b/mps/test/function/140.c index 7502386c7f1..ae442893a12 100644 --- a/mps/test/function/140.c +++ b/mps/test/function/140.c @@ -61,7 +61,7 @@ static int chkobj(mps_addr_t a, size_t size, unsigned char val) static void dt(int kind, size_t extendBy, size_t avgSize, size_t align, - size_t mins, size_t maxs, int number, int iter) + unsigned long mins, unsigned long maxs, int number, int iter) { mps_pool_t pool; int i, hd; @@ -114,11 +114,11 @@ static void dt(int kind, if (queue[hd].addr != NULL) { asserts(chkobj(queue[hd].addr, queue[hd].size, (unsigned char) (hd%256)), - "corrupt at %p (%s: %x, %x, %x, %c%c%c, %x, %x, %i, %i)", + "corrupt at %p (%s: %x, %x, %x, %c%c%c, %lx, %lx, %i, %i)", queue[hd].addr, tdesc[kind], (int) extendBy, (int) avgSize, (int) align, slotHigh ? 'S' : 's', arenaHigh ? 'A' : 'a', firstFit ? 'F' : 'f', - (int) mins, (int) maxs, number, iter); + mins, maxs, number, iter); commentif(comments, "Free %i at %x, size %x", hd, queue[hd].addr, queue[hd].size); mps_free(pool, queue[hd].addr, queue[hd].size); @@ -147,16 +147,16 @@ static void dt(int kind, time1=clock(); secs=(time1-time0)/(double)CLOCKS_PER_SEC; - comment("%s test (%x, %x, %x, %c%c%c, %x, %x, %i, %i) in %.2f s", + comment("%s test (%x, %x, %x, %c%c%c, %lx, %lx, %i, %i) in %.2f s", tdesc[kind], (int) extendBy, (int) avgSize, (int) align, slotHigh ? 'S' : 's', arenaHigh ? 'A' : 'a', firstFit ? 'F' : 'f', - (int) mins, (int) maxs, number, iter, secs); + mins, maxs, number, iter, secs); } static void test(void) { mps_thr_t thread; - size_t mins; + unsigned long mins; int symm; size_t comlimit; diff --git a/mps/test/function/164.c b/mps/test/function/164.c index aece86397f2..368bbffd86e 100644 --- a/mps/test/function/164.c +++ b/mps/test/function/164.c @@ -58,7 +58,7 @@ static int chkobj(mps_addr_t a, size_t size, unsigned char val) static void dt(int kind, size_t extendBy, size_t avgSize, size_t align, - size_t mins, size_t maxs, int number, int iter) + unsigned long mins, unsigned long maxs, int number, int iter) { mps_pool_t pool; int i, hd; @@ -107,11 +107,11 @@ static void dt(int kind, if (queue[hd].addr != NULL) { asserts(chkobj(queue[hd].addr, queue[hd].size, (unsigned char) (hd%256)), - "corrupt at %x (%s: %x, %x, %x, %c%c%c, %x, %x, %i, %i)", + "corrupt at %x (%s: %x, %x, %x, %c%c%c, %lx, %lx, %i, %i)", queue[hd].addr, tdesc[kind], (int) extendBy, (int) avgSize, (int) align, slotHigh ? 'S' : 's', arenaHigh ? 'A' : 'a', firstFit ? 'F' : 'f', - (int) mins, (int) maxs, number, iter); + mins, maxs, number, iter); commentif(comments, "Free %i at %x, size %x", hd, queue[hd].addr, queue[hd].size); mps_free(pool, queue[hd].addr, queue[hd].size); @@ -140,16 +140,16 @@ static void dt(int kind, time1=clock(); secs=(time1-time0)/(double)CLOCKS_PER_SEC; - comment("%s test (%x, %x, %x, %c%c%c, %x, %x, %i, %i) in %.2f s", + comment("%s test (%x, %x, %x, %c%c%c, %lx, %lx, %i, %i) in %.2f s", tdesc[kind], (int) extendBy, (int) avgSize, (int) align, slotHigh ? 'S' : 's', arenaHigh ? 'A' : 'a', firstFit ? 'F' : 'f', - (int) mins, (int) maxs, number, iter, secs); + mins, maxs, number, iter, secs); } static void test(void) { mps_thr_t thread; - size_t mins; + unsigned long mins; int symm; size_t comlimit; diff --git a/mps/test/function/165.c b/mps/test/function/165.c index 5bd3bda7a44..167854851a0 100644 --- a/mps/test/function/165.c +++ b/mps/test/function/165.c @@ -30,7 +30,7 @@ static void test(void) mps_pool_t pool; mps_thr_t thread; - unsigned long com0, com1, com2; + size_t com0, com1, com2; /* create a VM arena of 40MB with commit limit of 100MB, i.e. let the arena do the limiting. */ diff --git a/mps/test/function/167.c b/mps/test/function/167.c index c8858668099..fa17c120fb7 100644 --- a/mps/test/function/167.c +++ b/mps/test/function/167.c @@ -30,7 +30,7 @@ static void test(void) mps_pool_t poolhi, poollo; mps_thr_t thread; - unsigned long com0, com1; + size_t com0, com1; /* create a VM arena of 40MB */ diff --git a/mps/test/function/170.c b/mps/test/function/170.c index 28eb7028be7..85a6a89852c 100644 --- a/mps/test/function/170.c +++ b/mps/test/function/170.c @@ -5,7 +5,7 @@ TEST_HEADER language = c link = testlib.o rankfmt.o harness = 2.1 - parameters = EXTEND=65536 AVGSIZE=32 BIGSIZE=(5*1024*1024); + parameters = EXTEND=65536 AVGSIZE=32 BIGSIZE=5*1024*1024 OUTPUT_SPEC completed = yes failed = no diff --git a/mps/test/function/200.c b/mps/test/function/200.c index 90e5494da92..4000d9e4185 100644 --- a/mps/test/function/200.c +++ b/mps/test/function/200.c @@ -57,7 +57,7 @@ static int chkobj(mps_addr_t a, size_t size, unsigned char val) static void dt(int kind, size_t extendBy, size_t avgSize, size_t maxSize, - size_t mins, size_t maxs, int number, int iter) + unsigned long mins, unsigned long maxs, int number, int iter) { mps_pool_t pool; int i, hd; @@ -101,10 +101,10 @@ static void dt(int kind, if (queue[hd].addr != NULL) { asserts(chkobj(queue[hd].addr, queue[hd].size, (unsigned char) (hd%256)), - "corrupt at %x (%s: %x, %x, %x, %x, %x, %i, %i)", + "corrupt at %x (%s: %x, %x, %x, %lx, %lx, %i, %i)", queue[hd].addr, tdesc[kind], (int) extendBy, (int) avgSize, (int) maxSize, - (int) mins, (int) maxs, number, iter); + mins, maxs, number, iter); mps_free(pool, queue[hd].addr, queue[hd].size); } size = ranrange(mins, maxs); @@ -126,15 +126,15 @@ static void dt(int kind, time1=clock(); secs=(time1-time0)/(double)CLOCKS_PER_SEC; - comment("%s test (%x, %x, %x, %x, %x, %i, %i) in %.2f s", + comment("%s test (%x, %x, %x, %lx, %lx, %i, %i) in %.2f s", tdesc[kind], (int) extendBy, (int) avgSize, (int) maxSize, - (int) mins, (int) maxs, number, iter, secs); + mins, maxs, number, iter, secs); } static void test(void) { mps_thr_t thread; - size_t mins; + unsigned long mins; cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t) (1024*1024*50)), "create arena"); cdie(mps_thread_reg(&thread, arena), "register thread"); diff --git a/mps/test/function/203.c b/mps/test/function/203.c index 479ab25cbda..360f6ffd8be 100644 --- a/mps/test/function/203.c +++ b/mps/test/function/203.c @@ -42,7 +42,7 @@ static void setobj(mps_addr_t a, size_t size, unsigned char val) static mps_res_t mvt_alloc(mps_addr_t *ref, mps_ap_t ap, size_t size) { mps_res_t res; - size = ((size+7)/8)*8; + size = (size + MPS_PF_ALIGN - 1) & ~(MPS_PF_ALIGN - 1); do { MPS_RESERVE_BLOCK(res, *ref, ap, size); @@ -71,7 +71,7 @@ static int chkobj(mps_addr_t a, size_t size, unsigned char val) static void dt(int kind, size_t minSize, size_t avgSize, size_t maxSize, mps_word_t depth, mps_word_t fragLimit, - size_t mins, size_t maxs, int number, int iter) + unsigned long mins, unsigned long maxs, int number, int iter) { mps_pool_t pool; mps_ap_t ap; @@ -118,11 +118,11 @@ static void dt(int kind, if (queue[hd].addr != NULL) { asserts(chkobj(queue[hd].addr, queue[hd].size, (unsigned char) (hd%256)), - "corrupt at %x (%s: %x, %x, %x, %i, %i, %x, %x, %i, %i)", + "corrupt at %x (%s: %x, %x, %x, %i, %i, %lx, %lx, %i, %i)", queue[hd].addr, tdesc[kind], (int) minSize, (int) avgSize, (int) maxSize, (int) depth, (int) fragLimit, - (int) mins, (int) maxs, number, iter); + mins, maxs, number, iter); mps_free(pool, queue[hd].addr, queue[hd].size); } size = ranrange(mins, maxs); @@ -145,16 +145,16 @@ static void dt(int kind, time1=clock(); secs=(time1-time0)/(double)CLOCKS_PER_SEC; - comment("%s test (%x, %x, %x, %i, %i, %x, %x, %i, %i) in %.2f s", + comment("%s test (%x, %x, %x, %i, %i, %lx, %lx, %i, %i) in %.2f s", tdesc[kind], (int) minSize, (int) avgSize, (int) maxSize, (int) depth, (int) fragLimit, - (int) mins, (int) maxs, number, iter, secs); + mins, maxs, number, iter, secs); } static void test(void) { mps_thr_t thread; - size_t mins; + unsigned long mins; mps_word_t dep, frag; cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t) (1024*1024*100)), "create arena"); diff --git a/mps/test/function/204.c b/mps/test/function/204.c index 52af542c913..73d087c0adf 100644 --- a/mps/test/function/204.c +++ b/mps/test/function/204.c @@ -42,7 +42,7 @@ static void setobj(mps_addr_t a, size_t size, unsigned char val) static mps_res_t mvt_alloc(mps_addr_t *ref, mps_ap_t ap, size_t size) { mps_res_t res; - size = ((size+7)/8)*8; + size = (size + MPS_PF_ALIGN - 1) & ~ (MPS_PF_ALIGN - 1); do { MPS_RESERVE_BLOCK(res, *ref, ap, size); @@ -71,7 +71,7 @@ static int chkobj(mps_addr_t a, size_t size, unsigned char val) static void dt(int kind, size_t minSize, size_t avgSize, size_t maxSize, mps_word_t depth, mps_word_t fragLimit, - size_t mins, size_t maxs, int number, int iter) + unsigned long mins, unsigned long maxs, int number, int iter) { mps_pool_t pool; mps_ap_t ap; @@ -118,11 +118,11 @@ static void dt(int kind, if (queue[hd].addr != NULL) { asserts(chkobj(queue[hd].addr, queue[hd].size, (unsigned char) (hd%256)), - "corrupt at %x (%s: %x, %x, %x, %i, %i, %x, %x, %i, %i)", + "corrupt at %x (%s: %x, %x, %x, %i, %i, %lx, %lx, %i, %i)", queue[hd].addr, tdesc[kind], (int) minSize, (int) avgSize, (int) maxSize, (int) depth, (int) fragLimit, - (int) mins, (int) maxs, number, iter); + mins, maxs, number, iter); mps_free(pool, queue[hd].addr, queue[hd].size); } size = ranrange(mins, maxs); @@ -145,16 +145,16 @@ static void dt(int kind, time1=clock(); secs=(time1-time0)/(double)CLOCKS_PER_SEC; - comment("%s test (%x, %x, %x, %i, %i, %x, %x, %i, %i) in %.2f s", + comment("%s test (%x, %x, %x, %i, %i, %lx, %lx, %i, %i) in %.2f s", tdesc[kind], (int) minSize, (int) avgSize, (int) maxSize, (int) depth, (int) fragLimit, - (int) mins, (int) maxs, number, iter, secs); + mins, maxs, number, iter, secs); } static void test(void) { mps_thr_t thread; - size_t mins; + unsigned long mins; mps_word_t dep, frag; cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t) (1024*1024*100)), "create arena"); diff --git a/mps/test/function/205.c b/mps/test/function/205.c index 16ff013c766..ff94d098ca2 100644 --- a/mps/test/function/205.c +++ b/mps/test/function/205.c @@ -42,7 +42,7 @@ static void setobj(mps_addr_t a, size_t size, unsigned char val) static mps_res_t mvt_alloc(mps_addr_t *ref, mps_ap_t ap, size_t size) { mps_res_t res; - size = ((size+7)/8)*8; + size = (size + MPS_PF_ALIGN - 1) & ~ (MPS_PF_ALIGN - 1); do { MPS_RESERVE_BLOCK(res, *ref, ap, size); @@ -71,7 +71,7 @@ static int chkobj(mps_addr_t a, size_t size, unsigned char val) static void dt(int kind, size_t minSize, size_t avgSize, size_t maxSize, mps_word_t depth, mps_word_t fragLimit, - size_t mins, size_t maxs, int number, int iter) + unsigned long mins, unsigned long maxs, int number, int iter) { mps_pool_t pool; mps_ap_t ap; @@ -118,11 +118,11 @@ static void dt(int kind, if (queue[hd].addr != NULL) { asserts(chkobj(queue[hd].addr, queue[hd].size, (unsigned char) (hd%256)), - "corrupt at %x (%s: %x, %x, %x, %i, %i, %x, %x, %i, %i)", + "corrupt at %x (%s: %x, %x, %x, %i, %i, %lx, %lx, %i, %i)", queue[hd].addr, tdesc[kind], (int) minSize, (int) avgSize, (int) maxSize, (int) depth, (int) fragLimit, - (int) mins, (int) maxs, number, iter); + mins, maxs, number, iter); mps_free(pool, queue[hd].addr, queue[hd].size); } size = ranrange(mins, maxs); @@ -145,16 +145,16 @@ static void dt(int kind, time1=clock(); secs=(time1-time0)/(double)CLOCKS_PER_SEC; - comment("%s test (%x, %x, %x, %i, %i, %x, %x, %i, %i) in %.2f s", + comment("%s test (%x, %x, %x, %i, %i, %lx, %lx, %i, %i) in %.2f s", tdesc[kind], (int) minSize, (int) avgSize, (int) maxSize, (int) depth, (int) fragLimit, - (int) mins, (int) maxs, number, iter, secs); + mins, maxs, number, iter, secs); } static void test(void) { mps_thr_t thread; - size_t mins; + unsigned long mins; mps_word_t dep, frag; cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t) (1024*1024*100)), "create arena"); diff --git a/mps/test/function/206.c b/mps/test/function/206.c index 64d5517944d..f9a40cf7f1d 100644 --- a/mps/test/function/206.c +++ b/mps/test/function/206.c @@ -59,7 +59,7 @@ static int chkobj(mps_addr_t a, size_t size, unsigned char val) static void dt(int kind, size_t extendBy, size_t avgSize, size_t align, - size_t mins, size_t maxs, int number, int iter) + unsigned long mins, unsigned long maxs, int number, int iter) { mps_pool_t pool; int i, hd; @@ -103,11 +103,11 @@ static void dt(int kind, if (queue[hd].addr != NULL) { asserts(chkobj(queue[hd].addr, queue[hd].size, (unsigned char) (hd%256)), - "corrupt at %p (%s: %x, %x, %x, %c%c%c, %x, %x, %i, %i)", + "corrupt at %p (%s: %x, %x, %x, %c%c%c, %lx, %lx, %i, %i)", queue[hd].addr, tdesc[kind], (int) extendBy, (int) avgSize, (int) align, slotHigh ? 'S' : 's', arenaHigh ? 'A' : 'a', firstFit ? 'F' : 'f', - (int) mins, (int) maxs, number, iter); + mins, maxs, number, iter); mps_free(pool, queue[hd].addr, queue[hd].size); } size = ranrange(mins, maxs); @@ -129,18 +129,18 @@ static void dt(int kind, time1=clock(); secs=(time1-time0)/(double)CLOCKS_PER_SEC; - comment("%s test (%x, %x, %x, %c%c%c, %x, %x, %i, %i) in %.2f s", + comment("%s test (%x, %x, %x, %c%c%c, %lx, %lx, %i, %i) in %.2f s", tdesc[kind], (int) extendBy, (int) avgSize, (int) align, slotHigh ? 'S' : 's', arenaHigh ? 'A' : 'a', firstFit ? 'F' : 'f', - (int) mins, (int) maxs, number, iter, secs); + mins, maxs, number, iter, secs); } static void test(void) { mps_thr_t thread; - size_t extendBy, avgSize, maxSize; + size_t avgSize; size_t align = sizeof(void*); - size_t minSize = sizeof(int); + unsigned long extendBy, minSize = sizeof(int), maxSize; int i, j, kind; cdie(mps_arena_create(&arena, mps_arena_class_vm(), (size_t) (1024*1024*50)), "create arena"); diff --git a/mps/test/function/207.c b/mps/test/function/207.c index 6d73d87d4bd..c68ac5757af 100644 --- a/mps/test/function/207.c +++ b/mps/test/function/207.c @@ -58,7 +58,7 @@ static int chkobj(mps_addr_t a, size_t size, unsigned char val) static void dt(int kind, size_t extendBy, size_t avgSize, size_t align, - size_t mins, size_t maxs, int number, int iter) + unsigned long mins, unsigned long maxs, int number, int iter) { mps_pool_t pool; int i, hd; @@ -107,11 +107,11 @@ static void dt(int kind, if (queue[hd].addr != NULL) { asserts(chkobj(queue[hd].addr, queue[hd].size, (unsigned char) (hd%256)), - "corrupt at %x (%s: %x, %x, %x, %c%c%c, %x, %x, %i, %i)", + "corrupt at %x (%s: %x, %x, %x, %c%c%c, %lx, %lx, %i, %i)", queue[hd].addr, tdesc[kind], (int) extendBy, (int) avgSize, (int) align, slotHigh ? 'S' : 's', arenaHigh ? 'A' : 'a', firstFit ? 'F' : 'f', - (int) mins, (int) maxs, number, iter); + mins, maxs, number, iter); commentif(comments, "Free %i at %x, size %x", hd, queue[hd].addr, queue[hd].size); mps_free(pool, queue[hd].addr, queue[hd].size); @@ -140,16 +140,16 @@ static void dt(int kind, time1=clock(); secs=(time1-time0)/(double)CLOCKS_PER_SEC; - comment("%s test (%x, %x, %x, %c%c%c, %x, %x, %i, %i) in %.2f s", + comment("%s test (%x, %x, %x, %c%c%c, %lx, %lx, %i, %i) in %.2f s", tdesc[kind], (int) extendBy, (int) avgSize, (int) align, slotHigh ? 'S' : 's', arenaHigh ? 'A' : 'a', firstFit ? 'F' : 'f', - (int) mins, (int) maxs, number, iter, secs); + mins, maxs, number, iter, secs); } static void test(void) { mps_thr_t thread; - size_t mins; + unsigned long mins; int symm; size_t comlimit; diff --git a/mps/test/function/21.c b/mps/test/function/21.c index 7b493f6602f..7992000899a 100644 --- a/mps/test/function/21.c +++ b/mps/test/function/21.c @@ -24,8 +24,8 @@ static void test(void) { for (p=0; p<2000; p++) { die(mps_alloc(&q, pool, 1024*1024), "alloc"); - q = (mps_addr_t) ((char *) q + 8); - mps_free(pool, q, 256*1024-8); + q = (mps_addr_t) ((char *) q + MPS_PF_ALIGN); + mps_free(pool, q, 256*1024-MPS_PF_ALIGN); report("promise", "%i", p); } } diff --git a/mps/test/function/215.c b/mps/test/function/215.c index ab3862f9a5f..48e7148e029 100644 --- a/mps/test/function/215.c +++ b/mps/test/function/215.c @@ -138,7 +138,7 @@ static void test(void) { } } if(mps_message_get(&message, arena, mps_message_type_gc())) { - unsigned long live, condemned, notCondemned; + size_t live, condemned, notCondemned; live = mps_message_gc_live_size(arena, message); condemned = mps_message_gc_condemned_size(arena, message); notCondemned = diff --git a/mps/test/function/22.c b/mps/test/function/22.c index 8927643e49f..4959b7a88f1 100644 --- a/mps/test/function/22.c +++ b/mps/test/function/22.c @@ -27,8 +27,8 @@ static void test(void) { for (p=0; p<2000; p++) { report("promise", "%i", p); die(mps_alloc(&r, pool, 1024*1024), "alloc"); - mps_free(pool, q, 256*1024-8); - q = (mps_addr_t) ((char *) r + 8); + mps_free(pool, q, 256*1024-MPS_PF_ALIGN); + q = (mps_addr_t) ((char *) r + MPS_PF_ALIGN); } } diff --git a/mps/test/function/223.c b/mps/test/function/223.c index 6fb7a4357fa..75e14915728 100644 --- a/mps/test/function/223.c +++ b/mps/test/function/223.c @@ -138,7 +138,7 @@ static void test(void) { } } if(mps_message_get(&message, arena, mps_message_type_gc())) { - unsigned long live, condemned, notCondemned; + size_t live, condemned, notCondemned; live = mps_message_gc_live_size(arena, message); condemned = mps_message_gc_condemned_size(arena, message); notCondemned = mps_message_gc_not_condemned_size(arena, message); diff --git a/mps/test/function/226.c b/mps/test/function/226.c index ea6607498a2..2295ab34f1c 100644 --- a/mps/test/function/226.c +++ b/mps/test/function/226.c @@ -58,7 +58,7 @@ static void mergelds(int merge) { } } -static void blat(mps_ap_t apamc, int percent) { +static void blat(mps_ap_t apamc, unsigned percent) { int i; for (i=0; i < MAXLDS; i++) { if (ranint(100) < percent) { diff --git a/mps/test/function/232.c b/mps/test/function/232.c index 09c7359b6e2..ff16289fc1b 100644 --- a/mps/test/function/232.c +++ b/mps/test/function/232.c @@ -1,10 +1,10 @@ /* TEST_HEADER - id = $Id: //info.ravenbrook.com/project/mps/branch/2015-08-11/compact/test/function/229.c#1 $ + id = $Id$ summary = test arena extension and compaction language = c link = testlib.o - parameters = SIZE=1024*1024 ITERATIONS=100 + parameters = CHUNKSIZE=1024*1024 ITERATIONS=100 END_HEADER */ @@ -26,7 +26,7 @@ static void test(void) unsigned i; MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, SIZE); + MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, CHUNKSIZE); die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "arena_create"); } MPS_ARGS_END(args); @@ -37,12 +37,12 @@ static void test(void) check_chunks(arena, 1); for (i = 0; i < ITERATIONS; ++i) { - die(mps_alloc(&block[i], pool, SIZE), "mps_alloc"); + die(mps_alloc(&block[i], pool, CHUNKSIZE), "mps_alloc"); check_chunks(arena, i + 2); } for (i = ITERATIONS; i > 0; --i) { - mps_free(pool, block[i - 1], SIZE); + mps_free(pool, block[i - 1], CHUNKSIZE); mps_arena_collect(arena); /* ensure ArenaCompact is called */ check_chunks(arena, i); } diff --git a/mps/test/function/26.c b/mps/test/function/26.c index fc738f90733..1c0f840e18f 100644 --- a/mps/test/function/26.c +++ b/mps/test/function/26.c @@ -20,7 +20,8 @@ static mps_res_t trysize(size_t try) { mps_res_t res; die(mps_pool_create(&pool, arena, mps_class_mv(), - 1024*32, 1024*16, 1024*256), "pool"); + (size_t)(1024*32), (size_t)(1024*16), (size_t)(1024*256)), + "pool_create"); comment("Trying %x", try); diff --git a/mps/test/function/38.c b/mps/test/function/38.c index e3512864442..9effe17ddf2 100644 --- a/mps/test/function/38.c +++ b/mps/test/function/38.c @@ -91,7 +91,8 @@ static void test(void) cdie(mps_pool_create(&poolawl, arena, mps_class_awl(), format, getassociated), "create awl pool"); - cdie(mps_pool_create(&poolmv, arena, mps_class_mv(), 0x4000, 128, 0x4000), + cdie(mps_pool_create(&poolmv, arena, mps_class_mv(), + (size_t)0x4000, (size_t)128, (size_t)0x4000), "create mv pool"); cdie(mps_ap_create(&apawl, poolawl, mps_rank_exact()), diff --git a/mps/test/function/47.c b/mps/test/function/47.c index ee7c5605c2e..964de168c02 100644 --- a/mps/test/function/47.c +++ b/mps/test/function/47.c @@ -54,7 +54,8 @@ static void test(void) { cdie(mps_pool_create(&poolawl, arena, mps_class_awl(), format, getassociated), "create awl pool"); - cdie(mps_pool_create(&poolmv, arena, mps_class_mv(), 0x4000, 128, 0x4000), + cdie(mps_pool_create(&poolmv, arena, mps_class_mv(), + (size_t)0x4000, (size_t)128, (size_t)0x4000), "create mv pool"); cdie(mps_ap_create(&apawl, poolawl, mps_rank_exact()), diff --git a/mps/test/function/66.c b/mps/test/function/66.c index d395dbb3637..678fefe7e02 100644 --- a/mps/test/function/66.c +++ b/mps/test/function/66.c @@ -90,7 +90,8 @@ static void test(void) { "create awl pool"); cdie( - mps_pool_create(&poolmv, arena, mps_class_mv(), 0x4000, 128, 0x4000), + mps_pool_create(&poolmv, arena, mps_class_mv(), + (size_t)0x4000, (size_t)128, (size_t)0x4000), "create mv pool"); cdie( From abcea0b2a54a2e954c142bdbf2a9c966ea33f1ac Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Fri, 22 Apr 2016 17:04:50 +0100 Subject: [PATCH 09/52] The computed chunk size is the smallest size with a given number of usable bytes -- the actual chunk may be one grain larger. Copied from Perforce Change: 191574 ServerID: perforce.ravenbrook.com --- mps/code/arenavm.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/mps/code/arenavm.c b/mps/code/arenavm.c index e6b53931b49..9467e104bc2 100644 --- a/mps/code/arenavm.c +++ b/mps/code/arenavm.c @@ -502,6 +502,7 @@ static Res vmArenaChunkSize(Size *chunkSizeReturn, VMArena vmArena, Size size) overhead = 0; do { chunkSize = size + overhead; + AVER(SizeIsAligned(chunkSize, grainSize)); /* See .overhead.chunk-struct. */ overhead = SizeAlignUp(sizeof(VMChunkStruct), MPS_PF_ALIGN); @@ -632,15 +633,18 @@ static Res VMArenaCreate(Arena *arenaReturn, ArgList args) goto failChunkCreate; #if defined(AVER_AND_CHECK_ALL) - /* Check that the computation of the chunk size in vmArenaChunkSize - * was correct, now that we have the actual chunk for comparison. */ + /* Check the computation of the chunk size in vmArenaChunkSize, now + * that we have the actual chunk for comparison. Note that + * vmArenaChunkSize computes the smallest size with a given number + * of usable bytes -- the actual chunk may be one grain larger. */ { Size usableSize, computedChunkSize; usableSize = AddrOffset(PageIndexBase(chunk, chunk->allocBase), chunk->limit); res = vmArenaChunkSize(&computedChunkSize, vmArena, usableSize); AVER(res == ResOK); - AVER(computedChunkSize == ChunkSize(chunk)); + AVER(computedChunkSize == ChunkSize(chunk) + || computedChunkSize + grainSize == ChunkSize(chunk)); } #endif From b7e31828dba91d450b2848b0471e53ea19ffc994 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Fri, 22 Apr 2016 17:17:53 +0100 Subject: [PATCH 10/52] Memoryerror is only implemented on windows, so test for abort instead. Copied from Perforce Change: 191575 ServerID: perforce.ravenbrook.com --- mps/test/misc/1.c | 2 +- mps/test/misc/2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mps/test/misc/1.c b/mps/test/misc/1.c index cf955c68cec..a8477ca1f62 100644 --- a/mps/test/misc/1.c +++ b/mps/test/misc/1.c @@ -5,7 +5,7 @@ TEST_HEADER language = c link = testlib.o OUTPUT_SPEC - memoryerror = true + abort = true END_HEADER */ diff --git a/mps/test/misc/2.c b/mps/test/misc/2.c index a6ff666788b..7686fa9fb24 100644 --- a/mps/test/misc/2.c +++ b/mps/test/misc/2.c @@ -6,7 +6,7 @@ TEST_HEADER link = testlib.o parameters = NUM=1 OUTPUT_SPEC - memoryerror = true + abort = true END_HEADER */ From b76512800347bc5760ea1fd3fece21a4d312f60f Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sat, 23 Apr 2016 00:22:46 +0100 Subject: [PATCH 11/52] Turning pool describe methods the right way in, so that they call next-method. Copied from Perforce Change: 191587 ServerID: perforce.ravenbrook.com --- mps/code/mpm.h | 2 +- mps/code/pool.c | 46 +----------------------------------------- mps/code/poolabs.c | 44 +++++++++++++++++++++++++++++++++------- mps/code/poolamc.c | 19 ++++++------------ mps/code/poolams.c | 27 ++++++++++--------------- mps/code/poolmfs.c | 22 ++++++++++---------- mps/code/poolmrg.c | 20 +++++++++++------- mps/code/poolmv.c | 28 ++++++++++++++------------ mps/code/poolmv2.c | 49 ++++++++++++++++++++++----------------------- mps/code/poolmvff.c | 33 ++++++++++++++---------------- 10 files changed, 134 insertions(+), 156 deletions(-) diff --git a/mps/code/mpm.h b/mps/code/mpm.h index 1dc05e95177..9bc8b4b59cb 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -251,7 +251,7 @@ extern void PoolNoBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit); extern void PoolTrivBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit); -extern Res PoolTrivDescribe(Pool pool, mps_lib_FILE *stream, Count depth); +extern Res PoolAbsDescribe(Pool pool, mps_lib_FILE *stream, Count depth); extern Res PoolNoTraceBegin(Pool pool, Trace trace); extern Res PoolTrivTraceBegin(Pool pool, Trace trace); extern Res PoolNoAccess(Pool pool, Seg seg, Addr addr, diff --git a/mps/code/pool.c b/mps/code/pool.c index 43cb1fbe342..bb1a6f34f74 100644 --- a/mps/code/pool.c +++ b/mps/code/pool.c @@ -490,51 +490,7 @@ Size PoolFreeSize(Pool pool) Res PoolDescribe(Pool pool, mps_lib_FILE *stream, Count depth) { - Res res; - Ring node, nextNode; - PoolClass klass; - - if (!TESTC(AbstractPool, pool)) - return ResPARAM; - if (stream == NULL) - return ResPARAM; - - klass = ClassOfPoly(Pool, pool); - - res = WriteF(stream, depth, - "Pool $P ($U) {\n", (WriteFP)pool, (WriteFU)pool->serial, - " class $P (\"$S\")\n", - (WriteFP)klass, (WriteFS)ClassName(klass), - " arena $P ($U)\n", - (WriteFP)pool->arena, (WriteFU)pool->arena->serial, - " alignment $W\n", (WriteFW)pool->alignment, - NULL); - if (res != ResOK) - return res; - if (NULL != pool->format) { - res = FormatDescribe(pool->format, stream, depth + 2); - if (res != ResOK) - return res; - } - - res = Method(Pool, pool, describe)(pool, stream, depth + 2); - if (res != ResOK) - return res; - - RING_FOR(node, &pool->bufferRing, nextNode) { - Buffer buffer = RING_ELT(Buffer, poolRing, node); - res = BufferDescribe(buffer, stream, depth + 2); - if (res != ResOK) - return res; - } - - res = WriteF(stream, depth, - "} Pool $P ($U)\n", (WriteFP)pool, (WriteFU)pool->serial, - NULL); - if (res != ResOK) - return res; - - return ResOK; + return Method(Pool, pool, describe)(pool, stream, depth); } diff --git a/mps/code/poolabs.c b/mps/code/poolabs.c index 8f1f1831d62..e7fc6d3c01b 100644 --- a/mps/code/poolabs.c +++ b/mps/code/poolabs.c @@ -211,7 +211,7 @@ DEFINE_CLASS(Pool, AbstractPool, klass) klass->walk = PoolNoWalk; klass->freewalk = PoolTrivFreeWalk; klass->bufferClass = PoolNoBufferClass; - klass->describe = PoolTrivDescribe; + klass->describe = PoolAbsDescribe; klass->debugMixin = PoolNoDebugMixin; klass->totalSize = PoolNoSize; klass->freeSize = PoolNoSize; @@ -353,13 +353,43 @@ void PoolTrivBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit) } -Res PoolTrivDescribe(Pool pool, mps_lib_FILE *stream, Count depth) +Res PoolAbsDescribe(Pool pool, mps_lib_FILE *stream, Count depth) { - AVERT(Pool, pool); - AVER(stream != NULL); - return WriteF(stream, depth, - "No class-specific description available.\n", - NULL); + Res res; + Ring node, nextNode; + + if (!TESTC(AbstractPool, pool)) + return ResPARAM; + if (stream == NULL) + return ResPARAM; + + res = InstDescribe(CouldBeA(Inst, pool), stream, depth); + if (res != ResOK) + return res; + + res = WriteF(stream, depth + 2, + "serial $U\n", (WriteFU)pool->serial, + "arena $P ($U)\n", + (WriteFP)pool->arena, (WriteFU)pool->arena->serial, + "alignment $W\n", (WriteFW)pool->alignment, + NULL); + if (res != ResOK) + return res; + + if (pool->format != NULL) { + res = FormatDescribe(pool->format, stream, depth + 2); + if (res != ResOK) + return res; + } + + RING_FOR(node, &pool->bufferRing, nextNode) { + Buffer buffer = RING_ELT(Buffer, poolRing, node); + res = BufferDescribe(buffer, stream, depth + 2); + if (res != ResOK) + return res; + } + + return ResOK; } diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c index bf83d5458e8..192c688881a 100644 --- a/mps/code/poolamc.c +++ b/mps/code/poolamc.c @@ -1969,6 +1969,7 @@ static Size AMCFreeSize(Pool pool) * * See . */ + static Res AMCDescribe(Pool pool, mps_lib_FILE *stream, Count depth) { Res res; @@ -1976,17 +1977,13 @@ static Res AMCDescribe(Pool pool, mps_lib_FILE *stream, Count depth) Ring node, nextNode; const char *rampmode; - if(!TESTC(AMCZPool, amc)) + if (!TESTC(AMCZPool, amc)) return ResPARAM; - if(stream == NULL) + if (stream == NULL) return ResPARAM; - res = WriteF(stream, depth, - (amc->rankSet == RankSetEMPTY) ? "AMCZ" : "AMC", - " $P {\n", (WriteFP)amc, " pool $P ($U)\n", - (WriteFP)pool, (WriteFU)pool->serial, - NULL); - if(res != ResOK) + res = NextMethod(Pool, AMCZPool, describe)(pool, stream, depth); + if (res != ResOK) return res; switch(amc->rampMode) { @@ -2013,7 +2010,7 @@ static Res AMCDescribe(Pool pool, mps_lib_FILE *stream, Count depth) return res; } - if(0) { + if (0) { /* SegDescribes */ RING_FOR(node, &pool->segRing, nextNode) { Seg seg = RING_ELT(Seg, poolRing, node); @@ -2023,10 +2020,6 @@ static Res AMCDescribe(Pool pool, mps_lib_FILE *stream, Count depth) } } - res = WriteF(stream, depth, "} AMC $P\n", (WriteFP)amc, NULL); - if(res != ResOK) - return res; - return ResOK; } diff --git a/mps/code/poolams.c b/mps/code/poolams.c index 2cb2a79bfe1..aa0e8bd4567 100644 --- a/mps/code/poolams.c +++ b/mps/code/poolams.c @@ -1699,25 +1699,24 @@ static Size AMSFreeSize(Pool pool) * * Iterates over the segments, describing all of them. */ + static Res AMSDescribe(Pool pool, mps_lib_FILE *stream, Count depth) { - AMS ams; + AMS ams = CouldBeA(AMSPool, pool); Ring node, nextNode; Res res; - if (!TESTT(Pool, pool)) - return ResFAIL; - ams = PoolAMS(pool); - if (!TESTT(AMS, ams)) - return ResFAIL; + if (!TESTC(AMSPool, ams)) + return ResPARAM; if (stream == NULL) - return ResFAIL; + return ResPARAM; - res = WriteF(stream, depth, - "AMS $P {\n", (WriteFP)ams, - " pool $P ($U)\n", - (WriteFP)pool, (WriteFU)pool->serial, - " grain shift $U\n", (WriteFU)ams->grainShift, + res = NextMethod(Pool, AMSPool, describe)(pool, stream, depth); + if (res != ResOK) + return res; + + res = WriteF(stream, depth + 2, + "grain shift $U\n", (WriteFU)ams->grainShift, NULL); if (res != ResOK) return res; @@ -1736,10 +1735,6 @@ static Res AMSDescribe(Pool pool, mps_lib_FILE *stream, Count depth) return res; } - res = WriteF(stream, depth, "} AMS $P\n",(WriteFP)ams, NULL); - if (res != ResOK) - return res; - return ResOK; } diff --git a/mps/code/poolmfs.c b/mps/code/poolmfs.c index 62b5d45e0b6..92627aaf4f8 100644 --- a/mps/code/poolmfs.c +++ b/mps/code/poolmfs.c @@ -316,20 +316,20 @@ static Res MFSDescribe(Pool pool, mps_lib_FILE *stream, Count depth) if (stream == NULL) return ResPARAM; - res = WriteF(stream, depth, - "unroundedUnitSize $W\n", (WriteFW)mfs->unroundedUnitSize, - "extendBy $W\n", (WriteFW)mfs->extendBy, - "extendSelf $S\n", WriteFYesNo(mfs->extendSelf), - "unitSize $W\n", (WriteFW)mfs->unitSize, - "freeList $P\n", (WriteFP)mfs->freeList, - "total $W\n", (WriteFW)mfs->total, - "free $W\n", (WriteFW)mfs->free, - "tractList $P\n", (WriteFP)mfs->tractList, - NULL); + res = NextMethod(Pool, MFSPool, describe)(pool, stream, depth); if (res != ResOK) return res; - return ResOK; + return WriteF(stream, depth + 2, + "unroundedUnitSize $W\n", (WriteFW)mfs->unroundedUnitSize, + "extendBy $W\n", (WriteFW)mfs->extendBy, + "extendSelf $S\n", WriteFYesNo(mfs->extendSelf), + "unitSize $W\n", (WriteFW)mfs->unitSize, + "freeList $P\n", (WriteFP)mfs->freeList, + "total $W\n", (WriteFW)mfs->total, + "free $W\n", (WriteFW)mfs->free, + "tractList $P\n", (WriteFP)mfs->tractList, + NULL); } diff --git a/mps/code/poolmrg.c b/mps/code/poolmrg.c index d2b66a1c20f..5eaa017bf97 100644 --- a/mps/code/poolmrg.c +++ b/mps/code/poolmrg.c @@ -770,6 +770,7 @@ Res MRGDeregister(Pool pool, Ref obj) * This could be improved by implementing MRGSegDescribe * and having MRGDescribe iterate over all the pool's segments. */ + static Res MRGDescribe(Pool pool, mps_lib_FILE *stream, Count depth) { MRG mrg = CouldBeA(MRGPool, pool); @@ -783,20 +784,25 @@ static Res MRGDescribe(Pool pool, mps_lib_FILE *stream, Count depth) if (stream == NULL) return ResPARAM; + res = NextMethod(Pool, MRGPool, describe)(pool, stream, depth); + if (res != ResOK) + return res; + + res = WriteF(stream, depth + 2, "extendBy $W\n", (WriteFW)mrg->extendBy, NULL); + if (res != ResOK) + return res; + + res = WriteF(stream, depth + 2, "Entry queue:\n", NULL); + if (res != ResOK) + return res; arena = PoolArena(pool); - res = WriteF(stream, depth, "extendBy $W\n", (WriteFW)mrg->extendBy, NULL); - if (res != ResOK) - return res; - res = WriteF(stream, depth, "Entry queue:\n", NULL); - if (res != ResOK) - return res; RING_FOR(node, &mrg->entryRing, nextNode) { Bool outsideShield = !ArenaShield(arena)->inside; refPart = MRGRefPartOfLink(linkOfRing(node), arena); if (outsideShield) { ShieldEnter(arena); } - res = WriteF(stream, depth, "at $A Ref $A\n", + res = WriteF(stream, depth + 2, "at $A Ref $A\n", (WriteFA)refPart, (WriteFA)MRGRefPartRef(arena, refPart), NULL); if (outsideShield) { diff --git a/mps/code/poolmv.c b/mps/code/poolmv.c index e1d4a19fe27..821c8eea21f 100644 --- a/mps/code/poolmv.c +++ b/mps/code/poolmv.c @@ -754,23 +754,24 @@ static Size MVFreeSize(Pool pool) static Res MVDescribe(Pool pool, mps_lib_FILE *stream, Count depth) { + MV mv = CouldBeA(MVPool, pool); Res res; - MV mv; MVSpan span; Align step; Size length; char c; Ring spans, node = NULL, nextNode; /* gcc whinge stop */ - if (!TESTT(Pool, pool)) - return ResFAIL; - mv = PoolMV(pool); - if (!TESTT(MV, mv)) - return ResFAIL; + if (!TESTC(MVPool, mv)) + return ResPARAM; if (stream == NULL) - return ResFAIL; + return ResPARAM; - res = WriteF(stream, depth, + res = NextMethod(Pool, MVPool, describe)(pool, stream, depth); + if (res != ResOK) + return res; + + res = WriteF(stream, depth + 2, "blockPool $P ($U)\n", (WriteFP)mvBlockPool(mv), (WriteFU)mvBlockPool(mv)->serial, "spanPool $P ($U)\n", @@ -781,7 +782,8 @@ static Res MVDescribe(Pool pool, mps_lib_FILE *stream, Count depth) "free $W\n", (WriteFP)mv->free, "lost $W\n", (WriteFP)mv->lost, NULL); - if(res != ResOK) return res; + if(res != ResOK) + return res; step = pool->alignment; length = 0x40 * step; @@ -791,11 +793,11 @@ static Res MVDescribe(Pool pool, mps_lib_FILE *stream, Count depth) Addr i, j; MVBlock block; span = RING_ELT(MVSpan, spans, node); - res = WriteF(stream, depth, "MVSpan $P {\n", (WriteFP)span, NULL); + res = WriteF(stream, depth + 2, "MVSpan $P {\n", (WriteFP)span, NULL); if (res != ResOK) return res; - res = WriteF(stream, depth + 2, + res = WriteF(stream, depth + 4, "span $P\n", (WriteFP)span, "tract $P\n", (WriteFP)span->tract, "free $W\n", (WriteFW)span->free, @@ -815,7 +817,7 @@ static Res MVDescribe(Pool pool, mps_lib_FILE *stream, Count depth) block = span->blocks; for(i = span->base.base; i < span->limit.limit; i = AddrAdd(i, length)) { - res = WriteF(stream, depth + 2, "$A ", (WriteFA)i, NULL); + res = WriteF(stream, depth + 4, "$A ", (WriteFA)i, NULL); if (res != ResOK) return res; @@ -847,7 +849,7 @@ static Res MVDescribe(Pool pool, mps_lib_FILE *stream, Count depth) if (res != ResOK) return res; } - res = WriteF(stream, depth, "} MVSpan $P\n", (WriteFP)span, NULL); + res = WriteF(stream, depth + 2, "} MVSpan $P\n", (WriteFP)span, NULL); if (res != ResOK) return res; } diff --git a/mps/code/poolmv2.c b/mps/code/poolmv2.c index b11f6b65762..f563922588a 100644 --- a/mps/code/poolmv2.c +++ b/mps/code/poolmv2.c @@ -1025,34 +1025,34 @@ static Size MVTFreeSize(Pool pool) static Res MVTDescribe(Pool pool, mps_lib_FILE *stream, Count depth) { + MVT mvt = CouldBeA(MVTPool, pool); Res res; - MVT mvt; - if (!TESTT(Pool, pool)) - return ResFAIL; - mvt = PoolMVT(pool); - if (!TESTT(MVT, mvt)) - return ResFAIL; + if (!TESTC(MVTPool, mvt)) + return ResPARAM; if (stream == NULL) return ResFAIL; - res = WriteF(stream, depth, - "MVT $P {\n", (WriteFP)mvt, - " minSize: $U\n", (WriteFU)mvt->minSize, - " meanSize: $U\n", (WriteFU)mvt->meanSize, - " maxSize: $U\n", (WriteFU)mvt->maxSize, - " fragLimit: $U\n", (WriteFU)mvt->fragLimit, - " reuseSize: $U\n", (WriteFU)mvt->reuseSize, - " fillSize: $U\n", (WriteFU)mvt->fillSize, - " availLimit: $U\n", (WriteFU)mvt->availLimit, - " abqOverflow: $S\n", WriteFYesNo(mvt->abqOverflow), - " splinter: $S\n", WriteFYesNo(mvt->splinter), - " splinterBase: $A\n", (WriteFA)mvt->splinterBase, - " splinterLimit: $A\n", (WriteFU)mvt->splinterLimit, - " size: $U\n", (WriteFU)mvt->size, - " allocated: $U\n", (WriteFU)mvt->allocated, - " available: $U\n", (WriteFU)mvt->available, - " unavailable: $U\n", (WriteFU)mvt->unavailable, + res = NextMethod(Pool, MVTPool, describe)(pool, stream, depth); + if (res != ResOK) + return res; + + res = WriteF(stream, depth + 2, + "minSize: $U\n", (WriteFU)mvt->minSize, + "meanSize: $U\n", (WriteFU)mvt->meanSize, + "maxSize: $U\n", (WriteFU)mvt->maxSize, + "fragLimit: $U\n", (WriteFU)mvt->fragLimit, + "reuseSize: $U\n", (WriteFU)mvt->reuseSize, + "fillSize: $U\n", (WriteFU)mvt->fillSize, + "availLimit: $U\n", (WriteFU)mvt->availLimit, + "abqOverflow: $S\n", WriteFYesNo(mvt->abqOverflow), + "splinter: $S\n", WriteFYesNo(mvt->splinter), + "splinterBase: $A\n", (WriteFA)mvt->splinterBase, + "splinterLimit: $A\n", (WriteFU)mvt->splinterLimit, + "size: $U\n", (WriteFU)mvt->size, + "allocated: $U\n", (WriteFU)mvt->allocated, + "available: $U\n", (WriteFU)mvt->available, + "unavailable: $U\n", (WriteFU)mvt->unavailable, NULL); if (res != ResOK) return res; @@ -1103,8 +1103,7 @@ static Res MVTDescribe(Pool pool, mps_lib_FILE *stream, Count depth) METER_WRITE(mvt->exceptionSplinters, stream, depth + 2); METER_WRITE(mvt->exceptionReturns, stream, depth + 2); - res = WriteF(stream, depth, "} MVT $P\n", (WriteFP)mvt, NULL); - return res; + return ResOK; } diff --git a/mps/code/poolmvff.c b/mps/code/poolmvff.c index 5269f233a3e..dda5779eddc 100644 --- a/mps/code/poolmvff.c +++ b/mps/code/poolmvff.c @@ -673,26 +673,24 @@ static Size MVFFFreeSize(Pool pool) static Res MVFFDescribe(Pool pool, mps_lib_FILE *stream, Count depth) { + MVFF mvff = CouldBeA(MVFFPool, pool); Res res; - MVFF mvff; - if (!TESTT(Pool, pool)) - return ResFAIL; - mvff = PoolMVFF(pool); - if (!TESTT(MVFF, mvff)) - return ResFAIL; + if (!TESTC(MVFFPool, mvff)) + return ResPARAM; if (stream == NULL) - return ResFAIL; + return ResPARAM; - res = WriteF(stream, depth, - "MVFF $P {\n", (WriteFP)mvff, - " pool $P ($U)\n", - (WriteFP)pool, (WriteFU)pool->serial, - " extendBy $W\n", (WriteFW)mvff->extendBy, - " avgSize $W\n", (WriteFW)mvff->avgSize, - " firstFit $U\n", (WriteFU)mvff->firstFit, - " slotHigh $U\n", (WriteFU)mvff->slotHigh, - " spare $D\n", (WriteFD)mvff->spare, + res = NextMethod(Pool, MVFFPool, describe)(pool, stream, depth); + if (res != ResOK) + return res; + + res = WriteF(stream, depth + 2, + "extendBy $W\n", (WriteFW)mvff->extendBy, + "avgSize $W\n", (WriteFW)mvff->avgSize, + "firstFit $U\n", (WriteFU)mvff->firstFit, + "slotHigh $U\n", (WriteFU)mvff->slotHigh, + "spare $D\n", (WriteFD)mvff->spare, NULL); if (res != ResOK) return res; @@ -716,8 +714,7 @@ static Res MVFFDescribe(Pool pool, mps_lib_FILE *stream, Count depth) if (res != ResOK) return res; - res = WriteF(stream, depth, "} MVFF $P\n", (WriteFP)mvff, NULL); - return res; + return ResOK; } From 0ea36ccf02e328cefab69f44d880f989cf2e3dbd Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sat, 23 Apr 2016 00:48:48 +0100 Subject: [PATCH 12/52] Turning segment describe methods the right way in, so that they call next-method. deleting duplicate implementation of basic segment describe! Copied from Perforce Change: 191588 ServerID: perforce.ravenbrook.com --- mps/code/mpm.h | 1 + mps/code/poolamc.c | 43 +++++++------------ mps/code/poolams.c | 25 +++++------ mps/code/seg.c | 102 ++++++++++++++------------------------------- 4 files changed, 59 insertions(+), 112 deletions(-) diff --git a/mps/code/mpm.h b/mps/code/mpm.h index 9bc8b4b59cb..556886c7104 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -669,6 +669,7 @@ extern void SegSetRankSet(Seg seg, RankSet rankSet); extern void SegSetRankAndSummary(Seg seg, RankSet rankSet, RefSet summary); extern Res SegMerge(Seg *mergedSegReturn, Seg segLo, Seg segHi); 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); diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c index 192c688881a..b7fe2fbaf27 100644 --- a/mps/code/poolamc.c +++ b/mps/code/poolamc.c @@ -236,22 +236,22 @@ static void AMCSegSketch(Seg seg, char *pbSketch, size_t cbSketch) */ static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) { - Res res; amcSeg amcseg = CouldBeA(amcSeg, seg); + Res res; Pool pool; Addr i, p, base, limit, init; Align step; Size row; char abzSketch[5]; - if(!TESTC(amcSeg, amcseg)) + if (!TESTC(amcSeg, amcseg)) return ResPARAM; - if(stream == NULL) + if (stream == NULL) return ResPARAM; /* Describe the superclass fields first via next-method call */ res = NextMethod(Seg, amcSeg, describe)(seg, stream, depth); - if(res != ResOK) + if (res != ResOK) return res; pool = SegPool(seg); @@ -262,16 +262,9 @@ static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) p = AddrAdd(base, pool->format->headerSize); limit = SegLimit(seg); - res = WriteF(stream, depth, - "AMC seg $P [$A,$A){\n", - (WriteFP)seg, (WriteFA)base, (WriteFA)limit, - NULL); - if(res != ResOK) - return res; - - if(amcSegHasNailboard(seg)) { + if (amcSegHasNailboard(seg)) { res = WriteF(stream, depth + 2, "Boarded\n", NULL); - } else if(SegNailed(seg) == TraceSetEMPTY) { + } else if (SegNailed(seg) == TraceSetEMPTY) { res = WriteF(stream, depth + 2, "Mobile\n", NULL); } else { res = WriteF(stream, depth + 2, "Stuck\n", NULL); @@ -281,32 +274,32 @@ static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) res = WriteF(stream, depth + 2, "Map: *===:object @+++:nails bbbb:buffer\n", NULL); - if(res != ResOK) + if (res != ResOK) return res; - if(SegBuffer(seg) != NULL) + if (SegBuffer(seg) != NULL) init = BufferGetInit(SegBuffer(seg)); else init = limit; - for(i = base; i < limit; i = AddrAdd(i, row)) { + for (i = base; i < limit; i = AddrAdd(i, row)) { Addr j; char c; res = WriteF(stream, depth + 2, "$A ", (WriteFA)i, NULL); - if(res != ResOK) + if (res != ResOK) return res; /* @@@@ This misses a header-sized pad at the end. */ - for(j = i; j < AddrAdd(i, row); j = AddrAdd(j, step)) { - if(j >= limit) + for (j = i; j < AddrAdd(i, row); j = AddrAdd(j, step)) { + if (j >= limit) c = ' '; /* if seg is not a whole number of print rows */ - else if(j >= init) + else if (j >= init) c = 'b'; else { Bool nailed = amcSegHasNailboard(seg) && NailboardGet(amcSegNailboard(seg), j); - if(j == p) { + if (j == p) { c = (nailed ? '@' : '*'); p = (pool->format->skip)(p); } else { @@ -314,12 +307,12 @@ static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) } } res = WriteF(stream, 0, "$C", (WriteFC)c, NULL); - if(res != ResOK) + if (res != ResOK) return res; } res = WriteF(stream, 0, "\n", NULL); - if(res != ResOK) + if (res != ResOK) return res; } @@ -328,10 +321,6 @@ static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) if(res != ResOK) return res; - res = WriteF(stream, depth, "} AMC Seg $P\n", (WriteFP)seg, NULL); - if(res != ResOK) - return res; - return ResOK; } diff --git a/mps/code/poolams.c b/mps/code/poolams.c index aa0e8bd4567..8218fa53f81 100644 --- a/mps/code/poolams.c +++ b/mps/code/poolams.c @@ -525,18 +525,15 @@ failCreateTablesLo: static Res AMSSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) { + AMSSeg amsseg = CouldBeA(AMSSeg, seg); Res res; - AMSSeg amsseg; Buffer buffer; /* the segment's buffer, if it has one */ Index i; - if (!TESTT(Seg, seg)) - return ResFAIL; + if (!TESTC(AMSSeg, amsseg)) + return ResPARAM; if (stream == NULL) - return ResFAIL; - amsseg = Seg2AMSSeg(seg); - if (!TESTT(AMSSeg, amsseg)) - return ResFAIL; + return ResPARAM; /* Describe the superclass fields first via next-method call */ res = NextMethod(Seg, AMSSeg, describe)(seg, stream, depth); @@ -545,13 +542,13 @@ static Res AMSSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) buffer = SegBuffer(seg); - res = WriteF(stream, depth, - " AMS $P\n", (WriteFP)amsseg->ams, - " grains $W\n", (WriteFW)amsseg->grains, - " freeGrains $W\n", (WriteFW)amsseg->freeGrains, - " buffferedGrains $W\n", (WriteFW)amsseg->bufferedGrains, - " newGrains $W\n", (WriteFW)amsseg->newGrains, - " oldGrains $W\n", (WriteFW)amsseg->oldGrains, + res = WriteF(stream, depth + 2, + "AMS $P\n", (WriteFP)amsseg->ams, + "grains $W\n", (WriteFW)amsseg->grains, + "freeGrains $W\n", (WriteFW)amsseg->freeGrains, + "buffferedGrains $W\n", (WriteFW)amsseg->bufferedGrains, + "newGrains $W\n", (WriteFW)amsseg->newGrains, + "oldGrains $W\n", (WriteFW)amsseg->oldGrains, NULL); if (res != ResOK) return res; diff --git a/mps/code/seg.c b/mps/code/seg.c index 9143245832f..88b34fe6e55 100644 --- a/mps/code/seg.c +++ b/mps/code/seg.c @@ -375,61 +375,57 @@ Addr SegBufferScanLimit(Seg seg) /* SegDescribe -- describe a segment */ -Res SegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) +Res SegAbsDescribe(Seg seg, mps_lib_FILE *stream, Count depth) { Res res; Pool pool; - SegClass klass; if (!TESTC(Seg, seg)) return ResPARAM; if (stream == NULL) return ResPARAM; - pool = SegPool(seg); - klass = ClassOfPoly(Seg, seg); + res = InstDescribe(CouldBeA(Inst, seg), stream, depth); + if (res != ResOK) + return res; - res = WriteF(stream, depth, - "Segment $P [$A,$A) {\n", (WriteFP)seg, - (WriteFA)SegBase(seg), (WriteFA)SegLimit(seg), - " class $P (\"$S\")\n", - (WriteFP)klass, (WriteFS)ClassName(klass), - " pool $P ($U)\n", - (WriteFP)pool, (WriteFU)pool->serial, - " depth $U\n", seg->depth, - " pm", + pool = SegPool(seg); + + res = WriteF(stream, depth + 2, + "base $A\n", (WriteFA)SegBase(seg), + "limit $A\n", (WriteFA)SegLimit(seg), + "pool $P ($U)\n", (WriteFP)pool, (WriteFU)pool->serial, + "depth $U\n", seg->depth, + "pm", seg->pm == AccessSetEMPTY ? " EMPTY" : "", seg->pm & AccessREAD ? " READ" : "", seg->pm & AccessWRITE ? " WRITE" : "", "\n", - " sm", + "sm", seg->sm == AccessSetEMPTY ? " EMPTY" : "", seg->sm & AccessREAD ? " READ" : "", seg->sm & AccessWRITE ? " WRITE" : "", "\n", - " grey $B\n", (WriteFB)seg->grey, - " white $B\n", (WriteFB)seg->white, - " nailed $B\n", (WriteFB)seg->nailed, - " rankSet", + "grey $B\n", (WriteFB)seg->grey, + "white $B\n", (WriteFB)seg->white, + "nailed $B\n", (WriteFB)seg->nailed, + "rankSet", seg->rankSet == RankSetEMPTY ? " EMPTY" : "", BS_IS_MEMBER(seg->rankSet, RankAMBIG) ? " AMBIG" : "", BS_IS_MEMBER(seg->rankSet, RankEXACT) ? " EXACT" : "", BS_IS_MEMBER(seg->rankSet, RankFINAL) ? " FINAL" : "", BS_IS_MEMBER(seg->rankSet, RankWEAK) ? " WEAK" : "", + "\n", NULL); if (res != ResOK) return res; - res = Method(Seg, seg, describe)(seg, stream, depth + 2); - if (res != ResOK) - return res; + return ResOK; +} - res = WriteF(stream, 0, "\n", NULL); - if (res != ResOK) - return res; - - res = WriteF(stream, depth, "} Segment $P\n", (WriteFP)seg, NULL); - return res; +Res SegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) +{ + return Method(Seg, seg, describe)(seg, stream, depth); } @@ -1011,39 +1007,6 @@ static Res segTrivSplit(Seg seg, Seg segHi, } -/* segTrivDescribe -- Basic Seg description method */ - -static Res segTrivDescribe(Seg seg, mps_lib_FILE *stream, Count depth) -{ - Res res; - - if (!TESTT(Seg, seg)) - return ResFAIL; - if (stream == NULL) - return ResFAIL; - - res = WriteF(stream, depth, - "shield depth $U\n", (WriteFU)seg->depth, - "protection mode: ", - (SegPM(seg) & AccessREAD) ? "" : "!", "READ", " ", - (SegPM(seg) & AccessWRITE) ? "" : "!", "WRITE", "\n", - "shield mode: ", - (SegSM(seg) & AccessREAD) ? "" : "!", "READ", " ", - (SegSM(seg) & AccessWRITE) ? "" : "!", "WRITE", "\n", - "ranks:", - RankSetIsMember(seg->rankSet, RankAMBIG) ? " ambiguous" : "", - RankSetIsMember(seg->rankSet, RankEXACT) ? " exact" : "", - RankSetIsMember(seg->rankSet, RankFINAL) ? " final" : "", - RankSetIsMember(seg->rankSet, RankWEAK) ? " weak" : "", - "\n", - "white $B\n", (WriteFB)seg->white, - "grey $B\n", (WriteFB)seg->grey, - "nailed $B\n", (WriteFB)seg->nailed, - NULL); - return res; -} - - /* Class GCSeg -- Segment class with GC support */ @@ -1553,32 +1516,29 @@ failSuper: static Res gcSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) { + GCSeg gcseg = CouldBeA(GCSeg, seg); Res res; - GCSeg gcseg; - if (!TESTT(Seg, seg)) - return ResFAIL; + if (!TESTC(GCSeg, gcseg)) + return ResPARAM; if (stream == NULL) - return ResFAIL; - gcseg = SegGCSeg(seg); - if (!TESTT(GCSeg, gcseg)) - return ResFAIL; + return ResPARAM; /* Describe the superclass fields first via next-method call */ res = NextMethod(Seg, GCSeg, describe)(seg, stream, depth); if (res != ResOK) return res; - res = WriteF(stream, depth, + res = WriteF(stream, depth + 2, "summary $W\n", (WriteFW)gcseg->summary, NULL); if (res != ResOK) return res; if (gcseg->buffer == NULL) { - res = WriteF(stream, depth, "buffer: NULL\n", NULL); + res = WriteF(stream, depth + 2, "buffer: NULL\n", NULL); } else { - res = BufferDescribe(gcseg->buffer, stream, depth); + res = BufferDescribe(gcseg->buffer, stream, depth + 2); } if (res != ResOK) return res; @@ -1629,7 +1589,7 @@ DEFINE_CLASS(Seg, Seg, klass) klass->setRankSummary = segNoSetRankSummary; klass->merge = segTrivMerge; klass->split = segTrivSplit; - klass->describe = segTrivDescribe; + klass->describe = SegAbsDescribe; klass->sig = SegClassSig; AVERT(SegClass, klass); } From 6ede631ed182a22fe809cdb0c8e07419119da577 Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sat, 23 Apr 2016 00:57:46 +0100 Subject: [PATCH 13/52] Turning buffer describe methods the right way in, so that they use next-method. Copied from Perforce Change: 191589 ServerID: perforce.ravenbrook.com --- mps/code/buffer.c | 80 +++++++++++++++++------------------------------ 1 file changed, 29 insertions(+), 51 deletions(-) diff --git a/mps/code/buffer.c b/mps/code/buffer.c index f16897a3c2c..a35b7b55a12 100644 --- a/mps/code/buffer.c +++ b/mps/code/buffer.c @@ -119,54 +119,46 @@ Bool BufferCheck(Buffer buffer) * * See for structure definitions. */ -Res BufferDescribe(Buffer buffer, mps_lib_FILE *stream, Count depth) +static Res BufferAbsDescribe(Buffer buffer, mps_lib_FILE *stream, Count depth) { Res res; - BufferClass klass; if (!TESTC(Buffer, buffer)) return ResPARAM; if (stream == NULL) return ResPARAM; - klass = ClassOfPoly(Buffer, buffer); - - res = WriteF(stream, depth, - "Buffer $P ($U) {\n", - (WriteFP)buffer, (WriteFU)buffer->serial, - " class $P (\"$S\")\n", - (WriteFP)klass, (WriteFS)ClassName(klass), - " Arena $P\n", (WriteFP)buffer->arena, - " Pool $P\n", (WriteFP)buffer->pool, - " ", buffer->isMutator ? "Mutator" : "Internal", " Buffer\n", - " mode $C$C$C$C (TRANSITION, LOGGED, FLIPPED, ATTACHED)\n", - (WriteFC)((buffer->mode & BufferModeTRANSITION) ? 't' : '_'), - (WriteFC)((buffer->mode & BufferModeLOGGED) ? 'l' : '_'), - (WriteFC)((buffer->mode & BufferModeFLIPPED) ? 'f' : '_'), - (WriteFC)((buffer->mode & BufferModeATTACHED) ? 'a' : '_'), - " fillSize $UKb\n", (WriteFU)(buffer->fillSize / 1024), - " emptySize $UKb\n", (WriteFU)(buffer->emptySize / 1024), - " alignment $W\n", (WriteFW)buffer->alignment, - " base $A\n", (WriteFA)buffer->base, - " initAtFlip $A\n", (WriteFA)buffer->initAtFlip, - " init $A\n", (WriteFA)buffer->ap_s.init, - " alloc $A\n", (WriteFA)buffer->ap_s.alloc, - " limit $A\n", (WriteFA)buffer->ap_s.limit, - " poolLimit $A\n", (WriteFA)buffer->poolLimit, - " alignment $W\n", (WriteFW)buffer->alignment, - " rampCount $U\n", (WriteFU)buffer->rampCount, - NULL); + res = InstDescribe(CouldBeA(Inst, buffer), stream, depth); if (res != ResOK) return res; - res = Method(Buffer, buffer, describe)(buffer, stream, depth + 2); - if (res != ResOK) - return res; + return WriteF(stream, depth + 2, + "serial $U\n", (WriteFU)buffer->serial, + "Arena $P\n", (WriteFP)buffer->arena, + "Pool $P\n", (WriteFP)buffer->pool, + buffer->isMutator ? "Mutator" : "Internal", " Buffer\n", + "mode $C$C$C$C (TRANSITION, LOGGED, FLIPPED, ATTACHED)\n", + (WriteFC)((buffer->mode & BufferModeTRANSITION) ? 't' : '_'), + (WriteFC)((buffer->mode & BufferModeLOGGED) ? 'l' : '_'), + (WriteFC)((buffer->mode & BufferModeFLIPPED) ? 'f' : '_'), + (WriteFC)((buffer->mode & BufferModeATTACHED) ? 'a' : '_'), + "fillSize $UKb\n", (WriteFU)(buffer->fillSize / 1024), + "emptySize $UKb\n", (WriteFU)(buffer->emptySize / 1024), + "alignment $W\n", (WriteFW)buffer->alignment, + "base $A\n", (WriteFA)buffer->base, + "initAtFlip $A\n", (WriteFA)buffer->initAtFlip, + "init $A\n", (WriteFA)buffer->ap_s.init, + "alloc $A\n", (WriteFA)buffer->ap_s.alloc, + "limit $A\n", (WriteFA)buffer->ap_s.limit, + "poolLimit $A\n", (WriteFA)buffer->poolLimit, + "alignment $W\n", (WriteFW)buffer->alignment, + "rampCount $U\n", (WriteFU)buffer->rampCount, + NULL); +} - res = WriteF(stream, depth, "} Buffer $P ($U)\n", - (WriteFP)buffer, (WriteFU)buffer->serial, - NULL); - return res; +Res BufferDescribe(Buffer buffer, mps_lib_FILE *stream, Count depth) +{ + return Method(Buffer, buffer, describe)(buffer, stream, depth); } @@ -1006,20 +998,6 @@ static void bufferNoReassignSeg(Buffer buffer, Seg seg) } -/* bufferTrivDescribe -- basic Buffer describe method */ - -static Res bufferTrivDescribe(Buffer buffer, mps_lib_FILE *stream, Count depth) -{ - if (!TESTT(Buffer, buffer)) - return ResFAIL; - if (stream == NULL) - return ResFAIL; - UNUSED(depth); - /* dispatching function does it all */ - return ResOK; -} - - /* BufferClassCheck -- check the consistency of a BufferClass */ Bool BufferClassCheck(BufferClass klass) @@ -1059,7 +1037,7 @@ DEFINE_CLASS(Buffer, Buffer, klass) klass->finish = BufferAbsFinish; klass->attach = bufferTrivAttach; klass->detach = bufferTrivDetach; - klass->describe = bufferTrivDescribe; + klass->describe = BufferAbsDescribe; klass->seg = bufferNoSeg; klass->rankSet = bufferTrivRankSet; klass->setRankSet = bufferNoSetRankSet; From c78477d9394fa55af88841da5b37831bc6c51345 Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sat, 23 Apr 2016 15:37:43 +0100 Subject: [PATCH 14/52] Branching master to branch/2016-04-23/inst-methods. Copied from Perforce Change: 191594 ServerID: perforce.ravenbrook.com From b9e791798b95cdc14f7fdc42dfb53a6dfeba53f8 Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sat, 23 Apr 2016 11:47:17 +0100 Subject: [PATCH 15/52] Making describe a method on inst and implementing generic describe for segments. Copied from Perforce Change: 191601 ServerID: perforce.ravenbrook.com --- mps/code/mpm.h | 2 +- mps/code/mpmst.h | 3 +-- mps/code/mpmtypes.h | 1 - mps/code/poolamc.c | 11 ++++++----- mps/code/poolams.c | 9 +++++---- mps/code/protocol.c | 6 +++++- mps/code/protocol.h | 2 ++ mps/code/seg.c | 22 +++++++++++----------- 8 files changed, 31 insertions(+), 25 deletions(-) diff --git a/mps/code/mpm.h b/mps/code/mpm.h index 556886c7104..589416f8017 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -669,7 +669,7 @@ extern void SegSetRankSet(Seg seg, RankSet rankSet); extern void SegSetRankAndSummary(Seg seg, RankSet rankSet, RefSet summary); extern Res SegMerge(Seg *mergedSegReturn, Seg segLo, Seg segHi); extern Res SegSplit(Seg *segLoReturn, Seg *segHiReturn, Seg seg, Addr at); -extern Res SegAbsDescribe(Seg seg, mps_lib_FILE *stream, Count depth); +extern Res SegAbsDescribe(Inst 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); diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index 065088e9cf0..13ca9776ff8 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -218,7 +218,7 @@ typedef struct mps_message_s { #define SegClassSig ((Sig)0x5195E9C7) /* SIGnature SEG CLass */ typedef struct SegClassStruct { - InstClassStruct protocol; + InstClassStruct instClassStruct; size_t size; /* size of outer structure */ SegInitMethod init; /* initialize the segment */ SegFinishMethod finish; /* finish the segment */ @@ -229,7 +229,6 @@ typedef struct SegClassStruct { SegSetWhiteMethod setWhite; /* change whiteness of segment */ SegSetRankSetMethod setRankSet; /* change rank set of segment */ SegSetRankSummaryMethod setRankSummary; /* change rank set & summary */ - SegDescribeMethod describe; /* describe the contents of the seg */ SegMergeMethod merge; /* merge two adjacent segments */ SegSplitMethod split; /* split a segment into two */ Sig sig; /* .class.end-sig */ diff --git a/mps/code/mpmtypes.h b/mps/code/mpmtypes.h index 5d8070eaa46..5fdc0402c44 100644 --- a/mps/code/mpmtypes.h +++ b/mps/code/mpmtypes.h @@ -162,7 +162,6 @@ typedef void (*SegSetRankSummaryMethod)(Seg seg, RankSet rankSet, typedef void (*SegSetSummaryMethod)(Seg seg, RefSet summary); typedef Buffer (*SegBufferMethod)(Seg seg); typedef void (*SegSetBufferMethod)(Seg seg, Buffer buffer); -typedef Res (*SegDescribeMethod)(Seg seg, mps_lib_FILE *stream, Count depth); typedef Res (*SegMergeMethod)(Seg seg, Seg segHi, Addr base, Addr mid, Addr limit); typedef Res (*SegSplitMethod)(Seg seg, Seg segHi, diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c index b7fe2fbaf27..77d81d58442 100644 --- a/mps/code/poolamc.c +++ b/mps/code/poolamc.c @@ -234,9 +234,10 @@ static void AMCSegSketch(Seg seg, char *pbSketch, size_t cbSketch) * * See . */ -static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) +static Res AMCSegDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { - amcSeg amcseg = CouldBeA(amcSeg, seg); + amcSeg amcseg = CouldBeA(amcSeg, inst); + Seg seg = CouldBeA(Seg, amcseg); Res res; Pool pool; Addr i, p, base, limit, init; @@ -250,7 +251,7 @@ static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) return ResPARAM; /* Describe the superclass fields first via next-method call */ - res = NextMethod(Seg, amcSeg, describe)(seg, stream, depth); + res = NextMethod(Inst, amcSeg, describe)(inst, stream, depth); if (res != ResOK) return res; @@ -331,9 +332,9 @@ DEFINE_CLASS(Seg, amcSeg, klass) { INHERIT_CLASS(klass, amcSeg, GCSeg); SegClassMixInNoSplitMerge(klass); /* no support for this (yet) */ + klass->instClassStruct.describe = AMCSegDescribe; klass->size = sizeof(amcSegStruct); klass->init = AMCSegInit; - klass->describe = AMCSegDescribe; } @@ -2003,7 +2004,7 @@ static Res AMCDescribe(Pool pool, mps_lib_FILE *stream, Count depth) /* SegDescribes */ RING_FOR(node, &pool->segRing, nextNode) { Seg seg = RING_ELT(Seg, poolRing, node); - res = AMCSegDescribe(seg, stream, depth + 2); + res = SegDescribe(seg, stream, depth + 2); if(res != ResOK) return res; } diff --git a/mps/code/poolams.c b/mps/code/poolams.c index 8218fa53f81..fe2f2f59341 100644 --- a/mps/code/poolams.c +++ b/mps/code/poolams.c @@ -523,9 +523,10 @@ failCreateTablesLo: } \ END -static Res AMSSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) +static Res AMSSegDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { - AMSSeg amsseg = CouldBeA(AMSSeg, seg); + AMSSeg amsseg = CouldBeA(AMSSeg, inst); + Seg seg = CouldBeA(Seg, amsseg); Res res; Buffer buffer; /* the segment's buffer, if it has one */ Index i; @@ -536,7 +537,7 @@ static Res AMSSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) return ResPARAM; /* Describe the superclass fields first via next-method call */ - res = NextMethod(Seg, AMSSeg, describe)(seg, stream, depth); + res = NextMethod(Inst, AMSSeg, describe)(inst, stream, depth); if (res != ResOK) return res; @@ -618,12 +619,12 @@ static Res AMSSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) DEFINE_CLASS(Seg, AMSSeg, klass) { INHERIT_CLASS(klass, AMSSeg, GCSeg); + klass->instClassStruct.describe = AMSSegDescribe; klass->size = sizeof(AMSSegStruct); klass->init = AMSSegInit; klass->finish = AMSSegFinish; klass->merge = AMSSegMerge; klass->split = AMSSegSplit; - klass->describe = AMSSegDescribe; AVERT(SegClass, klass); } diff --git a/mps/code/protocol.c b/mps/code/protocol.c index 7a749afd9bf..dff42bd2dd9 100644 --- a/mps/code/protocol.c +++ b/mps/code/protocol.c @@ -47,6 +47,8 @@ static void InstClassInitInternal(InstClass klass) klass->level = 0; klass->display[klass->level] = CLASS_ID(Inst); + klass->describe = InstDescribe; + /* We can't call CLASS(InstClass) here because it causes a loop back to here, so we have to tie this knot specially. */ klass->instStruct.klass = &CLASS_STATIC(InstClass); @@ -70,6 +72,7 @@ Bool InstClassCheck(InstClass klass) for (i = klass->level + 1; i < ClassDEPTH; ++i) { CHECKL(klass->display[i] == NULL); } + CHECKL(FUNCHECK(klass->describe)); return TRUE; } @@ -101,7 +104,8 @@ static InstClassStruct invalidClassStruct = { /* .name = */ "Invalid", /* .superclass = */ &invalidClassStruct, /* .level = */ 0, - /* .display = */ {(ClassId)&invalidClassStruct} + /* .display = */ {(ClassId)&invalidClassStruct}, + /* .describe = */ NULL }; void InstFinish(Inst inst) diff --git a/mps/code/protocol.h b/mps/code/protocol.h index 3b469d690e9..7288b9ec022 100644 --- a/mps/code/protocol.h +++ b/mps/code/protocol.h @@ -177,6 +177,7 @@ typedef struct InstStruct { typedef const char *ClassName; typedef unsigned char ClassLevel; +typedef Res (*DescribeMethod)(Inst inst, mps_lib_FILE *stream, Count depth); #define ClassDEPTH 8 /* maximum depth of class hierarchy */ #define InstClassSig ((Sig)0x519B1452) /* SIGnature Protocol INST */ @@ -188,6 +189,7 @@ typedef struct InstClassStruct { InstClass superclass; /* pointer to direct superclass */ ClassLevel level; /* distance from root of class hierarchy */ ClassId display[ClassDEPTH]; /* classes at this level and above */ + DescribeMethod describe; /* write a debugging description */ } InstClassStruct; enum {ClassLevelNoSuper = -1}; diff --git a/mps/code/seg.c b/mps/code/seg.c index 88b34fe6e55..919a0457b1f 100644 --- a/mps/code/seg.c +++ b/mps/code/seg.c @@ -375,8 +375,9 @@ Addr SegBufferScanLimit(Seg seg) /* SegDescribe -- describe a segment */ -Res SegAbsDescribe(Seg seg, mps_lib_FILE *stream, Count depth) +Res SegAbsDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { + Seg seg = CouldBeA(Seg, inst); Res res; Pool pool; @@ -385,7 +386,7 @@ Res SegAbsDescribe(Seg seg, mps_lib_FILE *stream, Count depth) if (stream == NULL) return ResPARAM; - res = InstDescribe(CouldBeA(Inst, seg), stream, depth); + res = NextMethod(Inst, Seg, describe)(inst, stream, depth); if (res != ResOK) return res; @@ -425,7 +426,7 @@ Res SegAbsDescribe(Seg seg, mps_lib_FILE *stream, Count depth) Res SegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) { - return Method(Seg, seg, describe)(seg, stream, depth); + return Method(Inst, seg, describe)(MustBeA(Inst, seg), stream, depth); } @@ -1514,9 +1515,9 @@ failSuper: /* gcSegDescribe -- GCSeg description method */ -static Res gcSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) +static Res gcSegDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { - GCSeg gcseg = CouldBeA(GCSeg, seg); + GCSeg gcseg = CouldBeA(GCSeg, inst); Res res; if (!TESTC(GCSeg, gcseg)) @@ -1525,7 +1526,7 @@ static Res gcSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) return ResPARAM; /* Describe the superclass fields first via next-method call */ - res = NextMethod(Seg, GCSeg, describe)(seg, stream, depth); + res = NextMethod(Inst, GCSeg, describe)(inst, stream, depth); if (res != ResOK) return res; @@ -1551,7 +1552,7 @@ static Res gcSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) Bool SegClassCheck(SegClass klass) { - CHECKD(InstClass, &klass->protocol); + CHECKD(InstClass, &klass->instClassStruct); CHECKL(klass->size >= sizeof(SegStruct)); CHECKL(FUNCHECK(klass->init)); CHECKL(FUNCHECK(klass->finish)); @@ -1561,7 +1562,6 @@ Bool SegClassCheck(SegClass klass) CHECKL(FUNCHECK(klass->setRankSummary)); CHECKL(FUNCHECK(klass->merge)); CHECKL(FUNCHECK(klass->split)); - CHECKL(FUNCHECK(klass->describe)); CHECKS(SegClass, klass); return TRUE; } @@ -1576,7 +1576,8 @@ DEFINE_CLASS(Inst, SegClass, klass) DEFINE_CLASS(Seg, Seg, klass) { - INHERIT_CLASS(&klass->protocol, Seg, Inst); + INHERIT_CLASS(&klass->instClassStruct, Seg, Inst); + klass->instClassStruct.describe = SegAbsDescribe; klass->size = sizeof(SegStruct); klass->init = SegAbsInit; klass->finish = SegAbsFinish; @@ -1589,7 +1590,6 @@ DEFINE_CLASS(Seg, Seg, klass) klass->setRankSummary = segNoSetRankSummary; klass->merge = segTrivMerge; klass->split = segTrivSplit; - klass->describe = SegAbsDescribe; klass->sig = SegClassSig; AVERT(SegClass, klass); } @@ -1602,6 +1602,7 @@ typedef SegClassStruct GCSegClassStruct; DEFINE_CLASS(Seg, GCSeg, klass) { INHERIT_CLASS(klass, GCSeg, Seg); + klass->instClassStruct.describe = gcSegDescribe; klass->size = sizeof(GCSegStruct); klass->init = gcSegInit; klass->finish = gcSegFinish; @@ -1614,7 +1615,6 @@ DEFINE_CLASS(Seg, GCSeg, klass) klass->setRankSummary = gcSegSetRankSummary; klass->merge = gcSegMerge; klass->split = gcSegSplit; - klass->describe = gcSegDescribe; AVERT(SegClass, klass); } From 5f7db268e211e813a2268cc51f36bc30065de343 Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sat, 23 Apr 2016 12:04:46 +0100 Subject: [PATCH 16/52] Making finish a method on inst and implementing generic finish for segments. Copied from Perforce Change: 191602 ServerID: perforce.ravenbrook.com --- mps/code/mpmst.h | 1 - mps/code/poolams.c | 20 ++++++++------------ mps/code/poolawl.c | 9 +++++---- mps/code/poollo.c | 11 ++++++----- mps/code/protocol.c | 6 +++++- mps/code/protocol.h | 2 ++ mps/code/seg.c | 22 +++++++++------------- mps/code/segsmss.c | 11 +++++------ 8 files changed, 40 insertions(+), 42 deletions(-) diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index 13ca9776ff8..301b1159e02 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -221,7 +221,6 @@ typedef struct SegClassStruct { InstClassStruct instClassStruct; size_t size; /* size of outer structure */ SegInitMethod init; /* initialize the segment */ - SegFinishMethod finish; /* finish the segment */ SegSetSummaryMethod setSummary; /* set the segment summary */ SegBufferMethod buffer; /* get the segment buffer */ SegSetBufferMethod setBuffer; /* set the segment buffer */ diff --git a/mps/code/poolams.c b/mps/code/poolams.c index fe2f2f59341..1ae594652a9 100644 --- a/mps/code/poolams.c +++ b/mps/code/poolams.c @@ -266,7 +266,7 @@ static Res AMSSegInit(Seg seg, Pool pool, Addr base, Size size, ArgList args) return ResOK; failCreateTables: - NextMethod(Seg, AMSSeg, finish)(seg); + NextMethod(Inst, AMSSeg, finish)(MustBeA(Inst, seg)); failNextMethod: AVER(res != ResOK); return res; @@ -275,18 +275,14 @@ failNextMethod: /* AMSSegFinish -- Finish method for AMS segments */ -static void AMSSegFinish(Seg seg) +static void AMSSegFinish(Inst inst) { - AMSSeg amsseg; - AMS ams; - Arena arena; + Seg seg = MustBeA(Seg, inst); + AMSSeg amsseg = MustBeA(AMSSeg, seg); + AMS ams = amsseg->ams; + Arena arena = PoolArena(AMSPool(ams)); - AVERT(Seg, seg); - amsseg = Seg2AMSSeg(seg); AVERT(AMSSeg, amsseg); - ams = amsseg->ams; - AVERT(AMS, ams); - arena = PoolArena(AMSPool(ams)); AVER(SegBuffer(seg) == NULL); /* keep the destructions in step with AMSSegInit failure cases */ @@ -299,7 +295,7 @@ static void AMSSegFinish(Seg seg) amsseg->sig = SigInvalid; /* finish the superclass fields last */ - NextMethod(Seg, AMSSeg, finish)(seg); + NextMethod(Inst, AMSSeg, finish)(inst); } @@ -620,9 +616,9 @@ DEFINE_CLASS(Seg, AMSSeg, klass) { INHERIT_CLASS(klass, AMSSeg, GCSeg); klass->instClassStruct.describe = AMSSegDescribe; + klass->instClassStruct.finish = AMSSegFinish; klass->size = sizeof(AMSSegStruct); klass->init = AMSSegInit; - klass->finish = AMSSegFinish; klass->merge = AMSSegMerge; klass->split = AMSSegSplit; AVERT(SegClass, klass); diff --git a/mps/code/poolawl.c b/mps/code/poolawl.c index 6ea7105185b..22e8e075b64 100644 --- a/mps/code/poolawl.c +++ b/mps/code/poolawl.c @@ -240,7 +240,7 @@ failControlAllocAlloc: failControlAllocScanned: ControlFree(arena, awlseg->mark, tableSize); failControlAllocMark: - NextMethod(Seg, AWLSeg, finish)(seg); + NextMethod(Inst, AWLSeg, finish)(MustBeA(Inst, seg)); failSuperInit: AVER(res != ResOK); return res; @@ -249,8 +249,9 @@ failSuperInit: /* AWLSegFinish -- Finish method for AWL segments */ -static void AWLSegFinish(Seg seg) +static void AWLSegFinish(Inst inst) { + Seg seg = MustBeA(Seg, inst); AWLSeg awlseg = MustBeA(AWLSeg, seg); Pool pool = SegPool(seg); AWL awl = MustBeA(AWLPool, pool); @@ -269,7 +270,7 @@ static void AWLSegFinish(Seg seg) awlseg->sig = SigInvalid; /* finish the superclass fields last */ - NextMethod(Seg, AWLSeg, finish)(seg); + NextMethod(Inst, AWLSeg, finish)(inst); } @@ -279,9 +280,9 @@ DEFINE_CLASS(Seg, AWLSeg, klass) { INHERIT_CLASS(klass, AWLSeg, GCSeg); SegClassMixInNoSplitMerge(klass); /* no support for this (yet) */ + klass->instClassStruct.finish = AWLSegFinish; klass->size = sizeof(AWLSegStruct); klass->init = AWLSegInit; - klass->finish = AWLSegFinish; } diff --git a/mps/code/poollo.c b/mps/code/poollo.c index 5b3a20189d5..f20c54a9170 100644 --- a/mps/code/poollo.c +++ b/mps/code/poollo.c @@ -61,7 +61,7 @@ typedef struct LOSegStruct { /* forward decls */ static Res loSegInit(Seg seg, Pool pool, Addr base, Size size, ArgList args); -static void loSegFinish(Seg seg); +static void loSegFinish(Inst inst); static Count loSegGrains(LOSeg loseg); @@ -71,9 +71,9 @@ DEFINE_CLASS(Seg, LOSeg, klass) { INHERIT_CLASS(klass, LOSeg, GCSeg); SegClassMixInNoSplitMerge(klass); + klass->instClassStruct.finish = loSegFinish; klass->size = sizeof(LOSegStruct); klass->init = loSegInit; - klass->finish = loSegFinish; } @@ -143,7 +143,7 @@ static Res loSegInit(Seg seg, Pool pool, Addr base, Size size, ArgList args) failAllocTable: ControlFree(arena, loseg->mark, tablebytes); failMarkTable: - NextMethod(Seg, LOSeg, finish)(seg); + NextMethod(Inst, LOSeg, finish)(MustBeA(Inst, seg)); failSuperInit: AVER(res != ResOK); return res; @@ -152,8 +152,9 @@ failSuperInit: /* loSegFinish -- Finish method for LO segments */ -static void loSegFinish(Seg seg) +static void loSegFinish(Inst inst) { + Seg seg = MustBeA(Seg, inst); LOSeg loseg = MustBeA(LOSeg, seg); Pool pool = SegPool(seg); Arena arena = PoolArena(pool); @@ -167,7 +168,7 @@ static void loSegFinish(Seg seg) ControlFree(arena, loseg->alloc, tablesize); ControlFree(arena, loseg->mark, tablesize); - NextMethod(Seg, LOSeg, finish)(seg); + NextMethod(Inst, LOSeg, finish)(inst); } diff --git a/mps/code/protocol.c b/mps/code/protocol.c index dff42bd2dd9..36e4a45dc2d 100644 --- a/mps/code/protocol.c +++ b/mps/code/protocol.c @@ -47,7 +47,9 @@ static void InstClassInitInternal(InstClass klass) klass->level = 0; klass->display[klass->level] = CLASS_ID(Inst); + /* Generic methods */ klass->describe = InstDescribe; + klass->finish = InstFinish; /* We can't call CLASS(InstClass) here because it causes a loop back to here, so we have to tie this knot specially. */ @@ -73,6 +75,7 @@ Bool InstClassCheck(InstClass klass) CHECKL(klass->display[i] == NULL); } CHECKL(FUNCHECK(klass->describe)); + CHECKL(FUNCHECK(klass->finish)); return TRUE; } @@ -105,7 +108,8 @@ static InstClassStruct invalidClassStruct = { /* .superclass = */ &invalidClassStruct, /* .level = */ 0, /* .display = */ {(ClassId)&invalidClassStruct}, - /* .describe = */ NULL + /* .describe = */ NULL, + /* .finish = */ NULL, }; void InstFinish(Inst inst) diff --git a/mps/code/protocol.h b/mps/code/protocol.h index 7288b9ec022..7a230057f41 100644 --- a/mps/code/protocol.h +++ b/mps/code/protocol.h @@ -178,6 +178,7 @@ typedef struct InstStruct { typedef const char *ClassName; typedef unsigned char ClassLevel; typedef Res (*DescribeMethod)(Inst inst, mps_lib_FILE *stream, Count depth); +typedef void (*FinishMethod)(Inst inst); #define ClassDEPTH 8 /* maximum depth of class hierarchy */ #define InstClassSig ((Sig)0x519B1452) /* SIGnature Protocol INST */ @@ -190,6 +191,7 @@ typedef struct InstClassStruct { ClassLevel level; /* distance from root of class hierarchy */ ClassId display[ClassDEPTH]; /* classes at this level and above */ DescribeMethod describe; /* write a debugging description */ + FinishMethod finish; /* finish instance */ } InstClassStruct; enum {ClassLevelNoSuper = -1}; diff --git a/mps/code/seg.c b/mps/code/seg.c index 919a0457b1f..52a1ac0ade8 100644 --- a/mps/code/seg.c +++ b/mps/code/seg.c @@ -192,8 +192,9 @@ static Res SegInit(Seg seg, SegClass klass, Pool pool, Addr base, Size size, Arg /* SegFinish -- finish a segment */ -static void SegAbsFinish(Seg seg) +static void SegAbsFinish(Inst inst) { + Seg seg = MustBeA(Seg, inst); Arena arena; Addr addr, limit; Tract tract; @@ -246,7 +247,7 @@ static void SegAbsFinish(Seg seg) static void SegFinish(Seg seg) { AVERC(Seg, seg); - Method(Seg, seg, finish)(seg); + Method(Inst, seg, finish)(MustBeA(Inst, seg)); } @@ -1069,14 +1070,10 @@ static Res gcSegInit(Seg seg, Pool pool, Addr base, Size size, ArgList args) /* gcSegFinish -- finish a GC segment */ -static void gcSegFinish(Seg seg) +static void gcSegFinish(Inst inst) { - GCSeg gcseg; - - AVERT(Seg, seg); - gcseg = SegGCSeg(seg); - AVERT(GCSeg, gcseg); - AVER(&gcseg->segStruct == seg); + Seg seg = MustBeA(Seg, inst); + GCSeg gcseg = MustBeA(GCSeg, seg); if (SegGrey(seg) != TraceSetEMPTY) { RingRemove(&gcseg->greyRing); @@ -1092,7 +1089,7 @@ static void gcSegFinish(Seg seg) RingFinish(&gcseg->greyRing); /* finish the superclass fields last */ - NextMethod(Seg, GCSeg, finish)(seg); + NextMethod(Inst, GCSeg, finish)(inst); } @@ -1555,7 +1552,6 @@ Bool SegClassCheck(SegClass klass) CHECKD(InstClass, &klass->instClassStruct); CHECKL(klass->size >= sizeof(SegStruct)); CHECKL(FUNCHECK(klass->init)); - CHECKL(FUNCHECK(klass->finish)); CHECKL(FUNCHECK(klass->setGrey)); CHECKL(FUNCHECK(klass->setWhite)); CHECKL(FUNCHECK(klass->setRankSet)); @@ -1578,9 +1574,9 @@ DEFINE_CLASS(Seg, Seg, klass) { INHERIT_CLASS(&klass->instClassStruct, Seg, Inst); klass->instClassStruct.describe = SegAbsDescribe; + klass->instClassStruct.finish = SegAbsFinish; klass->size = sizeof(SegStruct); klass->init = SegAbsInit; - klass->finish = SegAbsFinish; klass->setSummary = segNoSetSummary; klass->buffer = segNoBuffer; klass->setBuffer = segNoSetBuffer; @@ -1603,9 +1599,9 @@ DEFINE_CLASS(Seg, GCSeg, klass) { INHERIT_CLASS(klass, GCSeg, Seg); klass->instClassStruct.describe = gcSegDescribe; + klass->instClassStruct.finish = gcSegFinish; klass->size = sizeof(GCSegStruct); klass->init = gcSegInit; - klass->finish = gcSegFinish; klass->setSummary = gcSegSetSummary; klass->buffer = gcSegBuffer; klass->setBuffer = gcSegSetBuffer; diff --git a/mps/code/segsmss.c b/mps/code/segsmss.c index a4f9ebab030..db26cfafd4f 100644 --- a/mps/code/segsmss.c +++ b/mps/code/segsmss.c @@ -141,12 +141,11 @@ static Res amstSegInit(Seg seg, Pool pool, Addr base, Size size, ArgList args) /* amstSegFinish -- Finish method for AMST segments */ -static void amstSegFinish(Seg seg) +static void amstSegFinish(Inst inst) { - AMSTSeg amstseg; + Seg seg = MustBeA(Seg, inst); + AMSTSeg amstseg = MustBeA(AMSTSeg, seg); - AVERT(Seg, seg); - amstseg = Seg2AMSTSeg(seg); AVERT(AMSTSeg, amstseg); if (amstseg->next != NULL) @@ -156,7 +155,7 @@ static void amstSegFinish(Seg seg) amstseg->sig = SigInvalid; /* finish the superclass fields last */ - NextMethod(Seg, AMSTSeg, finish)(seg); + NextMethod(Inst, AMSTSeg, finish)(inst); } @@ -269,9 +268,9 @@ failSuper: DEFINE_CLASS(Seg, AMSTSeg, klass) { INHERIT_CLASS(klass, AMSTSeg, AMSSeg); + klass->instClassStruct.finish = amstSegFinish; klass->size = sizeof(AMSTSegStruct); klass->init = amstSegInit; - klass->finish = amstSegFinish; klass->split = amstSegSplit; klass->merge = amstSegMerge; AVERT(SegClass, klass); From 1e39e959e73a833c41741989cdb90ecf52480084 Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sat, 23 Apr 2016 12:35:27 +0100 Subject: [PATCH 17/52] Making init a method on inst and using it as next-method in segments. Copied from Perforce Change: 191603 ServerID: perforce.ravenbrook.com --- mps/code/protocol.c | 3 +++ mps/code/protocol.h | 2 ++ mps/code/seg.c | 3 +-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/mps/code/protocol.c b/mps/code/protocol.c index 36e4a45dc2d..1f3a648975c 100644 --- a/mps/code/protocol.c +++ b/mps/code/protocol.c @@ -50,6 +50,7 @@ static void InstClassInitInternal(InstClass klass) /* Generic methods */ klass->describe = InstDescribe; klass->finish = InstFinish; + klass->init = InstInit; /* We can't call CLASS(InstClass) here because it causes a loop back to here, so we have to tie this knot specially. */ @@ -76,6 +77,7 @@ Bool InstClassCheck(InstClass klass) } CHECKL(FUNCHECK(klass->describe)); CHECKL(FUNCHECK(klass->finish)); + CHECKL(FUNCHECK(klass->init)); return TRUE; } @@ -110,6 +112,7 @@ static InstClassStruct invalidClassStruct = { /* .display = */ {(ClassId)&invalidClassStruct}, /* .describe = */ NULL, /* .finish = */ NULL, + /* .init = */ NULL, }; void InstFinish(Inst inst) diff --git a/mps/code/protocol.h b/mps/code/protocol.h index 7a230057f41..6e569486d48 100644 --- a/mps/code/protocol.h +++ b/mps/code/protocol.h @@ -178,6 +178,7 @@ typedef struct InstStruct { typedef const char *ClassName; typedef unsigned char ClassLevel; typedef Res (*DescribeMethod)(Inst inst, mps_lib_FILE *stream, Count depth); +typedef void (*InstInitMethod)(Inst inst); typedef void (*FinishMethod)(Inst inst); #define ClassDEPTH 8 /* maximum depth of class hierarchy */ @@ -192,6 +193,7 @@ typedef struct InstClassStruct { ClassId display[ClassDEPTH]; /* classes at this level and above */ DescribeMethod describe; /* write a debugging description */ FinishMethod finish; /* finish instance */ + InstInitMethod init; /* base init method */ } InstClassStruct; enum {ClassLevelNoSuper = -1}; diff --git a/mps/code/seg.c b/mps/code/seg.c index 52a1ac0ade8..67803910d47 100644 --- a/mps/code/seg.c +++ b/mps/code/seg.c @@ -132,8 +132,7 @@ static Res SegAbsInit(Seg seg, Pool pool, Addr base, Size size, ArgList args) AVER(SizeIsArenaGrains(size, arena)); AVERT(ArgList, args); - /* Superclass init */ - InstInit(CouldBeA(Inst, seg)); + NextMethod(Inst, Seg, init)(CouldBeA(Inst, seg)); limit = AddrAdd(base, size); seg->limit = limit; From 6217b5b3a53803cdd8b4176c4e0d65bab4be9038 Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sat, 23 Apr 2016 12:54:17 +0100 Subject: [PATCH 18/52] Converting pool describe methods to specialise instdescribe. Copied from Perforce Change: 191604 ServerID: perforce.ravenbrook.com --- mps/code/mpm.h | 2 +- mps/code/mpmst.h | 1 - mps/code/pool.c | 3 +-- mps/code/poolabs.c | 5 +++-- mps/code/poolamc.c | 9 +++++---- mps/code/poolams.c | 7 ++++--- mps/code/poolmfs.c | 7 ++++--- mps/code/poolmrg.c | 7 ++++--- mps/code/poolmv.c | 7 ++++--- mps/code/poolmv2.c | 9 +++++---- mps/code/poolmvff.c | 7 ++++--- mps/code/pooln.c | 15 ++++++++++----- 12 files changed, 45 insertions(+), 34 deletions(-) diff --git a/mps/code/mpm.h b/mps/code/mpm.h index 589416f8017..793e19db5b2 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -251,7 +251,7 @@ extern void PoolNoBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit); extern void PoolTrivBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit); -extern Res PoolAbsDescribe(Pool pool, mps_lib_FILE *stream, Count depth); +extern Res PoolAbsDescribe(Inst inst, mps_lib_FILE *stream, Count depth); extern Res PoolNoTraceBegin(Pool pool, Trace trace); extern Res PoolTrivTraceBegin(Pool pool, Trace trace); extern Res PoolNoAccess(Pool pool, Seg seg, Addr addr, diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index 301b1159e02..930f442ea34 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -76,7 +76,6 @@ typedef struct mps_pool_class_s { PoolWalkMethod walk; /* walk over a segment */ PoolFreeWalkMethod freewalk; /* walk over free blocks */ PoolBufferClassMethod bufferClass; /* default BufferClass of pool */ - PoolDescribeMethod describe; /* describe the contents of the pool */ PoolDebugMixinMethod debugMixin; /* find the debug mixin, if any */ PoolSizeMethod totalSize; /* total memory allocated from arena */ PoolSizeMethod freeSize; /* free memory (unused by client program) */ diff --git a/mps/code/pool.c b/mps/code/pool.c index bb1a6f34f74..d132365f7dc 100644 --- a/mps/code/pool.c +++ b/mps/code/pool.c @@ -65,7 +65,6 @@ Bool PoolClassCheck(PoolClass klass) CHECKL(FUNCHECK(klass->walk)); CHECKL(FUNCHECK(klass->freewalk)); CHECKL(FUNCHECK(klass->bufferClass)); - CHECKL(FUNCHECK(klass->describe)); CHECKL(FUNCHECK(klass->debugMixin)); CHECKL(FUNCHECK(klass->totalSize)); CHECKL(FUNCHECK(klass->freeSize)); @@ -490,7 +489,7 @@ Size PoolFreeSize(Pool pool) Res PoolDescribe(Pool pool, mps_lib_FILE *stream, Count depth) { - return Method(Pool, pool, describe)(pool, stream, depth); + return Method(Inst, pool, describe)(MustBeA(Inst, pool), stream, depth); } diff --git a/mps/code/poolabs.c b/mps/code/poolabs.c index e7fc6d3c01b..a25c3b814f1 100644 --- a/mps/code/poolabs.c +++ b/mps/code/poolabs.c @@ -185,6 +185,7 @@ DEFINE_CLASS(Inst, PoolClass, klass) DEFINE_CLASS(Pool, AbstractPool, klass) { INHERIT_CLASS(&klass->protocol, AbstractPool, Inst); + klass->protocol.describe = PoolAbsDescribe; klass->size = sizeof(PoolStruct); klass->attr = 0; klass->varargs = ArgTrivVarargs; @@ -211,7 +212,6 @@ DEFINE_CLASS(Pool, AbstractPool, klass) klass->walk = PoolNoWalk; klass->freewalk = PoolTrivFreeWalk; klass->bufferClass = PoolNoBufferClass; - klass->describe = PoolAbsDescribe; klass->debugMixin = PoolNoDebugMixin; klass->totalSize = PoolNoSize; klass->freeSize = PoolNoSize; @@ -353,8 +353,9 @@ void PoolTrivBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit) } -Res PoolAbsDescribe(Pool pool, mps_lib_FILE *stream, Count depth) +Res PoolAbsDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { + Pool pool = CouldBeA(AbstractPool, inst); Res res; Ring node, nextNode; diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c index 77d81d58442..7ecc80ecaf3 100644 --- a/mps/code/poolamc.c +++ b/mps/code/poolamc.c @@ -1960,10 +1960,11 @@ static Size AMCFreeSize(Pool pool) * See . */ -static Res AMCDescribe(Pool pool, mps_lib_FILE *stream, Count depth) +static Res AMCDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { - Res res; + Pool pool = CouldBeA(AbstractPool, inst); AMC amc = CouldBeA(AMCZPool, pool); + Res res; Ring node, nextNode; const char *rampmode; @@ -1972,7 +1973,7 @@ static Res AMCDescribe(Pool pool, mps_lib_FILE *stream, Count depth) if (stream == NULL) return ResPARAM; - res = NextMethod(Pool, AMCZPool, describe)(pool, stream, depth); + res = NextMethod(Inst, AMCZPool, describe)(inst, stream, depth); if (res != ResOK) return res; @@ -2021,6 +2022,7 @@ DEFINE_CLASS(Pool, AMCZPool, klass) INHERIT_CLASS(klass, AMCZPool, AbstractSegBufPool); PoolClassMixInFormat(klass); PoolClassMixInCollect(klass); + klass->protocol.describe = AMCDescribe; klass->size = sizeof(AMCStruct); klass->attr |= AttrMOVINGGC; klass->varargs = AMCVarargs; @@ -2039,7 +2041,6 @@ DEFINE_CLASS(Pool, AMCZPool, klass) klass->bufferClass = amcBufClassGet; klass->totalSize = AMCTotalSize; klass->freeSize = AMCFreeSize; - klass->describe = AMCDescribe; } diff --git a/mps/code/poolams.c b/mps/code/poolams.c index 1ae594652a9..38600642d77 100644 --- a/mps/code/poolams.c +++ b/mps/code/poolams.c @@ -1694,8 +1694,9 @@ static Size AMSFreeSize(Pool pool) * Iterates over the segments, describing all of them. */ -static Res AMSDescribe(Pool pool, mps_lib_FILE *stream, Count depth) +static Res AMSDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { + Pool pool = CouldBeA(AbstractPool, inst); AMS ams = CouldBeA(AMSPool, pool); Ring node, nextNode; Res res; @@ -1705,7 +1706,7 @@ static Res AMSDescribe(Pool pool, mps_lib_FILE *stream, Count depth) if (stream == NULL) return ResPARAM; - res = NextMethod(Pool, AMSPool, describe)(pool, stream, depth); + res = NextMethod(Inst, AMSPool, describe)(inst, stream, depth); if (res != ResOK) return res; @@ -1742,6 +1743,7 @@ DEFINE_CLASS(Pool, AMSPool, klass) { INHERIT_CLASS(klass, AMSPool, AbstractCollectPool); PoolClassMixInFormat(klass); + klass->protocol.describe = AMSDescribe; klass->size = sizeof(AMSStruct); klass->varargs = AMSVarargs; klass->init = AMSInit; @@ -1760,7 +1762,6 @@ DEFINE_CLASS(Pool, AMSPool, klass) klass->freewalk = AMSFreeWalk; klass->totalSize = AMSTotalSize; klass->freeSize = AMSFreeSize; - klass->describe = AMSDescribe; AVERT(PoolClass, klass); } diff --git a/mps/code/poolmfs.c b/mps/code/poolmfs.c index 92627aaf4f8..688258db696 100644 --- a/mps/code/poolmfs.c +++ b/mps/code/poolmfs.c @@ -306,8 +306,9 @@ static Size MFSFreeSize(Pool pool) } -static Res MFSDescribe(Pool pool, mps_lib_FILE *stream, Count depth) +static Res MFSDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { + Pool pool = CouldBeA(AbstractPool, inst); MFS mfs = CouldBeA(MFSPool, pool); Res res; @@ -316,7 +317,7 @@ static Res MFSDescribe(Pool pool, mps_lib_FILE *stream, Count depth) if (stream == NULL) return ResPARAM; - res = NextMethod(Pool, MFSPool, describe)(pool, stream, depth); + res = NextMethod(Inst, MFSPool, describe)(inst, stream, depth); if (res != ResOK) return res; @@ -336,6 +337,7 @@ static Res MFSDescribe(Pool pool, mps_lib_FILE *stream, Count depth) DEFINE_CLASS(Pool, MFSPool, klass) { INHERIT_CLASS(klass, MFSPool, AbstractPool); + klass->protocol.describe = MFSDescribe; klass->size = sizeof(MFSStruct); klass->varargs = MFSVarargs; klass->init = MFSInit; @@ -344,7 +346,6 @@ DEFINE_CLASS(Pool, MFSPool, klass) klass->free = MFSFree; klass->totalSize = MFSTotalSize; klass->freeSize = MFSFreeSize; - klass->describe = MFSDescribe; } diff --git a/mps/code/poolmrg.c b/mps/code/poolmrg.c index 5eaa017bf97..5d29dcc792f 100644 --- a/mps/code/poolmrg.c +++ b/mps/code/poolmrg.c @@ -771,8 +771,9 @@ Res MRGDeregister(Pool pool, Ref obj) * and having MRGDescribe iterate over all the pool's segments. */ -static Res MRGDescribe(Pool pool, mps_lib_FILE *stream, Count depth) +static Res MRGDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { + Pool pool = CouldBeA(AbstractPool, inst); MRG mrg = CouldBeA(MRGPool, pool); Arena arena; Ring node, nextNode; @@ -784,7 +785,7 @@ static Res MRGDescribe(Pool pool, mps_lib_FILE *stream, Count depth) if (stream == NULL) return ResPARAM; - res = NextMethod(Pool, MRGPool, describe)(pool, stream, depth); + res = NextMethod(Inst, MRGPool, describe)(inst, stream, depth); if (res != ResOK) return res; @@ -840,13 +841,13 @@ static Res MRGScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) DEFINE_CLASS(Pool, MRGPool, klass) { INHERIT_CLASS(klass, MRGPool, AbstractPool); + klass->protocol.describe = MRGDescribe; klass->size = sizeof(MRGStruct); klass->init = MRGInit; klass->finish = MRGFinish; klass->grey = PoolTrivGrey; klass->blacken = PoolTrivBlacken; klass->scan = MRGScan; - klass->describe = MRGDescribe; } diff --git a/mps/code/poolmv.c b/mps/code/poolmv.c index 821c8eea21f..0ff6c0bc455 100644 --- a/mps/code/poolmv.c +++ b/mps/code/poolmv.c @@ -752,8 +752,9 @@ static Size MVFreeSize(Pool pool) } -static Res MVDescribe(Pool pool, mps_lib_FILE *stream, Count depth) +static Res MVDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { + Pool pool = CouldBeA(AbstractPool, inst); MV mv = CouldBeA(MVPool, pool); Res res; MVSpan span; @@ -767,7 +768,7 @@ static Res MVDescribe(Pool pool, mps_lib_FILE *stream, Count depth) if (stream == NULL) return ResPARAM; - res = NextMethod(Pool, MVPool, describe)(pool, stream, depth); + res = NextMethod(Inst, MVPool, describe)(inst, stream, depth); if (res != ResOK) return res; @@ -864,6 +865,7 @@ static Res MVDescribe(Pool pool, mps_lib_FILE *stream, Count depth) DEFINE_CLASS(Pool, MVPool, klass) { INHERIT_CLASS(klass, MVPool, AbstractBufferPool); + klass->protocol.describe = MVDescribe; klass->size = sizeof(MVStruct); klass->varargs = MVVarargs; klass->init = MVInit; @@ -872,7 +874,6 @@ DEFINE_CLASS(Pool, MVPool, klass) klass->free = MVFree; klass->totalSize = MVTotalSize; klass->freeSize = MVFreeSize; - klass->describe = MVDescribe; } diff --git a/mps/code/poolmv2.c b/mps/code/poolmv2.c index f563922588a..fca7e43288d 100644 --- a/mps/code/poolmv2.c +++ b/mps/code/poolmv2.c @@ -38,7 +38,7 @@ static Res MVTBufferFill(Addr *baseReturn, Addr *limitReturn, Pool pool, Buffer buffer, Size minSize); static void MVTBufferEmpty(Pool pool, Buffer buffer, Addr base, Addr limit); static void MVTFree(Pool pool, Addr base, Size size); -static Res MVTDescribe(Pool pool, mps_lib_FILE *stream, Count depth); +static Res MVTDescribe(Inst inst, mps_lib_FILE *stream, Count depth); static Size MVTTotalSize(Pool pool); static Size MVTFreeSize(Pool pool); static Res MVTSegAlloc(Seg *segReturn, MVT mvt, Size size); @@ -139,6 +139,7 @@ typedef struct MVTStruct DEFINE_CLASS(Pool, MVTPool, klass) { INHERIT_CLASS(klass, MVTPool, AbstractBufferPool); + klass->protocol.describe = MVTDescribe; klass->size = sizeof(MVTStruct); klass->varargs = MVTVarargs; klass->init = MVTInit; @@ -148,7 +149,6 @@ DEFINE_CLASS(Pool, MVTPool, klass) klass->bufferEmpty = MVTBufferEmpty; klass->totalSize = MVTTotalSize; klass->freeSize = MVTFreeSize; - klass->describe = MVTDescribe; } /* Macros */ @@ -1023,8 +1023,9 @@ static Size MVTFreeSize(Pool pool) /* MVTDescribe -- describe an MVT pool */ -static Res MVTDescribe(Pool pool, mps_lib_FILE *stream, Count depth) +static Res MVTDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { + Pool pool = CouldBeA(AbstractPool, inst); MVT mvt = CouldBeA(MVTPool, pool); Res res; @@ -1033,7 +1034,7 @@ static Res MVTDescribe(Pool pool, mps_lib_FILE *stream, Count depth) if (stream == NULL) return ResFAIL; - res = NextMethod(Pool, MVTPool, describe)(pool, stream, depth); + res = NextMethod(Inst, MVTPool, describe)(inst, stream, depth); if (res != ResOK) return res; diff --git a/mps/code/poolmvff.c b/mps/code/poolmvff.c index dda5779eddc..5424d70fb99 100644 --- a/mps/code/poolmvff.c +++ b/mps/code/poolmvff.c @@ -671,8 +671,9 @@ static Size MVFFFreeSize(Pool pool) /* MVFFDescribe -- describe an MVFF pool */ -static Res MVFFDescribe(Pool pool, mps_lib_FILE *stream, Count depth) +static Res MVFFDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { + Pool pool = CouldBeA(AbstractPool, inst); MVFF mvff = CouldBeA(MVFFPool, pool); Res res; @@ -681,7 +682,7 @@ static Res MVFFDescribe(Pool pool, mps_lib_FILE *stream, Count depth) if (stream == NULL) return ResPARAM; - res = NextMethod(Pool, MVFFPool, describe)(pool, stream, depth); + res = NextMethod(Inst, MVFFPool, describe)(inst, stream, depth); if (res != ResOK) return res; @@ -722,6 +723,7 @@ DEFINE_CLASS(Pool, MVFFPool, klass) { INHERIT_CLASS(klass, MVFFPool, AbstractPool); PoolClassMixInBuffer(klass); + klass->protocol.describe = MVFFDescribe; klass->size = sizeof(MVFFStruct); klass->varargs = MVFFVarargs; klass->init = MVFFInit; @@ -732,7 +734,6 @@ DEFINE_CLASS(Pool, MVFFPool, klass) klass->bufferEmpty = MVFFBufferEmpty; klass->totalSize = MVFFTotalSize; klass->freeSize = MVFFFreeSize; - klass->describe = MVFFDescribe; } diff --git a/mps/code/pooln.c b/mps/code/pooln.c index 66986dafc0d..7111236183a 100644 --- a/mps/code/pooln.c +++ b/mps/code/pooln.c @@ -139,12 +139,17 @@ static void NBufferEmpty(Pool pool, Buffer buffer, /* NDescribe -- describe method for class N */ -static Res NDescribe(Pool pool, mps_lib_FILE *stream, Count depth) +static Res NDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { - PoolN poolN = MustBeA(NPool, pool); + Pool pool = CouldBeA(AbstractPool, inst); + PoolN poolN = CouldBeA(NPool, pool); + Res res; - UNUSED(stream); /* TODO: should output something here */ - UNUSED(depth); + res = NextMethod(Inst, NPool, describe)(inst, stream, depth); + if (res != ResOK) + return res; + + /* This is where you'd output some information about pool fields. */ UNUSED(poolN); return ResOK; @@ -251,6 +256,7 @@ static void NTraceEnd(Pool pool, Trace trace) DEFINE_CLASS(Pool, NPool, klass) { INHERIT_CLASS(klass, NPool, AbstractPool); + klass->protocol.describe = NDescribe; klass->size = sizeof(PoolNStruct); klass->attr |= AttrGC; klass->init = NInit; @@ -267,7 +273,6 @@ DEFINE_CLASS(Pool, NPool, klass) klass->fixEmergency = NFix; klass->reclaim = NReclaim; klass->traceEnd = NTraceEnd; - klass->describe = NDescribe; AVERT(PoolClass, klass); } From de1f3907ccd72b547c21ea6359126af7565aa46b Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sat, 23 Apr 2016 13:21:12 +0100 Subject: [PATCH 19/52] Converting pool finish methods to specialize instfinish, and fixing up quite a few calls to use nextmethod. Copied from Perforce Change: 191605 ServerID: perforce.ravenbrook.com --- mps/code/dbgpool.c | 9 +++++---- mps/code/mpm.h | 2 +- mps/code/mpmst.h | 1 - mps/code/pool.c | 6 +++--- mps/code/poolabs.c | 6 ++++-- mps/code/poolamc.c | 10 ++++++---- mps/code/poolams.c | 14 +++++++------- mps/code/poolams.h | 2 +- mps/code/poolawl.c | 10 ++++++---- mps/code/poollo.c | 10 ++++++---- mps/code/poolmfs.c | 8 +++++--- mps/code/poolmrg.c | 7 ++++--- mps/code/poolmv.c | 13 ++++++------- mps/code/poolmv2.c | 20 +++++++++----------- mps/code/poolmvff.c | 13 ++++++------- mps/code/pooln.c | 7 ++++--- mps/code/poolsnc.c | 11 +++++------ mps/code/segsmss.c | 14 +++++++------- 18 files changed, 85 insertions(+), 78 deletions(-) diff --git a/mps/code/dbgpool.c b/mps/code/dbgpool.c index 8068dc64b97..5a56002695c 100644 --- a/mps/code/dbgpool.c +++ b/mps/code/dbgpool.c @@ -206,7 +206,7 @@ static Res DebugPoolInit(Pool pool, Arena arena, PoolClass klass, ArgList args) return ResOK; tagFail: - SuperclassPoly(Pool, klass)->finish(pool); + SuperclassPoly(Inst, klass)->finish(MustBeA(Inst, pool)); AVER(res != ResOK); return res; } @@ -214,8 +214,9 @@ tagFail: /* DebugPoolFinish -- finish method for a debug pool */ -static void DebugPoolFinish(Pool pool) +static void DebugPoolFinish(Inst inst) { + Pool pool = MustBeA(AbstractPool, inst); PoolDebugMixin debug; PoolClass klass; @@ -229,7 +230,7 @@ static void DebugPoolFinish(Pool pool) PoolDestroy(debug->tagPool); } klass = ClassOfPoly(Pool, pool); - SuperclassPoly(Pool, klass)->finish(pool); + SuperclassPoly(Inst, klass)->finish(inst); } @@ -775,8 +776,8 @@ void DebugPoolCheckFreeSpace(Pool pool) void PoolClassMixInDebug(PoolClass klass) { /* Can't check klass because it's not initialized yet */ + klass->protocol.finish = DebugPoolFinish; klass->init = DebugPoolInit; - klass->finish = DebugPoolFinish; klass->alloc = DebugPoolAlloc; klass->free = DebugPoolFree; } diff --git a/mps/code/mpm.h b/mps/code/mpm.h index 793e19db5b2..df60bc1043e 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -238,7 +238,7 @@ extern Size PoolTotalSize(Pool pool); extern Size PoolFreeSize(Pool pool); extern Res PoolAbsInit(Pool pool, Arena arena, PoolClass klass, ArgList arg); -extern void PoolAbsFinish(Pool pool); +extern void PoolAbsFinish(Inst inst); extern Res PoolNoAlloc(Addr *pReturn, Pool pool, Size size); extern Res PoolTrivAlloc(Addr *pReturn, Pool pool, Size size); extern void PoolNoFree(Pool pool, Addr old, Size size); diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index 930f442ea34..19b3cae7983 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -54,7 +54,6 @@ typedef struct mps_pool_class_s { Attr attr; /* attributes */ PoolVarargsMethod varargs; /* convert deprecated varargs into keywords */ PoolInitMethod init; /* initialize the pool descriptor */ - PoolFinishMethod finish; /* finish the pool descriptor */ PoolAllocMethod alloc; /* allocate memory from pool */ PoolFreeMethod free; /* free memory to pool */ PoolBufferFillMethod bufferFill; /* out-of-line reserve */ diff --git a/mps/code/pool.c b/mps/code/pool.c index d132365f7dc..b6fb278a121 100644 --- a/mps/code/pool.c +++ b/mps/code/pool.c @@ -43,7 +43,6 @@ Bool PoolClassCheck(PoolClass klass) CHECKL(!(klass->attr & AttrMOVINGGC) || (klass->attr & AttrGC)); CHECKL(FUNCHECK(klass->varargs)); CHECKL(FUNCHECK(klass->init)); - CHECKL(FUNCHECK(klass->finish)); CHECKL(FUNCHECK(klass->alloc)); CHECKL(FUNCHECK(klass->free)); CHECKL(FUNCHECK(klass->bufferFill)); @@ -70,7 +69,8 @@ Bool PoolClassCheck(PoolClass klass) CHECKL(FUNCHECK(klass->freeSize)); /* Check that pool classes overide sets of related methods. */ - CHECKL((klass->init == PoolAbsInit) == (klass->finish == PoolAbsFinish)); + CHECKL((klass->init == PoolAbsInit) == + (klass->protocol.finish == PoolAbsFinish)); CHECKL((klass->bufferFill == PoolNoBufferFill) == (klass->bufferEmpty == PoolNoBufferEmpty)); CHECKL((klass->framePush == PoolNoFramePush) == @@ -196,7 +196,7 @@ failControlAlloc: void PoolFinish(Pool pool) { AVERT(Pool, pool); - Method(Pool, pool, finish)(pool); + Method(Inst, pool, finish)(MustBeA(Inst, pool)); } diff --git a/mps/code/poolabs.c b/mps/code/poolabs.c index a25c3b814f1..eb360e687b9 100644 --- a/mps/code/poolabs.c +++ b/mps/code/poolabs.c @@ -154,8 +154,10 @@ Res PoolAbsInit(Pool pool, Arena arena, PoolClass klass, ArgList args) /* PoolAbsFinish -- finish an abstract pool instance */ -void PoolAbsFinish(Pool pool) +void PoolAbsFinish(Inst inst) { + Pool pool = MustBeA(AbstractPool, inst); + /* Detach the pool from the arena and format, and unsig it. */ RingRemove(PoolArenaRing(pool)); @@ -186,11 +188,11 @@ DEFINE_CLASS(Pool, AbstractPool, klass) { INHERIT_CLASS(&klass->protocol, AbstractPool, Inst); klass->protocol.describe = PoolAbsDescribe; + klass->protocol.finish = PoolAbsFinish; klass->size = sizeof(PoolStruct); klass->attr = 0; klass->varargs = ArgTrivVarargs; klass->init = PoolAbsInit; - klass->finish = PoolAbsFinish; klass->alloc = PoolNoAlloc; klass->free = PoolNoFree; klass->bufferFill = PoolNoBufferFill; diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c index 7ecc80ecaf3..0cf0f9c03d3 100644 --- a/mps/code/poolamc.c +++ b/mps/code/poolamc.c @@ -799,7 +799,7 @@ failGenAlloc: } ControlFree(arena, amc->gen, genArraySize); failGensAlloc: - PoolAbsFinish(pool); + NextMethod(Inst, AMCZPool, finish)(MustBeA(Inst, pool)); return res; } @@ -824,8 +824,9 @@ static Res AMCZInit(Pool pool, Arena arena, PoolClass klass, ArgList args) * * See . */ -static void AMCFinish(Pool pool) +static void AMCFinish(Inst inst) { + Pool pool = MustBeA(AbstractPool, inst); AMC amc = MustBeA(AMCZPool, pool); Ring ring; Ring node, nextNode; @@ -868,7 +869,8 @@ static void AMCFinish(Pool pool) } amc->sig = SigInvalid; - PoolAbsFinish(pool); + + NextMethod(Inst, AMCZPool, finish)(inst); } @@ -2023,11 +2025,11 @@ DEFINE_CLASS(Pool, AMCZPool, klass) PoolClassMixInFormat(klass); PoolClassMixInCollect(klass); klass->protocol.describe = AMCDescribe; + klass->protocol.finish = AMCFinish; klass->size = sizeof(AMCStruct); klass->attr |= AttrMOVINGGC; klass->varargs = AMCVarargs; klass->init = AMCZInit; - klass->finish = AMCFinish; klass->bufferFill = AMCBufferFill; klass->bufferEmpty = AMCBufferEmpty; klass->whiten = AMCWhiten; diff --git a/mps/code/poolams.c b/mps/code/poolams.c index 38600642d77..17679639dd8 100644 --- a/mps/code/poolams.c +++ b/mps/code/poolams.c @@ -836,7 +836,7 @@ static Res AMSInit(Pool pool, Arena arena, PoolClass klass, ArgList args) return ResOK; failGenInit: - PoolAbsFinish(pool); + NextMethod(Inst, AMSPool, finish)(MustBeA(Inst, pool)); failAbsInit: return res; } @@ -847,12 +847,11 @@ failAbsInit: * Destroys all the segs in the pool. Can't invalidate the AMS until * we've destroyed all the segments, as it may be checked. */ -void AMSFinish(Pool pool) +void AMSFinish(Inst inst) { - AMS ams; + Pool pool = MustBeA(AbstractPool, inst); + AMS ams = MustBeA(AMSPool, pool); - AVERT(Pool, pool); - ams = PoolAMS(pool); AVERT(AMS, ams); ams->segsDestroy(ams); @@ -861,7 +860,8 @@ void AMSFinish(Pool pool) RingFinish(&ams->segRing); PoolGenFinish(ams->pgen); ams->pgen = NULL; - PoolAbsFinish(pool); + + NextMethod(Inst, AMSPool, finish)(inst); } @@ -1744,10 +1744,10 @@ DEFINE_CLASS(Pool, AMSPool, klass) INHERIT_CLASS(klass, AMSPool, AbstractCollectPool); PoolClassMixInFormat(klass); klass->protocol.describe = AMSDescribe; + klass->protocol.finish = AMSFinish; klass->size = sizeof(AMSStruct); klass->varargs = AMSVarargs; klass->init = AMSInit; - klass->finish = AMSFinish; klass->bufferClass = RankBufClassGet; klass->bufferFill = AMSBufferFill; klass->bufferEmpty = AMSBufferEmpty; diff --git a/mps/code/poolams.h b/mps/code/poolams.h index e1dd091168c..28fd829f127 100644 --- a/mps/code/poolams.h +++ b/mps/code/poolams.h @@ -172,7 +172,7 @@ typedef struct AMSSegStruct { extern Res AMSInitInternal(AMS ams, Arena arena, PoolClass klass, Chain chain, unsigned gen, Bool shareAllocTable, ArgList args); -extern void AMSFinish(Pool pool); +extern void AMSFinish(Inst inst); extern Bool AMSCheck(AMS ams); extern Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg); diff --git a/mps/code/poolawl.c b/mps/code/poolawl.c index 22e8e075b64..2287432ecc7 100644 --- a/mps/code/poolawl.c +++ b/mps/code/poolawl.c @@ -572,7 +572,7 @@ static Res AWLInit(Pool pool, Arena arena, PoolClass klass, ArgList args) return ResOK; failGenInit: - PoolAbsFinish(pool); + NextMethod(Inst, AWLPool, finish)(MustBeA(Inst, pool)); failAbsInit: AVER(res != ResOK); return res; @@ -581,8 +581,9 @@ failAbsInit: /* AWLFinish -- finish an AWL pool */ -static void AWLFinish(Pool pool) +static void AWLFinish(Inst inst) { + Pool pool = MustBeA(AbstractPool, inst); AWL awl = MustBeA(AWLPool, pool); Ring ring, node, nextNode; @@ -601,7 +602,8 @@ static void AWLFinish(Pool pool) } awl->sig = SigInvalid; PoolGenFinish(awl->pgen); - PoolAbsFinish(pool); + + NextMethod(Inst, AWLPool, finish)(inst); } @@ -1215,10 +1217,10 @@ DEFINE_CLASS(Pool, AWLPool, klass) { INHERIT_CLASS(klass, AWLPool, AbstractCollectPool); PoolClassMixInFormat(klass); + klass->protocol.finish = AWLFinish; klass->size = sizeof(AWLPoolStruct); klass->varargs = AWLVarargs; klass->init = AWLInit; - klass->finish = AWLFinish; klass->bufferClass = RankBufClassGet; klass->bufferFill = AWLBufferFill; klass->bufferEmpty = AWLBufferEmpty; diff --git a/mps/code/poollo.c b/mps/code/poollo.c index f20c54a9170..338d2c18618 100644 --- a/mps/code/poollo.c +++ b/mps/code/poollo.c @@ -502,7 +502,7 @@ static Res LOInit(Pool pool, Arena arena, PoolClass klass, ArgList args) return ResOK; failGenInit: - PoolAbsFinish(pool); + NextMethod(Inst, LOPool, finish)(MustBeA(Inst, pool)); failAbsInit: AVER(res != ResOK); return res; @@ -511,8 +511,9 @@ failAbsInit: /* LOFinish -- finish an LO pool */ -static void LOFinish(Pool pool) +static void LOFinish(Inst inst) { + Pool pool = MustBeA(AbstractPool, inst); LO lo = MustBeA(LOPool, pool); Ring node, nextNode; @@ -531,7 +532,8 @@ static void LOFinish(Pool pool) PoolGenFinish(lo->pgen); lo->sig = SigInvalid; - PoolAbsFinish(pool); + + NextMethod(Inst, LOPool, finish)(inst); } @@ -784,10 +786,10 @@ DEFINE_CLASS(Pool, LOPool, klass) INHERIT_CLASS(klass, LOPool, AbstractSegBufPool); PoolClassMixInFormat(klass); PoolClassMixInCollect(klass); + klass->protocol.finish = LOFinish; klass->size = sizeof(LOStruct); klass->varargs = LOVarargs; klass->init = LOInit; - klass->finish = LOFinish; klass->bufferFill = LOBufferFill; klass->bufferEmpty = LOBufferEmpty; klass->whiten = LOWhiten; diff --git a/mps/code/poolmfs.c b/mps/code/poolmfs.c index 688258db696..7b5443995b3 100644 --- a/mps/code/poolmfs.c +++ b/mps/code/poolmfs.c @@ -153,14 +153,16 @@ static void MFSTractFreeVisitor(Pool pool, Addr base, Size size, } -static void MFSFinish(Pool pool) +static void MFSFinish(Inst inst) { + Pool pool = MustBeA(AbstractPool, inst); MFS mfs = MustBeA(MFSPool, pool); MFSFinishTracts(pool, MFSTractFreeVisitor, UNUSED_POINTER); mfs->sig = SigInvalid; - PoolAbsFinish(pool); + + NextMethod(Inst, MFSPool, finish)(inst); } @@ -338,10 +340,10 @@ DEFINE_CLASS(Pool, MFSPool, klass) { INHERIT_CLASS(klass, MFSPool, AbstractPool); klass->protocol.describe = MFSDescribe; + klass->protocol.finish = MFSFinish; klass->size = sizeof(MFSStruct); klass->varargs = MFSVarargs; klass->init = MFSInit; - klass->finish = MFSFinish; klass->alloc = MFSAlloc; klass->free = MFSFree; klass->totalSize = MFSTotalSize; diff --git a/mps/code/poolmrg.c b/mps/code/poolmrg.c index 5d29dcc792f..f52715fe536 100644 --- a/mps/code/poolmrg.c +++ b/mps/code/poolmrg.c @@ -637,8 +637,9 @@ static Res MRGInit(Pool pool, Arena arena, PoolClass klass, ArgList args) /* MRGFinish -- finish a MRG pool */ -static void MRGFinish(Pool pool) +static void MRGFinish(Inst inst) { + Pool pool = MustBeA(AbstractPool, inst); MRG mrg = MustBeA(MRGPool, pool); Ring node, nextNode; @@ -676,7 +677,7 @@ static void MRGFinish(Pool pool) RingFinish(&mrg->refRing); /* */ - PoolAbsFinish(pool); + NextMethod(Inst, MRGPool, finish)(inst); } @@ -842,9 +843,9 @@ DEFINE_CLASS(Pool, MRGPool, klass) { INHERIT_CLASS(klass, MRGPool, AbstractPool); klass->protocol.describe = MRGDescribe; + klass->protocol.finish = MRGFinish; klass->size = sizeof(MRGStruct); klass->init = MRGInit; - klass->finish = MRGFinish; klass->grey = PoolTrivGrey; klass->blacken = PoolTrivBlacken; klass->scan = MRGScan; diff --git a/mps/code/poolmv.c b/mps/code/poolmv.c index 0ff6c0bc455..06fad8fb398 100644 --- a/mps/code/poolmv.c +++ b/mps/code/poolmv.c @@ -305,21 +305,20 @@ static Res MVInit(Pool pool, Arena arena, PoolClass klass, ArgList args) failSpanPoolInit: PoolFinish(mvBlockPool(mv)); failBlockPoolInit: - PoolAbsFinish(pool); + NextMethod(Inst, MVPool, finish)(MustBeA(Inst, pool)); return res; } /* MVFinish -- finish method for class MV */ -static void MVFinish(Pool pool) +static void MVFinish(Inst inst) { - MV mv; + Pool pool = MustBeA(AbstractPool, inst); + MV mv = MustBeA(MVPool, pool); Ring spans, node = NULL, nextNode; /* gcc whinge stop */ MVSpan span; - AVERT(Pool, pool); - mv = PoolMV(pool); AVERT(MV, mv); /* Destroy all the spans attached to the pool. */ @@ -335,7 +334,7 @@ static void MVFinish(Pool pool) PoolFinish(mvBlockPool(mv)); PoolFinish(mvSpanPool(mv)); - PoolAbsFinish(pool); + NextMethod(Inst, MVPool, finish)(inst); } @@ -866,10 +865,10 @@ DEFINE_CLASS(Pool, MVPool, klass) { INHERIT_CLASS(klass, MVPool, AbstractBufferPool); klass->protocol.describe = MVDescribe; + klass->protocol.finish = MVFinish; klass->size = sizeof(MVStruct); klass->varargs = MVVarargs; klass->init = MVInit; - klass->finish = MVFinish; klass->alloc = MVAlloc; klass->free = MVFree; klass->totalSize = MVTotalSize; diff --git a/mps/code/poolmv2.c b/mps/code/poolmv2.c index fca7e43288d..380b67c1811 100644 --- a/mps/code/poolmv2.c +++ b/mps/code/poolmv2.c @@ -33,7 +33,7 @@ typedef struct MVTStruct *MVT; static void MVTVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs); static Res MVTInit(Pool pool, Arena arena, PoolClass klass, ArgList arg); static Bool MVTCheck(MVT mvt); -static void MVTFinish(Pool pool); +static void MVTFinish(Inst inst); static Res MVTBufferFill(Addr *baseReturn, Addr *limitReturn, Pool pool, Buffer buffer, Size minSize); static void MVTBufferEmpty(Pool pool, Buffer buffer, Addr base, Addr limit); @@ -140,10 +140,10 @@ DEFINE_CLASS(Pool, MVTPool, klass) { INHERIT_CLASS(klass, MVTPool, AbstractBufferPool); klass->protocol.describe = MVTDescribe; + klass->protocol.finish = MVTFinish; klass->size = sizeof(MVTStruct); klass->varargs = MVTVarargs; klass->init = MVTInit; - klass->finish = MVTFinish; klass->free = MVTFree; klass->bufferFill = MVTBufferFill; klass->bufferEmpty = MVTBufferEmpty; @@ -376,7 +376,7 @@ failFreeLandInit: failFreeSecondaryInit: LandFinish(MVTFreePrimary(mvt)); failFreePrimaryInit: - PoolAbsFinish(pool); + NextMethod(Inst, MVTPool, finish)(MustBeA(Inst, pool)); failAbsInit: AVER(res != ResOK); return res; @@ -421,18 +421,15 @@ static Bool MVTCheck(MVT mvt) /* MVTFinish -- finish an MVT pool */ -static void MVTFinish(Pool pool) +static void MVTFinish(Inst inst) { - MVT mvt; - Arena arena; + Pool pool = MustBeA(AbstractPool, inst); + MVT mvt = MustBeA(MVTPool, pool); + Arena arena = PoolArena(pool); Ring ring; Ring node, nextNode; - AVERT(Pool, pool); - mvt = PoolMVT(pool); AVERT(MVT, mvt); - arena = PoolArena(pool); - AVERT(Arena, arena); mvt->sig = SigInvalid; @@ -450,7 +447,8 @@ static void MVTFinish(Pool pool) LandFinish(MVTFreeLand(mvt)); LandFinish(MVTFreeSecondary(mvt)); LandFinish(MVTFreePrimary(mvt)); - PoolAbsFinish(pool); + + NextMethod(Inst, MVTPool, finish)(inst); } diff --git a/mps/code/poolmvff.c b/mps/code/poolmvff.c index 5424d70fb99..cbf55ee1df0 100644 --- a/mps/code/poolmvff.c +++ b/mps/code/poolmvff.c @@ -578,7 +578,7 @@ failFreePrimaryInit: failTotalLandInit: PoolFinish(MVFFBlockPool(mvff)); failBlockPoolInit: - PoolAbsFinish(pool); + NextMethod(Inst, MVFFPool, finish)(MustBeA(Inst, pool)); failAbsInit: AVER(res != ResOK); return res; @@ -604,13 +604,12 @@ static Bool mvffFinishVisitor(Bool *deleteReturn, Land land, Range range, return TRUE; } -static void MVFFFinish(Pool pool) +static void MVFFFinish(Inst inst) { - MVFF mvff; + Pool pool = MustBeA(AbstractPool, inst); + MVFF mvff = MustBeA(MVFFPool, pool); Bool b; - AVERT(Pool, pool); - mvff = PoolMVFF(pool); AVERT(MVFF, mvff); mvff->sig = SigInvalid; @@ -623,7 +622,7 @@ static void MVFFFinish(Pool pool) LandFinish(MVFFFreePrimary(mvff)); LandFinish(MVFFTotalLand(mvff)); PoolFinish(MVFFBlockPool(mvff)); - PoolAbsFinish(pool); + NextMethod(Inst, MVFFPool, finish)(inst); } @@ -724,10 +723,10 @@ DEFINE_CLASS(Pool, MVFFPool, klass) INHERIT_CLASS(klass, MVFFPool, AbstractPool); PoolClassMixInBuffer(klass); klass->protocol.describe = MVFFDescribe; + klass->protocol.finish = MVFFFinish; klass->size = sizeof(MVFFStruct); klass->varargs = MVFFVarargs; klass->init = MVFFInit; - klass->finish = MVFFFinish; klass->alloc = MVFFAlloc; klass->free = MVFFFree; klass->bufferFill = MVFFBufferFill; diff --git a/mps/code/pooln.c b/mps/code/pooln.c index 7111236183a..af273c4ce47 100644 --- a/mps/code/pooln.c +++ b/mps/code/pooln.c @@ -65,14 +65,15 @@ failAbsInit: /* NFinish -- finish method for class N */ -static void NFinish(Pool pool) +static void NFinish(Inst inst) { + Pool pool = MustBeA(AbstractPool, inst); PoolN poolN = MustBeA(NPool, pool); /* Finish pool-specific structures. */ UNUSED(poolN); - PoolAbsFinish(pool); + NextMethod(Inst, NPool, finish)(inst); } @@ -257,10 +258,10 @@ DEFINE_CLASS(Pool, NPool, klass) { INHERIT_CLASS(klass, NPool, AbstractPool); klass->protocol.describe = NDescribe; + klass->protocol.finish = NFinish; klass->size = sizeof(PoolNStruct); klass->attr |= AttrGC; klass->init = NInit; - klass->finish = NFinish; klass->alloc = NAlloc; klass->free = NFree; klass->bufferFill = NBufferFill; diff --git a/mps/code/poolsnc.c b/mps/code/poolsnc.c index db0cb5f6173..ff0aa62dc76 100644 --- a/mps/code/poolsnc.c +++ b/mps/code/poolsnc.c @@ -380,13 +380,12 @@ static Res SNCInit(Pool pool, Arena arena, PoolClass klass, ArgList args) /* SNCFinish -- finish an SNC pool */ -static void SNCFinish(Pool pool) +static void SNCFinish(Inst inst) { - SNC snc; + Pool pool = MustBeA(AbstractPool, inst); + SNC snc = MustBeA(SNCPool, pool); Ring ring, node, nextNode; - AVERT(Pool, pool); - snc = PoolSNC(pool); AVERT(SNC, snc); ring = &pool->segRing; @@ -396,7 +395,7 @@ static void SNCFinish(Pool pool) SegFree(seg); } - PoolAbsFinish(pool); + NextMethod(Inst, SNCPool, finish)(inst); } @@ -668,10 +667,10 @@ DEFINE_CLASS(Pool, SNCPool, klass) { INHERIT_CLASS(klass, SNCPool, AbstractScanPool); PoolClassMixInFormat(klass); + klass->protocol.finish = SNCFinish; klass->size = sizeof(SNCStruct); klass->varargs = SNCVarargs; klass->init = SNCInit; - klass->finish = SNCFinish; klass->bufferFill = SNCBufferFill; klass->bufferEmpty = SNCBufferEmpty; klass->scan = SNCScan; diff --git a/mps/code/segsmss.c b/mps/code/segsmss.c index db26cfafd4f..9162deba674 100644 --- a/mps/code/segsmss.c +++ b/mps/code/segsmss.c @@ -344,14 +344,15 @@ static Res AMSTInit(Pool pool, Arena arena, PoolClass klass, ArgList args) /* AMSTFinish -- the pool class finish method */ -static void AMSTFinish(Pool pool) +static void AMSTFinish(Inst inst) { - AMST amst; + Pool pool = MustBeA(AbstractPool, inst); + AMST amst = MustBeA(AMSTPool, pool); - AVERT(Pool, pool); - amst = PoolAMST(pool); AVERT(AMST, amst); + amst->sig = SigInvalid; + printf("\nDestroying pool, having performed:\n"); printf(" %"PRIuLONGEST" splits (S)\n", (ulongest_t)amst->splits); printf(" %"PRIuLONGEST" merges (M)\n", (ulongest_t)amst->merges); @@ -361,8 +362,7 @@ static void AMSTFinish(Pool pool) printf(" %"PRIuLONGEST" buffered splits (C)\n", (ulongest_t)amst->bsplits); printf(" %"PRIuLONGEST" buffered merges (J)\n", (ulongest_t)amst->bmerges); - AMSFinish(pool); - amst->sig = SigInvalid; + NextMethod(Inst, AMSTPool, finish)(inst); } @@ -650,9 +650,9 @@ static void AMSTStressBufferedSeg(Seg seg, Buffer buffer) DEFINE_CLASS(Pool, AMSTPool, klass) { INHERIT_CLASS(klass, AMSTPool, AMSPool); + klass->protocol.finish = AMSTFinish; klass->size = sizeof(AMSTStruct); klass->init = AMSTInit; - klass->finish = AMSTFinish; klass->bufferFill = AMSTBufferFill; } From ea53ac476ea06b873b6d91fcd24d15357eea539b Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sat, 23 Apr 2016 13:28:52 +0100 Subject: [PATCH 20/52] Converting land finish methods to specialize instfinish. Copied from Perforce Change: 191606 ServerID: perforce.ravenbrook.com --- mps/code/cbs.c | 7 ++++--- mps/code/failover.c | 7 ++++--- mps/code/freelist.c | 7 ++++--- mps/code/land.c | 10 +++++----- mps/code/mpmst.h | 1 - 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/mps/code/cbs.c b/mps/code/cbs.c index c081ed61610..abcce81dfb3 100644 --- a/mps/code/cbs.c +++ b/mps/code/cbs.c @@ -289,8 +289,9 @@ static Res cbsInitZoned(Land land, Arena arena, Align alignment, ArgList args) * See . */ -static void cbsFinish(Land land) +static void cbsFinish(Inst inst) { + Land land = MustBeA(Land, inst); CBS cbs = MustBeA(CBS, land); METER_EMIT(&cbs->treeSearch); @@ -301,7 +302,7 @@ static void cbsFinish(Land land) if (cbs->ownPool) PoolDestroy(cbsBlockPool(cbs)); - NextMethod(Land, CBS, finish)(land); + NextMethod(Inst, CBS, finish)(inst); } @@ -1133,9 +1134,9 @@ static Res cbsDescribe(Land land, mps_lib_FILE *stream, Count depth) DEFINE_CLASS(Land, CBS, klass) { INHERIT_CLASS(klass, CBS, Land); + klass->protocol.finish = cbsFinish; klass->size = sizeof(CBSStruct); klass->init = cbsInit; - klass->finish = cbsFinish; klass->sizeMethod = cbsSize; klass->insert = cbsInsert; klass->delete = cbsDelete; diff --git a/mps/code/failover.c b/mps/code/failover.c index a48a6d04f66..ecabf01c62b 100644 --- a/mps/code/failover.c +++ b/mps/code/failover.c @@ -52,11 +52,12 @@ static Res failoverInit(Land land, Arena arena, Align alignment, ArgList args) } -static void failoverFinish(Land land) +static void failoverFinish(Inst inst) { + Land land = MustBeA(Land, inst); Failover fo = MustBeA(Failover, land); fo->sig = SigInvalid; - NextMethod(Land, Failover, finish)(land); + NextMethod(Inst, Failover, finish)(inst); } @@ -272,9 +273,9 @@ static Res failoverDescribe(Land land, mps_lib_FILE *stream, Count depth) DEFINE_CLASS(Land, Failover, klass) { INHERIT_CLASS(klass, Failover, Land); + klass->protocol.finish = failoverFinish; klass->size = sizeof(FailoverStruct); klass->init = failoverInit; - klass->finish = failoverFinish; klass->sizeMethod = failoverSize; klass->insert = failoverInsert; klass->delete = failoverDelete; diff --git a/mps/code/freelist.c b/mps/code/freelist.c index 7a58032f508..f337824882b 100644 --- a/mps/code/freelist.c +++ b/mps/code/freelist.c @@ -212,12 +212,13 @@ static Res freelistInit(Land land, Arena arena, Align alignment, ArgList args) } -static void freelistFinish(Land land) +static void freelistFinish(Inst inst) { + Land land = MustBeA(Land, inst); Freelist fl = MustBeA(Freelist, land); fl->sig = SigInvalid; fl->list = freelistEND; - NextMethod(Land, Freelist, finish)(land); + NextMethod(Inst, Freelist, finish)(inst); } @@ -779,9 +780,9 @@ static Res freelistDescribe(Land land, mps_lib_FILE *stream, Count depth) DEFINE_CLASS(Land, Freelist, klass) { INHERIT_CLASS(klass, Freelist, Land); + klass->protocol.finish = freelistFinish; klass->size = sizeof(FreelistStruct); klass->init = freelistInit; - klass->finish = freelistFinish; klass->sizeMethod = freelistSize; klass->insert = freelistInsert; klass->delete = freelistDelete; diff --git a/mps/code/land.c b/mps/code/land.c index 3d2bb84bdec..b704af11783 100644 --- a/mps/code/land.c +++ b/mps/code/land.c @@ -90,11 +90,12 @@ static Res LandAbsInit(Land land, Arena arena, Align alignment, ArgList args) return ResOK; } -static void LandAbsFinish(Land land) +static void LandAbsFinish(Inst inst) { + Land land = MustBeA(Land, inst); AVERC(Land, land); land->sig = SigInvalid; - InstFinish(CouldBeA(Inst, land)); + NextMethod(Inst, Land, finish)(inst); } @@ -183,7 +184,7 @@ void LandFinish(Land land) AVERC(Land, land); landEnter(land); - Method(Land, land, finish)(land); + Method(Inst, land, finish)(MustBeA(Inst, land)); } @@ -444,7 +445,6 @@ Bool LandClassCheck(LandClass klass) CHECKL(InstClassCheck(&klass->protocol)); CHECKL(klass->size >= sizeof(LandStruct)); CHECKL(FUNCHECK(klass->init)); - CHECKL(FUNCHECK(klass->finish)); CHECKL(FUNCHECK(klass->insert)); CHECKL(FUNCHECK(klass->delete)); CHECKL(FUNCHECK(klass->findFirst)); @@ -575,10 +575,10 @@ DEFINE_CLASS(Inst, LandClass, klass) DEFINE_CLASS(Land, Land, klass) { INHERIT_CLASS(&klass->protocol, Land, Inst); + klass->protocol.finish = LandAbsFinish; klass->size = sizeof(LandStruct); klass->init = LandAbsInit; klass->sizeMethod = landNoSize; - klass->finish = LandAbsFinish; klass->insert = landNoInsert; klass->delete = landNoDelete; klass->iterate = landNoIterate; diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index 19b3cae7983..a271d7b010b 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -575,7 +575,6 @@ typedef struct LandClassStruct { size_t size; /* size of outer structure */ LandSizeMethod sizeMethod; /* total size of ranges in land */ LandInitMethod init; /* initialize the land */ - LandFinishMethod finish; /* finish the land */ LandInsertMethod insert; /* insert a range into the land */ LandDeleteMethod delete; /* delete a range from the land */ LandIterateMethod iterate; /* iterate over ranges in the land */ From ed1ecb1bf59f00f73c3322eea7be20d96fcdcbd0 Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sat, 23 Apr 2016 13:35:20 +0100 Subject: [PATCH 21/52] Converting land describe methods to specialize instdescribe. Copied from Perforce Change: 191607 ServerID: perforce.ravenbrook.com --- mps/code/cbs.c | 7 ++++--- mps/code/failover.c | 7 ++++--- mps/code/freelist.c | 7 ++++--- mps/code/land.c | 10 +++++----- mps/code/mpmst.h | 1 - 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/mps/code/cbs.c b/mps/code/cbs.c index abcce81dfb3..80750e66c34 100644 --- a/mps/code/cbs.c +++ b/mps/code/cbs.c @@ -1090,8 +1090,9 @@ fail: * See . */ -static Res cbsDescribe(Land land, mps_lib_FILE *stream, Count depth) +static Res cbsDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { + Land land = CouldBeA(Land, inst); CBS cbs = CouldBeA(CBS, land); Res res; Res (*describe)(Tree, mps_lib_FILE *); @@ -1101,7 +1102,7 @@ static Res cbsDescribe(Land land, mps_lib_FILE *stream, Count depth) if (stream == NULL) return ResPARAM; - res = NextMethod(Land, CBS, describe)(land, stream, depth); + res = NextMethod(Inst, CBS, describe)(inst, stream, depth); if (res != ResOK) return res; @@ -1134,6 +1135,7 @@ static Res cbsDescribe(Land land, mps_lib_FILE *stream, Count depth) DEFINE_CLASS(Land, CBS, klass) { INHERIT_CLASS(klass, CBS, Land); + klass->protocol.describe = cbsDescribe; klass->protocol.finish = cbsFinish; klass->size = sizeof(CBSStruct); klass->init = cbsInit; @@ -1146,7 +1148,6 @@ DEFINE_CLASS(Land, CBS, klass) klass->findLast = cbsFindLast; klass->findLargest = cbsFindLargest; klass->findInZones = cbsFindInZones; - klass->describe = cbsDescribe; } DEFINE_CLASS(Land, CBSFast, klass) diff --git a/mps/code/failover.c b/mps/code/failover.c index ecabf01c62b..0a6e344a537 100644 --- a/mps/code/failover.c +++ b/mps/code/failover.c @@ -241,8 +241,9 @@ static Bool failoverFindInZones(Bool *foundReturn, Range rangeReturn, Range oldR } -static Res failoverDescribe(Land land, mps_lib_FILE *stream, Count depth) +static Res failoverDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { + Land land = CouldBeA(Land, inst); Failover fo = CouldBeA(Failover, land); LandClass primaryClass, secondaryClass; Res res; @@ -252,7 +253,7 @@ static Res failoverDescribe(Land land, mps_lib_FILE *stream, Count depth) if (stream == NULL) return ResPARAM; - res = NextMethod(Land, Failover, describe)(land, stream, depth); + res = NextMethod(Inst, Failover, describe)(inst, stream, depth); if (res != ResOK) return res; @@ -273,6 +274,7 @@ static Res failoverDescribe(Land land, mps_lib_FILE *stream, Count depth) DEFINE_CLASS(Land, Failover, klass) { INHERIT_CLASS(klass, Failover, Land); + klass->protocol.describe = failoverDescribe; klass->protocol.finish = failoverFinish; klass->size = sizeof(FailoverStruct); klass->init = failoverInit; @@ -284,7 +286,6 @@ DEFINE_CLASS(Land, Failover, klass) klass->findLast = failoverFindLast; klass->findLargest = failoverFindLargest; klass->findInZones = failoverFindInZones; - klass->describe = failoverDescribe; } diff --git a/mps/code/freelist.c b/mps/code/freelist.c index f337824882b..e01f78edfa3 100644 --- a/mps/code/freelist.c +++ b/mps/code/freelist.c @@ -746,8 +746,9 @@ static Bool freelistDescribeVisitor(Land land, Range range, } -static Res freelistDescribe(Land land, mps_lib_FILE *stream, Count depth) +static Res freelistDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { + Land land = CouldBeA(Land, inst); Freelist fl = CouldBeA(Freelist, land); Res res; Bool b; @@ -758,7 +759,7 @@ static Res freelistDescribe(Land land, mps_lib_FILE *stream, Count depth) if (stream == NULL) return ResPARAM; - res = NextMethod(Land, Freelist, describe)(land, stream, depth); + res = NextMethod(Inst, Freelist, describe)(inst, stream, depth); if (res != ResOK) return res; @@ -780,6 +781,7 @@ static Res freelistDescribe(Land land, mps_lib_FILE *stream, Count depth) DEFINE_CLASS(Land, Freelist, klass) { INHERIT_CLASS(klass, Freelist, Land); + klass->protocol.describe = freelistDescribe; klass->protocol.finish = freelistFinish; klass->size = sizeof(FreelistStruct); klass->init = freelistInit; @@ -792,7 +794,6 @@ DEFINE_CLASS(Land, Freelist, klass) klass->findLast = freelistFindLast; klass->findLargest = freelistFindLargest; klass->findInZones = freelistFindInZones; - klass->describe = freelistDescribe; } diff --git a/mps/code/land.c b/mps/code/land.c index b704af11783..1a13ec39fb6 100644 --- a/mps/code/land.c +++ b/mps/code/land.c @@ -391,7 +391,7 @@ Res LandFindInZones(Bool *foundReturn, Range rangeReturn, Range oldRangeReturn, Res LandDescribe(Land land, mps_lib_FILE *stream, Count depth) { - return Method(Land, land, describe)(land, stream, depth); + return Method(Inst, land, describe)(MustBeA(Inst, land), stream, depth); } @@ -451,7 +451,6 @@ Bool LandClassCheck(LandClass klass) CHECKL(FUNCHECK(klass->findLast)); CHECKL(FUNCHECK(klass->findLargest)); CHECKL(FUNCHECK(klass->findInZones)); - CHECKL(FUNCHECK(klass->describe)); CHECKS(LandClass, klass); return TRUE; } @@ -543,8 +542,9 @@ static Res landNoFindInZones(Bool *foundReturn, Range rangeReturn, Range oldRang return ResUNIMPL; } -static Res LandAbsDescribe(Land land, mps_lib_FILE *stream, Count depth) +static Res LandAbsDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { + Land land = CouldBeA(Land, inst); LandClass klass; Res res; @@ -553,7 +553,7 @@ static Res LandAbsDescribe(Land land, mps_lib_FILE *stream, Count depth) if (stream == NULL) return ResPARAM; - res = InstDescribe(CouldBeA(Inst, land), stream, depth); + res = NextMethod(Inst, Land, describe)(inst, stream, depth); if (res != ResOK) return res; @@ -575,6 +575,7 @@ DEFINE_CLASS(Inst, LandClass, klass) DEFINE_CLASS(Land, Land, klass) { INHERIT_CLASS(&klass->protocol, Land, Inst); + klass->protocol.describe = LandAbsDescribe; klass->protocol.finish = LandAbsFinish; klass->size = sizeof(LandStruct); klass->init = LandAbsInit; @@ -587,7 +588,6 @@ DEFINE_CLASS(Land, Land, klass) klass->findLast = landNoFind; klass->findLargest = landNoFind; klass->findInZones = landNoFindInZones; - klass->describe = LandAbsDescribe; klass->sig = LandClassSig; } diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index a271d7b010b..90f4d260a04 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -583,7 +583,6 @@ typedef struct LandClassStruct { LandFindMethod findLast; /* find last range of given size */ LandFindMethod findLargest; /* find largest range */ LandFindInZonesMethod findInZones; /* find first range of given size in zone set */ - LandDescribeMethod describe; /* describe the land */ Sig sig; /* .class.end-sig */ } LandClassStruct; From a241b44f8cb25bd440b40ad3262f8f203330821d Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sat, 23 Apr 2016 15:34:32 +0100 Subject: [PATCH 22/52] Converting buffer finish and describe methods to specialize instfinish and instdescribe. Copied from Perforce Change: 191608 ServerID: perforce.ravenbrook.com --- mps/code/buffer.c | 35 ++++++++++++++++++----------------- mps/code/mpmst.h | 2 -- mps/code/mpmtypes.h | 7 ------- mps/code/poolamc.c | 7 ++++--- mps/code/poolsnc.c | 7 ++++--- 5 files changed, 26 insertions(+), 32 deletions(-) diff --git a/mps/code/buffer.c b/mps/code/buffer.c index a35b7b55a12..f87dbf494ac 100644 --- a/mps/code/buffer.c +++ b/mps/code/buffer.c @@ -119,8 +119,9 @@ Bool BufferCheck(Buffer buffer) * * See for structure definitions. */ -static Res BufferAbsDescribe(Buffer buffer, mps_lib_FILE *stream, Count depth) +static Res BufferAbsDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { + Buffer buffer = CouldBeA(Buffer, inst); Res res; if (!TESTC(Buffer, buffer)) @@ -128,7 +129,7 @@ static Res BufferAbsDescribe(Buffer buffer, mps_lib_FILE *stream, Count depth) if (stream == NULL) return ResPARAM; - res = InstDescribe(CouldBeA(Inst, buffer), stream, depth); + res = NextMethod(Inst, Buffer, describe)(inst, stream, depth); if (res != ResOK) return res; @@ -158,7 +159,7 @@ static Res BufferAbsDescribe(Buffer buffer, mps_lib_FILE *stream, Count depth) Res BufferDescribe(Buffer buffer, mps_lib_FILE *stream, Count depth) { - return Method(Buffer, buffer, describe)(buffer, stream, depth); + return Method(Inst, buffer, describe)(MustBeA(Inst, buffer), stream, depth); } @@ -332,8 +333,9 @@ void BufferDestroy(Buffer buffer) /* BufferFinish -- finish an allocation buffer */ -static void BufferAbsFinish(Buffer buffer) +static void BufferAbsFinish(Inst inst) { + Buffer buffer = MustBeA(Buffer, inst); AVERT(Buffer, buffer); AVER(BufferIsReset(buffer)); @@ -353,9 +355,9 @@ void BufferFinish(Buffer buffer) AVERT(Buffer, buffer); AVER(BufferIsReady(buffer)); - BufferDetach(buffer, BufferPool(buffer)); + BufferDetach(buffer, BufferPool(buffer)); /* FIXME: Should be in BufferAbsFinish? */ - Method(Buffer, buffer, finish)(buffer); + Method(Inst, buffer, finish)(MustBeA(Inst, buffer)); } @@ -1006,14 +1008,12 @@ Bool BufferClassCheck(BufferClass klass) CHECKL(klass->size >= sizeof(BufferStruct)); CHECKL(FUNCHECK(klass->varargs)); CHECKL(FUNCHECK(klass->init)); - CHECKL(FUNCHECK(klass->finish)); CHECKL(FUNCHECK(klass->attach)); CHECKL(FUNCHECK(klass->detach)); CHECKL(FUNCHECK(klass->seg)); CHECKL(FUNCHECK(klass->rankSet)); CHECKL(FUNCHECK(klass->setRankSet)); CHECKL(FUNCHECK(klass->reassignSeg)); - CHECKL(FUNCHECK(klass->describe)); CHECKS(BufferClass, klass); return TRUE; } @@ -1031,13 +1031,13 @@ DEFINE_CLASS(Inst, BufferClass, klass) DEFINE_CLASS(Buffer, Buffer, klass) { INHERIT_CLASS(&klass->protocol, Buffer, Inst); + klass->protocol.finish = BufferAbsFinish; + klass->protocol.describe = BufferAbsDescribe; klass->size = sizeof(BufferStruct); klass->varargs = ArgTrivVarargs; klass->init = BufferAbsInit; - klass->finish = BufferAbsFinish; klass->attach = bufferTrivAttach; klass->detach = bufferTrivDetach; - klass->describe = BufferAbsDescribe; klass->seg = bufferNoSeg; klass->rankSet = bufferTrivRankSet; klass->setRankSet = bufferNoSetRankSet; @@ -1108,12 +1108,13 @@ static Res segBufInit(Buffer buffer, Pool pool, Bool isMutator, ArgList args) /* segBufFinish -- SegBuf finish method */ -static void segBufFinish(Buffer buffer) +static void segBufFinish(Inst inst) { + Buffer buffer = MustBeA(Buffer, inst); SegBuf segbuf = MustBeA(SegBuf, buffer); AVER(BufferIsReset(buffer)); segbuf->sig = SigInvalid; - NextMethod(Buffer, SegBuf, finish)(buffer); + NextMethod(Inst, SegBuf, finish)(inst); } @@ -1210,8 +1211,9 @@ static void segBufReassignSeg(Buffer buffer, Seg seg) /* segBufDescribe -- describe method for SegBuf */ -static Res segBufDescribe(Buffer buffer, mps_lib_FILE *stream, Count depth) +static Res segBufDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { + Buffer buffer = CouldBeA(Buffer, inst); SegBuf segbuf = CouldBeA(SegBuf, buffer); Res res; @@ -1220,8 +1222,7 @@ static Res segBufDescribe(Buffer buffer, mps_lib_FILE *stream, Count depth) if (stream == NULL) return ResPARAM; - /* Describe the superclass fields first via next-method call */ - res = NextMethod(Buffer, SegBuf, describe)(buffer, stream, depth); + res = NextMethod(Inst, SegBuf, describe)(inst, stream, depth); if (res != ResOK) return res; @@ -1240,12 +1241,12 @@ static Res segBufDescribe(Buffer buffer, mps_lib_FILE *stream, Count depth) DEFINE_CLASS(Buffer, SegBuf, klass) { INHERIT_CLASS(klass, SegBuf, Buffer); + klass->protocol.finish = segBufFinish; + klass->protocol.describe = segBufDescribe; klass->size = sizeof(SegBufStruct); klass->init = segBufInit; - klass->finish = segBufFinish; klass->attach = segBufAttach; klass->detach = segBufDetach; - klass->describe = segBufDescribe; klass->seg = segBufSeg; klass->rankSet = segBufRankSet; klass->setRankSet = segBufSetRankSet; diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index 90f4d260a04..d1e738d890d 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -305,10 +305,8 @@ typedef struct BufferClassStruct { size_t size; /* size of outer structure */ BufferVarargsMethod varargs; /* parse obsolete varargs */ BufferInitMethod init; /* initialize the buffer */ - BufferFinishMethod finish; /* finish the buffer */ BufferAttachMethod attach; /* attach the buffer */ BufferDetachMethod detach; /* detach the buffer */ - BufferDescribeMethod describe;/* describe the contents of the buffer */ BufferSegMethod seg; /* seg of buffer */ BufferRankSetMethod rankSet; /* rank set of buffer */ BufferSetRankSetMethod setRankSet; /* change rank set of buffer */ diff --git a/mps/code/mpmtypes.h b/mps/code/mpmtypes.h index 5fdc0402c44..bc438ede851 100644 --- a/mps/code/mpmtypes.h +++ b/mps/code/mpmtypes.h @@ -153,7 +153,6 @@ typedef void (*FreeBlockVisitor)(Addr base, Addr limit, Pool pool, void *p); typedef Res (*SegInitMethod)(Seg seg, Pool pool, Addr base, Size size, ArgList args); -typedef void (*SegFinishMethod)(Seg seg); typedef void (*SegSetGreyMethod)(Seg seg, TraceSet grey); typedef void (*SegSetWhiteMethod)(Seg seg, TraceSet white); typedef void (*SegSetRankSetMethod)(Seg seg, RankSet rankSet); @@ -171,7 +170,6 @@ typedef Res (*SegSplitMethod)(Seg seg, Seg segHi, typedef void (*BufferVarargsMethod)(ArgStruct args[], va_list varargs); typedef Res (*BufferInitMethod)(Buffer buffer, Pool pool, Bool isMutator, ArgList args); -typedef void (*BufferFinishMethod)(Buffer buffer); typedef void (*BufferAttachMethod)(Buffer buffer, Addr base, Addr limit, Addr init, Size size); typedef void (*BufferDetachMethod)(Buffer buffer); @@ -179,7 +177,6 @@ typedef Seg (*BufferSegMethod)(Buffer buffer); typedef RankSet (*BufferRankSetMethod)(Buffer buffer); typedef void (*BufferSetRankSetMethod)(Buffer buffer, RankSet rankSet); typedef void (*BufferReassignSegMethod)(Buffer buffer, Seg seg); -typedef Res (*BufferDescribeMethod)(Buffer buffer, mps_lib_FILE *stream, Count depth); /* Pool*Method -- see */ @@ -188,7 +185,6 @@ typedef Res (*BufferDescribeMethod)(Buffer buffer, mps_lib_FILE *stream, Count d typedef void (*PoolVarargsMethod)(ArgStruct args[], va_list varargs); typedef Res (*PoolInitMethod)(Pool pool, Arena arena, PoolClass klass, ArgList args); -typedef void (*PoolFinishMethod)(Pool pool); typedef Res (*PoolAllocMethod)(Addr *pReturn, Pool pool, Size size); typedef void (*PoolFreeMethod)(Pool pool, Addr old, Size size); typedef Res (*PoolBufferFillMethod)(Addr *baseReturn, Addr *limitReturn, @@ -221,7 +217,6 @@ typedef void (*PoolWalkMethod)(Pool pool, Seg seg, FormattedObjectsVisitor f, void *v, size_t s); typedef void (*PoolFreeWalkMethod)(Pool pool, FreeBlockVisitor f, void *p); typedef BufferClass (*PoolBufferClassMethod)(void); -typedef Res (*PoolDescribeMethod)(Pool pool, mps_lib_FILE *stream, Count depth); typedef PoolDebugMixin (*PoolDebugMixinMethod)(Pool pool); typedef Size (*PoolSizeMethod)(Pool pool); @@ -254,7 +249,6 @@ typedef struct TraceMessageStruct *TraceMessage; /* trace end */ /* Land*Method -- see */ typedef Res (*LandInitMethod)(Land land, Arena arena, Align alignment, ArgList args); -typedef void (*LandFinishMethod)(Land land); typedef Size (*LandSizeMethod)(Land land); typedef Res (*LandInsertMethod)(Range rangeReturn, Land land, Range range); typedef Res (*LandDeleteMethod)(Range rangeReturn, Land land, Range range); @@ -264,7 +258,6 @@ typedef Bool (*LandIterateMethod)(Land land, LandVisitor visitor, void *closure) typedef Bool (*LandIterateAndDeleteMethod)(Land land, LandDeleteVisitor visitor, void *closure); typedef Bool (*LandFindMethod)(Range rangeReturn, Range oldRangeReturn, Land land, Size size, FindDelete findDelete); typedef Res (*LandFindInZonesMethod)(Bool *foundReturn, Range rangeReturn, Range oldRangeReturn, Land land, Size size, ZoneSet zoneSet, Bool high); -typedef Res (*LandDescribeMethod)(Land land, mps_lib_FILE *stream, Count depth); /* CONSTANTS */ diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c index 0cf0f9c03d3..07969f72e2c 100644 --- a/mps/code/poolamc.c +++ b/mps/code/poolamc.c @@ -509,11 +509,12 @@ static Res AMCBufInit(Buffer buffer, Pool pool, Bool isMutator, ArgList args) /* AMCBufFinish -- Finish an amcBuf */ -static void AMCBufFinish(Buffer buffer) +static void AMCBufFinish(Inst inst) { + Buffer buffer = MustBeA(Buffer, inst); amcBuf amcbuf = MustBeA(amcBuf, buffer); amcbuf->sig = SigInvalid; - NextMethod(Buffer, amcBuf, finish)(buffer); + NextMethod(Inst, amcBuf, finish)(inst); } @@ -522,9 +523,9 @@ static void AMCBufFinish(Buffer buffer) DEFINE_CLASS(Buffer, amcBuf, klass) { INHERIT_CLASS(klass, amcBuf, SegBuf); + klass->protocol.finish = AMCBufFinish; klass->size = sizeof(amcBufStruct); klass->init = AMCBufInit; - klass->finish = AMCBufFinish; } diff --git a/mps/code/poolsnc.c b/mps/code/poolsnc.c index ff0aa62dc76..e37a800ad52 100644 --- a/mps/code/poolsnc.c +++ b/mps/code/poolsnc.c @@ -138,8 +138,9 @@ static Res SNCBufInit(Buffer buffer, Pool pool, Bool isMutator, ArgList args) /* SNCBufFinish -- Finish an SNCBuf */ -static void SNCBufFinish(Buffer buffer) +static void SNCBufFinish(Inst inst) { + Buffer buffer = MustBeA(Buffer, inst); SNCBuf sncbuf = MustBeA(SNCBuf, buffer); SNC snc = MustBeA(SNCPool, BufferPool(buffer)); @@ -148,7 +149,7 @@ static void SNCBufFinish(Buffer buffer) sncbuf->sig = SigInvalid; - NextMethod(Buffer, SNCBuf, finish)(buffer); + NextMethod(Inst, SNCBuf, finish)(inst); } @@ -157,9 +158,9 @@ static void SNCBufFinish(Buffer buffer) DEFINE_CLASS(Buffer, SNCBuf, klass) { INHERIT_CLASS(klass, SNCBuf, RankBuf); + klass->protocol.finish = SNCBufFinish; klass->size = sizeof(SNCBufStruct); klass->init = SNCBufInit; - klass->finish = SNCBufFinish; } From 771f6defda5f12fe4ac7e6fa021c61e51f1d71a4 Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sat, 23 Apr 2016 16:30:08 +0100 Subject: [PATCH 23/52] Converting arena finish and describe methods to specialize instfinish and instdescribe. Copied from Perforce Change: 191614 ServerID: perforce.ravenbrook.com --- mps/code/arena.c | 27 +++++++++++---------------- mps/code/arenacl.c | 4 ++-- mps/code/arenavm.c | 13 +++++++------ mps/code/mpmst.h | 2 -- mps/code/mpmtypes.h | 2 -- 5 files changed, 20 insertions(+), 28 deletions(-) diff --git a/mps/code/arena.c b/mps/code/arena.c index 3fc69afc30f..fca92bd05d3 100644 --- a/mps/code/arena.c +++ b/mps/code/arena.c @@ -43,8 +43,8 @@ static void ArenaTrivCompact(Arena arena, Trace trace); static void arenaFreePage(Arena arena, Addr base, Pool pool); static void arenaFreeLandFinish(Arena arena); static Res ArenaAbsInit(Arena arena, Size grainSize, ArgList args); -static void ArenaAbsFinish(Arena arena); -static Res ArenaAbsDescribe(Arena arena, mps_lib_FILE *stream, Count depth); +static void ArenaAbsFinish(Inst inst); +static Res ArenaAbsDescribe(Inst inst, mps_lib_FILE *stream, Count depth); static void ArenaNoFree(Addr base, Size size, Pool pool) @@ -107,10 +107,11 @@ DEFINE_CLASS(Inst, ArenaClass, klass) DEFINE_CLASS(Arena, AbstractArena, klass) { INHERIT_CLASS(&klass->protocol, AbstractArena, Inst); + klass->protocol.finish = ArenaAbsFinish; + klass->protocol.describe = ArenaAbsDescribe; klass->size = sizeof(ArenaStruct); klass->varargs = ArgTrivVarargs; klass->init = ArenaAbsInit; - klass->finish = ArenaAbsFinish; klass->create = ArenaNoCreate; klass->destroy = ArenaNoDestroy; klass->purgeSpare = ArenaNoPurgeSpare; @@ -120,7 +121,6 @@ DEFINE_CLASS(Arena, AbstractArena, klass) klass->chunkInit = ArenaNoChunkInit; klass->chunkFinish = ArenaNoChunkFinish; klass->compact = ArenaTrivCompact; - klass->describe = ArenaAbsDescribe; klass->pagesMarkAllocated = ArenaNoPagesMarkAllocated; klass->sig = ArenaClassSig; } @@ -134,7 +134,6 @@ Bool ArenaClassCheck(ArenaClass klass) CHECKL(klass->size >= sizeof(ArenaStruct)); CHECKL(FUNCHECK(klass->varargs)); CHECKL(FUNCHECK(klass->init)); - CHECKL(FUNCHECK(klass->finish)); CHECKL(FUNCHECK(klass->create)); CHECKL(FUNCHECK(klass->destroy)); CHECKL(FUNCHECK(klass->purgeSpare)); @@ -144,7 +143,6 @@ Bool ArenaClassCheck(ArenaClass klass) CHECKL(FUNCHECK(klass->chunkInit)); CHECKL(FUNCHECK(klass->chunkFinish)); CHECKL(FUNCHECK(klass->compact)); - CHECKL(FUNCHECK(klass->describe)); CHECKL(FUNCHECK(klass->pagesMarkAllocated)); CHECKS(ArenaClass, klass); return TRUE; @@ -406,19 +404,15 @@ failInit: } -/* ArenaAbsFinish -- finish the generic part of the arena - * - * .finish.caller: Unlike PoolFinish, this is called by the class finish - * methods, not the generic Destroy. This is because the class is - * responsible for deallocating the descriptor. - */ +/* ArenaAbsFinish -- finish the generic part of the arena */ -static void ArenaAbsFinish(Arena arena) +static void ArenaAbsFinish(Inst inst) { + Arena arena = MustBeA(AbstractArena, inst); AVERC(Arena, arena); PoolFinish(ArenaCBSBlockPool(arena)); arena->sig = SigInvalid; - InstFinish(MustBeA(Inst, arena)); + NextMethod(Inst, AbstractArena, finish)(inst); GlobalsFinish(ArenaGlobals(arena)); LocusFinish(arena); RingFinish(ArenaChunkRing(arena)); @@ -510,8 +504,9 @@ void ControlFinish(Arena arena) /* ArenaDescribe -- describe the arena */ -static Res ArenaAbsDescribe(Arena arena, mps_lib_FILE *stream, Count depth) +static Res ArenaAbsDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { + Arena arena = CouldBeA(AbstractArena, inst); Res res; if (!TESTC(AbstractArena, arena)) @@ -565,7 +560,7 @@ static Res ArenaAbsDescribe(Arena arena, mps_lib_FILE *stream, Count depth) Res ArenaDescribe(Arena arena, mps_lib_FILE *stream, Count depth) { - return Method(Arena, arena, describe)(arena, stream, depth); + return Method(Inst, arena, describe)(MustBeA(Inst, arena), stream, depth); } diff --git a/mps/code/arenacl.c b/mps/code/arenacl.c index bc139e23857..72e8c4af386 100644 --- a/mps/code/arenacl.c +++ b/mps/code/arenacl.c @@ -311,7 +311,7 @@ static Res ClientArenaCreate(Arena *arenaReturn, ArgList args) return ResOK; failChunkCreate: - NextMethod(Arena, ClientArena, finish)(arena); + NextMethod(Inst, ClientArena, finish)(MustBeA(Inst, arena)); failSuperInit: AVER(res != ResOK); return res; @@ -336,7 +336,7 @@ static void ClientArenaDestroy(Arena arena) AVER(arena->reserved == 0); AVER(arena->committed == 0); - NextMethod(Arena, ClientArena, finish)(arena); /* */ + NextMethod(Inst, ClientArena, finish)(MustBeA(Inst, arena)); } diff --git a/mps/code/arenavm.c b/mps/code/arenavm.c index 9467e104bc2..613f4aef8e8 100644 --- a/mps/code/arenavm.c +++ b/mps/code/arenavm.c @@ -187,17 +187,18 @@ static Bool VMArenaCheck(VMArena vmArena) /* VMArenaDescribe -- describe the VMArena */ -static Res VMArenaDescribe(Arena arena, mps_lib_FILE *stream, Count depth) +static Res VMArenaDescribe(Inst inst, mps_lib_FILE *stream, Count depth) { - Res res; + Arena arena = CouldBeA(AbstractArena, inst); VMArena vmArena = CouldBeA(VMArena, arena); + Res res; if (!TESTC(VMArena, vmArena)) return ResPARAM; if (stream == NULL) return ResPARAM; - res = NextMethod(Arena, VMArena, describe)(arena, stream, depth); + res = NextMethod(Inst, VMArena, describe)(inst, stream, depth); if (res != ResOK) return res; @@ -666,7 +667,7 @@ static Res VMArenaCreate(Arena *arenaReturn, ArgList args) return ResOK; failChunkCreate: - NextMethod(Arena, VMArena, finish)(arena); + NextMethod(Inst, VMArena, finish)(MustBeA(Inst, arena)); failArenaInit: VMUnmap(vm, VMBase(vm), VMLimit(vm)); failVMMap: @@ -701,7 +702,7 @@ static void VMArenaDestroy(Arena arena) vmArena->sig = SigInvalid; - NextMethod(Arena, VMArena, finish)(arena); /* */ + NextMethod(Inst, VMArena, finish)(MustBeA(Inst, arena)); /* Copy VM descriptor to stack-local storage so that we can continue * using the descriptor after the VM has been unmapped. */ @@ -1195,6 +1196,7 @@ mps_res_t mps_arena_vm_growth(mps_arena_t mps_arena, DEFINE_CLASS(Arena, VMArena, klass) { INHERIT_CLASS(klass, VMArena, AbstractArena); + klass->protocol.describe = VMArenaDescribe; klass->size = sizeof(VMArenaStruct); klass->varargs = VMArenaVarargs; klass->create = VMArenaCreate; @@ -1205,7 +1207,6 @@ DEFINE_CLASS(Arena, VMArena, klass) klass->chunkInit = VMChunkInit; klass->chunkFinish = VMChunkFinish; klass->compact = VMCompact; - klass->describe = VMArenaDescribe; klass->pagesMarkAllocated = VMPagesMarkAllocated; } diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index d1e738d890d..fcb56d5465c 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -494,7 +494,6 @@ typedef struct mps_arena_class_s { size_t size; /* size of outer structure */ ArenaVarargsMethod varargs; ArenaInitMethod init; - ArenaFinishMethod finish; ArenaCreateMethod create; ArenaDestroyMethod destroy; ArenaPurgeSpareMethod purgeSpare; @@ -504,7 +503,6 @@ typedef struct mps_arena_class_s { ArenaChunkInitMethod chunkInit; ArenaChunkFinishMethod chunkFinish; ArenaCompactMethod compact; - ArenaDescribeMethod describe; ArenaPagesMarkAllocatedMethod pagesMarkAllocated; Sig sig; } ArenaClassStruct; diff --git a/mps/code/mpmtypes.h b/mps/code/mpmtypes.h index bc438ede851..b18d5c3691f 100644 --- a/mps/code/mpmtypes.h +++ b/mps/code/mpmtypes.h @@ -114,7 +114,6 @@ typedef void (*ArenaVarargsMethod)(ArgStruct args[], va_list varargs); typedef Res (*ArenaCreateMethod)(Arena *arenaReturn, ArgList args); typedef void (*ArenaDestroyMethod)(Arena arena); typedef Res (*ArenaInitMethod)(Arena arena, Size grainSize, ArgList args); -typedef void (*ArenaFinishMethod)(Arena arena); typedef Size (*ArenaPurgeSpareMethod)(Arena arena, Size size); typedef Res (*ArenaExtendMethod)(Arena arena, Addr base, Size size); typedef Res (*ArenaGrowMethod)(Arena arena, LocusPref pref, Size size); @@ -122,7 +121,6 @@ typedef void (*ArenaFreeMethod)(Addr base, Size size, Pool pool); typedef Res (*ArenaChunkInitMethod)(Chunk chunk, BootBlock boot); typedef void (*ArenaChunkFinishMethod)(Chunk chunk); typedef void (*ArenaCompactMethod)(Arena arena, Trace trace); -typedef Res (*ArenaDescribeMethod)(Arena arena, mps_lib_FILE *stream, Count depth); typedef Res (*ArenaPagesMarkAllocatedMethod)(Arena arena, Chunk chunk, Index baseIndex, Count pages, Pool pool); From bda168dfb8df094d4a07453610eb7bc180c944a5 Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Wed, 27 Apr 2016 14:25:54 +0100 Subject: [PATCH 24/52] Renaming class fields called "protocol" to "instclassstruct" in line with usual mps convention. Copied from Perforce Change: 191685 ServerID: perforce.ravenbrook.com --- mps/code/arena.c | 8 ++++---- mps/code/arenavm.c | 2 +- mps/code/buffer.c | 12 ++++++------ mps/code/cbs.c | 4 ++-- mps/code/dbgpool.c | 2 +- mps/code/failover.c | 4 ++-- mps/code/freelist.c | 4 ++-- mps/code/land.c | 8 ++++---- mps/code/mpmst.h | 8 ++++---- mps/code/pool.c | 4 ++-- mps/code/poolabs.c | 6 +++--- mps/code/poolamc.c | 6 +++--- mps/code/poolams.c | 4 ++-- mps/code/poolawl.c | 2 +- mps/code/poollo.c | 2 +- mps/code/poolmfs.c | 4 ++-- mps/code/poolmrg.c | 4 ++-- mps/code/poolmv.c | 4 ++-- mps/code/poolmv2.c | 4 ++-- mps/code/poolmvff.c | 4 ++-- mps/code/pooln.c | 4 ++-- mps/code/poolsnc.c | 4 ++-- mps/code/segsmss.c | 2 +- 23 files changed, 53 insertions(+), 53 deletions(-) diff --git a/mps/code/arena.c b/mps/code/arena.c index fca92bd05d3..a3301521fae 100644 --- a/mps/code/arena.c +++ b/mps/code/arena.c @@ -106,9 +106,9 @@ DEFINE_CLASS(Inst, ArenaClass, klass) DEFINE_CLASS(Arena, AbstractArena, klass) { - INHERIT_CLASS(&klass->protocol, AbstractArena, Inst); - klass->protocol.finish = ArenaAbsFinish; - klass->protocol.describe = ArenaAbsDescribe; + INHERIT_CLASS(&klass->instClassStruct, AbstractArena, Inst); + klass->instClassStruct.finish = ArenaAbsFinish; + klass->instClassStruct.describe = ArenaAbsDescribe; klass->size = sizeof(ArenaStruct); klass->varargs = ArgTrivVarargs; klass->init = ArenaAbsInit; @@ -130,7 +130,7 @@ DEFINE_CLASS(Arena, AbstractArena, klass) Bool ArenaClassCheck(ArenaClass klass) { - CHECKD(InstClass, &klass->protocol); + CHECKD(InstClass, &klass->instClassStruct); CHECKL(klass->size >= sizeof(ArenaStruct)); CHECKL(FUNCHECK(klass->varargs)); CHECKL(FUNCHECK(klass->init)); diff --git a/mps/code/arenavm.c b/mps/code/arenavm.c index 613f4aef8e8..0168b4b6ed8 100644 --- a/mps/code/arenavm.c +++ b/mps/code/arenavm.c @@ -1196,7 +1196,7 @@ mps_res_t mps_arena_vm_growth(mps_arena_t mps_arena, DEFINE_CLASS(Arena, VMArena, klass) { INHERIT_CLASS(klass, VMArena, AbstractArena); - klass->protocol.describe = VMArenaDescribe; + klass->instClassStruct.describe = VMArenaDescribe; klass->size = sizeof(VMArenaStruct); klass->varargs = VMArenaVarargs; klass->create = VMArenaCreate; diff --git a/mps/code/buffer.c b/mps/code/buffer.c index f87dbf494ac..460d4d6508a 100644 --- a/mps/code/buffer.c +++ b/mps/code/buffer.c @@ -1004,7 +1004,7 @@ static void bufferNoReassignSeg(Buffer buffer, Seg seg) Bool BufferClassCheck(BufferClass klass) { - CHECKD(InstClass, &klass->protocol); + CHECKD(InstClass, &klass->instClassStruct); CHECKL(klass->size >= sizeof(BufferStruct)); CHECKL(FUNCHECK(klass->varargs)); CHECKL(FUNCHECK(klass->init)); @@ -1030,9 +1030,9 @@ DEFINE_CLASS(Inst, BufferClass, klass) DEFINE_CLASS(Buffer, Buffer, klass) { - INHERIT_CLASS(&klass->protocol, Buffer, Inst); - klass->protocol.finish = BufferAbsFinish; - klass->protocol.describe = BufferAbsDescribe; + INHERIT_CLASS(&klass->instClassStruct, Buffer, Inst); + klass->instClassStruct.finish = BufferAbsFinish; + klass->instClassStruct.describe = BufferAbsDescribe; klass->size = sizeof(BufferStruct); klass->varargs = ArgTrivVarargs; klass->init = BufferAbsInit; @@ -1241,8 +1241,8 @@ static Res segBufDescribe(Inst inst, mps_lib_FILE *stream, Count depth) DEFINE_CLASS(Buffer, SegBuf, klass) { INHERIT_CLASS(klass, SegBuf, Buffer); - klass->protocol.finish = segBufFinish; - klass->protocol.describe = segBufDescribe; + klass->instClassStruct.finish = segBufFinish; + klass->instClassStruct.describe = segBufDescribe; klass->size = sizeof(SegBufStruct); klass->init = segBufInit; klass->attach = segBufAttach; diff --git a/mps/code/cbs.c b/mps/code/cbs.c index 80750e66c34..349d6737abc 100644 --- a/mps/code/cbs.c +++ b/mps/code/cbs.c @@ -1135,8 +1135,8 @@ static Res cbsDescribe(Inst inst, mps_lib_FILE *stream, Count depth) DEFINE_CLASS(Land, CBS, klass) { INHERIT_CLASS(klass, CBS, Land); - klass->protocol.describe = cbsDescribe; - klass->protocol.finish = cbsFinish; + klass->instClassStruct.describe = cbsDescribe; + klass->instClassStruct.finish = cbsFinish; klass->size = sizeof(CBSStruct); klass->init = cbsInit; klass->sizeMethod = cbsSize; diff --git a/mps/code/dbgpool.c b/mps/code/dbgpool.c index 5a56002695c..3eaea4d9e3c 100644 --- a/mps/code/dbgpool.c +++ b/mps/code/dbgpool.c @@ -776,7 +776,7 @@ void DebugPoolCheckFreeSpace(Pool pool) void PoolClassMixInDebug(PoolClass klass) { /* Can't check klass because it's not initialized yet */ - klass->protocol.finish = DebugPoolFinish; + klass->instClassStruct.finish = DebugPoolFinish; klass->init = DebugPoolInit; klass->alloc = DebugPoolAlloc; klass->free = DebugPoolFree; diff --git a/mps/code/failover.c b/mps/code/failover.c index 0a6e344a537..94b6b17b2fc 100644 --- a/mps/code/failover.c +++ b/mps/code/failover.c @@ -274,8 +274,8 @@ static Res failoverDescribe(Inst inst, mps_lib_FILE *stream, Count depth) DEFINE_CLASS(Land, Failover, klass) { INHERIT_CLASS(klass, Failover, Land); - klass->protocol.describe = failoverDescribe; - klass->protocol.finish = failoverFinish; + klass->instClassStruct.describe = failoverDescribe; + klass->instClassStruct.finish = failoverFinish; klass->size = sizeof(FailoverStruct); klass->init = failoverInit; klass->sizeMethod = failoverSize; diff --git a/mps/code/freelist.c b/mps/code/freelist.c index e01f78edfa3..c4dba60d7ed 100644 --- a/mps/code/freelist.c +++ b/mps/code/freelist.c @@ -781,8 +781,8 @@ static Res freelistDescribe(Inst inst, mps_lib_FILE *stream, Count depth) DEFINE_CLASS(Land, Freelist, klass) { INHERIT_CLASS(klass, Freelist, Land); - klass->protocol.describe = freelistDescribe; - klass->protocol.finish = freelistFinish; + klass->instClassStruct.describe = freelistDescribe; + klass->instClassStruct.finish = freelistFinish; klass->size = sizeof(FreelistStruct); klass->init = freelistInit; klass->sizeMethod = freelistSize; diff --git a/mps/code/land.c b/mps/code/land.c index 1a13ec39fb6..c378128ba29 100644 --- a/mps/code/land.c +++ b/mps/code/land.c @@ -442,7 +442,7 @@ Bool LandFlush(Land dest, Land src) Bool LandClassCheck(LandClass klass) { - CHECKL(InstClassCheck(&klass->protocol)); + CHECKL(InstClassCheck(&klass->instClassStruct)); CHECKL(klass->size >= sizeof(LandStruct)); CHECKL(FUNCHECK(klass->init)); CHECKL(FUNCHECK(klass->insert)); @@ -574,9 +574,9 @@ DEFINE_CLASS(Inst, LandClass, klass) DEFINE_CLASS(Land, Land, klass) { - INHERIT_CLASS(&klass->protocol, Land, Inst); - klass->protocol.describe = LandAbsDescribe; - klass->protocol.finish = LandAbsFinish; + INHERIT_CLASS(&klass->instClassStruct, Land, Inst); + klass->instClassStruct.describe = LandAbsDescribe; + klass->instClassStruct.finish = LandAbsFinish; klass->size = sizeof(LandStruct); klass->init = LandAbsInit; klass->sizeMethod = landNoSize; diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index fcb56d5465c..e4a7694eb90 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -49,7 +49,7 @@ #define PoolClassSig ((Sig)0x519C7A55) /* SIGnature pool CLASS */ typedef struct mps_pool_class_s { - InstClassStruct protocol; + InstClassStruct instClassStruct; size_t size; /* size of outer structure */ Attr attr; /* attributes */ PoolVarargsMethod varargs; /* convert deprecated varargs into keywords */ @@ -301,7 +301,7 @@ typedef struct LocusPrefStruct { /* locus placement preferences */ #define BufferClassSig ((Sig)0x519B0FC7) /* SIGnature BUFfer CLass */ typedef struct BufferClassStruct { - InstClassStruct protocol; + InstClassStruct instClassStruct; size_t size; /* size of outer structure */ BufferVarargsMethod varargs; /* parse obsolete varargs */ BufferInitMethod init; /* initialize the buffer */ @@ -490,7 +490,7 @@ typedef struct TraceStruct { #define ArenaClassSig ((Sig)0x519A6C1A) /* SIGnature ARena CLAss */ typedef struct mps_arena_class_s { - InstClassStruct protocol; + InstClassStruct instClassStruct; size_t size; /* size of outer structure */ ArenaVarargsMethod varargs; ArenaInitMethod init; @@ -567,7 +567,7 @@ typedef struct GlobalsStruct { #define LandClassSig ((Sig)0x5197A4DC) /* SIGnature LAND Class */ typedef struct LandClassStruct { - InstClassStruct protocol; + InstClassStruct instClassStruct; size_t size; /* size of outer structure */ LandSizeMethod sizeMethod; /* total size of ranges in land */ LandInitMethod init; /* initialize the land */ diff --git a/mps/code/pool.c b/mps/code/pool.c index b6fb278a121..f337ccbbbce 100644 --- a/mps/code/pool.c +++ b/mps/code/pool.c @@ -37,7 +37,7 @@ SRCID(pool, "$Id$"); Bool PoolClassCheck(PoolClass klass) { - CHECKD(InstClass, &klass->protocol); + CHECKD(InstClass, &klass->instClassStruct); CHECKL(klass->size >= sizeof(PoolStruct)); CHECKL(AttrCheck(klass->attr)); CHECKL(!(klass->attr & AttrMOVINGGC) || (klass->attr & AttrGC)); @@ -70,7 +70,7 @@ Bool PoolClassCheck(PoolClass klass) /* Check that pool classes overide sets of related methods. */ CHECKL((klass->init == PoolAbsInit) == - (klass->protocol.finish == PoolAbsFinish)); + (klass->instClassStruct.finish == PoolAbsFinish)); CHECKL((klass->bufferFill == PoolNoBufferFill) == (klass->bufferEmpty == PoolNoBufferEmpty)); CHECKL((klass->framePush == PoolNoFramePush) == diff --git a/mps/code/poolabs.c b/mps/code/poolabs.c index eb360e687b9..d8475b893a6 100644 --- a/mps/code/poolabs.c +++ b/mps/code/poolabs.c @@ -186,9 +186,9 @@ DEFINE_CLASS(Inst, PoolClass, klass) DEFINE_CLASS(Pool, AbstractPool, klass) { - INHERIT_CLASS(&klass->protocol, AbstractPool, Inst); - klass->protocol.describe = PoolAbsDescribe; - klass->protocol.finish = PoolAbsFinish; + INHERIT_CLASS(&klass->instClassStruct, AbstractPool, Inst); + klass->instClassStruct.describe = PoolAbsDescribe; + klass->instClassStruct.finish = PoolAbsFinish; klass->size = sizeof(PoolStruct); klass->attr = 0; klass->varargs = ArgTrivVarargs; diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c index 07969f72e2c..fb63150b1df 100644 --- a/mps/code/poolamc.c +++ b/mps/code/poolamc.c @@ -523,7 +523,7 @@ static void AMCBufFinish(Inst inst) DEFINE_CLASS(Buffer, amcBuf, klass) { INHERIT_CLASS(klass, amcBuf, SegBuf); - klass->protocol.finish = AMCBufFinish; + klass->instClassStruct.finish = AMCBufFinish; klass->size = sizeof(amcBufStruct); klass->init = AMCBufInit; } @@ -2025,8 +2025,8 @@ DEFINE_CLASS(Pool, AMCZPool, klass) INHERIT_CLASS(klass, AMCZPool, AbstractSegBufPool); PoolClassMixInFormat(klass); PoolClassMixInCollect(klass); - klass->protocol.describe = AMCDescribe; - klass->protocol.finish = AMCFinish; + klass->instClassStruct.describe = AMCDescribe; + klass->instClassStruct.finish = AMCFinish; klass->size = sizeof(AMCStruct); klass->attr |= AttrMOVINGGC; klass->varargs = AMCVarargs; diff --git a/mps/code/poolams.c b/mps/code/poolams.c index 17679639dd8..39ec61931df 100644 --- a/mps/code/poolams.c +++ b/mps/code/poolams.c @@ -1743,8 +1743,8 @@ DEFINE_CLASS(Pool, AMSPool, klass) { INHERIT_CLASS(klass, AMSPool, AbstractCollectPool); PoolClassMixInFormat(klass); - klass->protocol.describe = AMSDescribe; - klass->protocol.finish = AMSFinish; + klass->instClassStruct.describe = AMSDescribe; + klass->instClassStruct.finish = AMSFinish; klass->size = sizeof(AMSStruct); klass->varargs = AMSVarargs; klass->init = AMSInit; diff --git a/mps/code/poolawl.c b/mps/code/poolawl.c index 2287432ecc7..e40c2384a70 100644 --- a/mps/code/poolawl.c +++ b/mps/code/poolawl.c @@ -1217,7 +1217,7 @@ DEFINE_CLASS(Pool, AWLPool, klass) { INHERIT_CLASS(klass, AWLPool, AbstractCollectPool); PoolClassMixInFormat(klass); - klass->protocol.finish = AWLFinish; + klass->instClassStruct.finish = AWLFinish; klass->size = sizeof(AWLPoolStruct); klass->varargs = AWLVarargs; klass->init = AWLInit; diff --git a/mps/code/poollo.c b/mps/code/poollo.c index 338d2c18618..7385b443b47 100644 --- a/mps/code/poollo.c +++ b/mps/code/poollo.c @@ -786,7 +786,7 @@ DEFINE_CLASS(Pool, LOPool, klass) INHERIT_CLASS(klass, LOPool, AbstractSegBufPool); PoolClassMixInFormat(klass); PoolClassMixInCollect(klass); - klass->protocol.finish = LOFinish; + klass->instClassStruct.finish = LOFinish; klass->size = sizeof(LOStruct); klass->varargs = LOVarargs; klass->init = LOInit; diff --git a/mps/code/poolmfs.c b/mps/code/poolmfs.c index 7b5443995b3..a511eabc393 100644 --- a/mps/code/poolmfs.c +++ b/mps/code/poolmfs.c @@ -339,8 +339,8 @@ static Res MFSDescribe(Inst inst, mps_lib_FILE *stream, Count depth) DEFINE_CLASS(Pool, MFSPool, klass) { INHERIT_CLASS(klass, MFSPool, AbstractPool); - klass->protocol.describe = MFSDescribe; - klass->protocol.finish = MFSFinish; + klass->instClassStruct.describe = MFSDescribe; + klass->instClassStruct.finish = MFSFinish; klass->size = sizeof(MFSStruct); klass->varargs = MFSVarargs; klass->init = MFSInit; diff --git a/mps/code/poolmrg.c b/mps/code/poolmrg.c index f52715fe536..d378889f1f3 100644 --- a/mps/code/poolmrg.c +++ b/mps/code/poolmrg.c @@ -842,8 +842,8 @@ static Res MRGScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) DEFINE_CLASS(Pool, MRGPool, klass) { INHERIT_CLASS(klass, MRGPool, AbstractPool); - klass->protocol.describe = MRGDescribe; - klass->protocol.finish = MRGFinish; + klass->instClassStruct.describe = MRGDescribe; + klass->instClassStruct.finish = MRGFinish; klass->size = sizeof(MRGStruct); klass->init = MRGInit; klass->grey = PoolTrivGrey; diff --git a/mps/code/poolmv.c b/mps/code/poolmv.c index 06fad8fb398..a7d113d09a4 100644 --- a/mps/code/poolmv.c +++ b/mps/code/poolmv.c @@ -864,8 +864,8 @@ static Res MVDescribe(Inst inst, mps_lib_FILE *stream, Count depth) DEFINE_CLASS(Pool, MVPool, klass) { INHERIT_CLASS(klass, MVPool, AbstractBufferPool); - klass->protocol.describe = MVDescribe; - klass->protocol.finish = MVFinish; + klass->instClassStruct.describe = MVDescribe; + klass->instClassStruct.finish = MVFinish; klass->size = sizeof(MVStruct); klass->varargs = MVVarargs; klass->init = MVInit; diff --git a/mps/code/poolmv2.c b/mps/code/poolmv2.c index 380b67c1811..a643ba7f8cc 100644 --- a/mps/code/poolmv2.c +++ b/mps/code/poolmv2.c @@ -139,8 +139,8 @@ typedef struct MVTStruct DEFINE_CLASS(Pool, MVTPool, klass) { INHERIT_CLASS(klass, MVTPool, AbstractBufferPool); - klass->protocol.describe = MVTDescribe; - klass->protocol.finish = MVTFinish; + klass->instClassStruct.describe = MVTDescribe; + klass->instClassStruct.finish = MVTFinish; klass->size = sizeof(MVTStruct); klass->varargs = MVTVarargs; klass->init = MVTInit; diff --git a/mps/code/poolmvff.c b/mps/code/poolmvff.c index cbf55ee1df0..0d284e58f68 100644 --- a/mps/code/poolmvff.c +++ b/mps/code/poolmvff.c @@ -722,8 +722,8 @@ DEFINE_CLASS(Pool, MVFFPool, klass) { INHERIT_CLASS(klass, MVFFPool, AbstractPool); PoolClassMixInBuffer(klass); - klass->protocol.describe = MVFFDescribe; - klass->protocol.finish = MVFFFinish; + klass->instClassStruct.describe = MVFFDescribe; + klass->instClassStruct.finish = MVFFFinish; klass->size = sizeof(MVFFStruct); klass->varargs = MVFFVarargs; klass->init = MVFFInit; diff --git a/mps/code/pooln.c b/mps/code/pooln.c index af273c4ce47..eb501244b24 100644 --- a/mps/code/pooln.c +++ b/mps/code/pooln.c @@ -257,8 +257,8 @@ static void NTraceEnd(Pool pool, Trace trace) DEFINE_CLASS(Pool, NPool, klass) { INHERIT_CLASS(klass, NPool, AbstractPool); - klass->protocol.describe = NDescribe; - klass->protocol.finish = NFinish; + klass->instClassStruct.describe = NDescribe; + klass->instClassStruct.finish = NFinish; klass->size = sizeof(PoolNStruct); klass->attr |= AttrGC; klass->init = NInit; diff --git a/mps/code/poolsnc.c b/mps/code/poolsnc.c index e37a800ad52..a62ae8abbc1 100644 --- a/mps/code/poolsnc.c +++ b/mps/code/poolsnc.c @@ -158,7 +158,7 @@ static void SNCBufFinish(Inst inst) DEFINE_CLASS(Buffer, SNCBuf, klass) { INHERIT_CLASS(klass, SNCBuf, RankBuf); - klass->protocol.finish = SNCBufFinish; + klass->instClassStruct.finish = SNCBufFinish; klass->size = sizeof(SNCBufStruct); klass->init = SNCBufInit; } @@ -668,7 +668,7 @@ DEFINE_CLASS(Pool, SNCPool, klass) { INHERIT_CLASS(klass, SNCPool, AbstractScanPool); PoolClassMixInFormat(klass); - klass->protocol.finish = SNCFinish; + klass->instClassStruct.finish = SNCFinish; klass->size = sizeof(SNCStruct); klass->varargs = SNCVarargs; klass->init = SNCInit; diff --git a/mps/code/segsmss.c b/mps/code/segsmss.c index 9162deba674..e2ce9f371e3 100644 --- a/mps/code/segsmss.c +++ b/mps/code/segsmss.c @@ -650,7 +650,7 @@ static void AMSTStressBufferedSeg(Seg seg, Buffer buffer) DEFINE_CLASS(Pool, AMSTPool, klass) { INHERIT_CLASS(klass, AMSTPool, AMSPool); - klass->protocol.finish = AMSTFinish; + klass->instClassStruct.finish = AMSTFinish; klass->size = sizeof(AMSTStruct); klass->init = AMSTInit; klass->bufferFill = AMSTBufferFill; From 726ba1d25acbe8da69c2955651f6f8b7539e9ffb Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Wed, 27 Apr 2016 15:27:47 +0100 Subject: [PATCH 25/52] Temporarily introducing seggetbuffer to eliminate use of "null" to mean "no buffer". Copied from Perforce Change: 191694 ServerID: perforce.ravenbrook.com --- mps/code/mpm.h | 1 + mps/code/poolamc.c | 26 ++++++++++++++------------ mps/code/poolams.c | 33 ++++++++++++++++----------------- mps/code/poolawl.c | 26 ++++++++++++++------------ mps/code/poollo.c | 14 +++++++------- mps/code/poolsnc.c | 3 ++- mps/code/seg.c | 17 ++++++++++++++--- mps/code/segsmss.c | 3 ++- 8 files changed, 70 insertions(+), 53 deletions(-) diff --git a/mps/code/mpm.h b/mps/code/mpm.h index 5131f908491..2e7c251d5d6 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -672,6 +672,7 @@ extern Res SegSplit(Seg *segLoReturn, Seg *segHiReturn, Seg seg, Addr at); extern Res SegDescribe(Seg seg, mps_lib_FILE *stream, Count depth); extern void SegSetSummary(Seg seg, RefSet summary); extern Bool SegHasBuffer(Seg seg); +extern Bool SegGetBuffer(Buffer *bufferReturn, Seg seg); extern Buffer SegBuffer(Seg seg); extern void SegSetBuffer(Seg seg, Buffer buffer); extern Addr SegBufferScanLimit(Seg seg); diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c index eba6836a025..116bfdab465 100644 --- a/mps/code/poolamc.c +++ b/mps/code/poolamc.c @@ -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 (!SegGetBuffer(&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; @@ -284,8 +284,8 @@ static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) if(res != ResOK) return res; - if(SegHasBuffer(seg)) - init = BufferGetInit(SegBuffer(seg)); + if (SegGetBuffer(&buffer, seg)) + init = BufferGetInit(buffer); else init = limit; @@ -1111,8 +1111,7 @@ static Res AMCWhiten(Pool pool, Trace trace, Seg seg) AVERT(Trace, trace); - buffer = SegBuffer(seg); - if(buffer != NULL) { + if (SegGetBuffer(&buffer, seg)) { AVERT(Buffer, buffer); if(!BufferIsMutator(buffer)) { /* forwarding buffer */ @@ -1261,6 +1260,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 */ @@ -1269,8 +1269,8 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn, NailboardClearNewNails(board); p = SegBase(seg); - while (SegHasBuffer(seg)) { - limit = BufferScanLimit(SegBuffer(seg)); + while (SegGetBuffer(&buffer, seg)) { + limit = BufferScanLimit(buffer); if(p >= limit) { AVER(p == limit); goto returnGood; @@ -1353,6 +1353,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); @@ -1369,8 +1370,8 @@ static Res AMCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) base = AddrAdd(SegBase(seg), format->headerSize); /* */ - while (SegHasBuffer(seg)) { - limit = AddrAdd(BufferScanLimit(SegBuffer(seg)), + while (SegGetBuffer(&buffer, seg)) { + limit = AddrAdd(BufferScanLimit(buffer), format->headerSize); if(base >= limit) { /* @@@@ Are we sure we don't need scan the rest of the */ @@ -1895,6 +1896,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); @@ -1905,7 +1907,7 @@ static Res AMCAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr) arena = PoolArena(pool); base = SegBase(seg); - if (SegHasBuffer(seg)) { + if (SegGetBuffer(&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 @@ -1917,7 +1919,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); } diff --git a/mps/code/poolams.c b/mps/code/poolams.c index 7edb4aaeaf2..11107488727 100644 --- a/mps/code/poolams.c +++ b/mps/code/poolams.c @@ -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) { Res res; AMSSeg amsseg; - Buffer buffer; /* the segment's buffer, if it has one */ + Buffer buffer; + Bool hasBuffer; Index i; if (!TESTT(Seg, seg)) @@ -543,7 +543,7 @@ static Res AMSSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) if (res != ResOK) return res; - buffer = SegBuffer(seg); + hasBuffer = SegGetBuffer(&buffer, seg); res = WriteF(stream, depth, " AMS $P\n", (WriteFP)amsseg->ams, @@ -586,9 +586,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) { @@ -608,8 +608,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; @@ -733,7 +733,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); @@ -1143,8 +1143,7 @@ static Res AMSWhiten(Pool pool, Trace trace, Seg seg) amsseg->allocTableInUse = TRUE; } - buffer = SegBuffer(seg); - if (buffer != NULL) { /* */ + if (SegGetBuffer(&buffer, seg)) { /* */ Index scanLimitIndex, limitIndex; scanLimitIndex = AMS_ADDR_INDEX(seg, BufferScanLimit(buffer)); limitIndex = AMS_ADDR_INDEX(seg, BufferLimit(buffer)); @@ -1211,6 +1210,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); @@ -1230,16 +1230,15 @@ static Res amsIterate(Seg seg, AMSObjectFunction f, void *closure) p = SegBase(seg); limit = SegLimit(seg); - buffer = SegBuffer(seg); + hasBuffer = SegGetBuffer(&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 */ diff --git a/mps/code/poolawl.c b/mps/code/poolawl.c index a544f6bf229..1d815707ae4 100644 --- a/mps/code/poolawl.c +++ b/mps/code/poolawl.c @@ -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, @@ -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 */ AVER(SegWhite(seg) == TraceSetEMPTY); - if(buffer == NULL) { + if (!SegGetBuffer(&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 (SegHasBuffer(seg)) { + if (SegGetBuffer(&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 (SegGetBuffer(&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 = SegGetBuffer(&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 (SegHasBuffer(seg)) { - Buffer buffer = SegBuffer(seg); + if (SegGetBuffer(&buffer, seg)) { if (object == BufferScanLimit(buffer) && BufferScanLimit(buffer) != BufferLimit(buffer)) { /* skip over buffered area */ diff --git a/mps/code/poollo.c b/mps/code/poollo.c index e120e4a99e6..c33ea3af9af 100644 --- a/mps/code/poollo.c +++ b/mps/code/poollo.c @@ -312,11 +312,12 @@ static void loSegReclaim(LOSeg loseg, Trace trace) */ p = base; while(p < limit) { - Buffer buffer = SegBuffer(seg); + Buffer buffer; + Bool hasBuffer = SegGetBuffer(&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 (SegHasBuffer(seg)) { - Buffer buffer = SegBuffer(seg); + if (SegGetBuffer(&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 (SegGetBuffer(&buffer, seg)) { Addr base = SegBase(seg); Index scanLimitIndex = loIndexOfAddr(base, lo, BufferScanLimit(buffer)); Index limitIndex = loIndexOfAddr(base, lo, BufferLimit(buffer)); diff --git a/mps/code/poolsnc.c b/mps/code/poolsnc.c index db0cb5f6173..640d637b24a 100644 --- a/mps/code/poolsnc.c +++ b/mps/code/poolsnc.c @@ -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); AVER(SegPool(seg) == pool); - if (SegBuffer(seg) == buf) { + if (SegGetBuffer(&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); diff --git a/mps/code/seg.c b/mps/code/seg.c index 6f34a310eac..c6f1e46a3fd 100644 --- a/mps/code/seg.c +++ b/mps/code/seg.c @@ -349,6 +349,17 @@ Buffer SegBuffer(Seg seg) } +Bool SegGetBuffer(Buffer *bufferReturn, Seg seg) +{ + Buffer buffer = SegBuffer(seg); + if (buffer != NULL) { + *bufferReturn = buffer; + return TRUE; + } + return FALSE; +} + + /* SegSetBuffer -- change the buffer on a segment */ void SegSetBuffer(Seg seg, Buffer buffer) @@ -369,8 +380,7 @@ Addr SegBufferScanLimit(Seg seg) AVERT(Seg, seg); - buf = SegBuffer(seg); - if (buf == NULL) { + if (!SegGetBuffer(&buf, seg)) { /* Segment is unbuffered: entire segment scannable */ limit = SegLimit(seg); } else { @@ -639,6 +649,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); @@ -654,7 +665,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(!SegHasBuffer(seg) || BufferLimit(SegBuffer(seg)) <= at); + AVER(!SegGetBuffer(&buffer, seg) || BufferLimit(buffer) <= at); if (seg->queued) ShieldFlush(arena); /* see */ diff --git a/mps/code/segsmss.c b/mps/code/segsmss.c index 1b5442547cf..bb9aa73b822 100644 --- a/mps/code/segsmss.c +++ b/mps/code/segsmss.c @@ -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(SegGetBuffer(&segBuf, seg) && segBuf == buffer); amstseg = Seg2AMSTSeg(seg); AVERT(AMSTSeg, amstseg); limit = BufferLimit(buffer); From 2020da56a6040e9d096e4c48e38649af612b2b1c Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Wed, 27 Apr 2016 15:47:26 +0100 Subject: [PATCH 26/52] Replacing segbuffer with version that returns bool and the buffer, and disallowing null to segsetbuffer, adding setunsetbuffer for that case instead. Copied from Perforce Change: 191695 ServerID: perforce.ravenbrook.com --- mps/code/buffer.c | 7 ++--- mps/code/mpm.h | 4 +-- mps/code/mpmst.h | 1 + mps/code/mpmtypes.h | 3 +- mps/code/poolamc.c | 12 +++---- mps/code/poolams.c | 6 ++-- mps/code/poolawl.c | 10 +++--- mps/code/poollo.c | 6 ++-- mps/code/poolsnc.c | 2 +- mps/code/seg.c | 77 +++++++++++++++++++++++++++++---------------- mps/code/segsmss.c | 2 +- 11 files changed, 76 insertions(+), 54 deletions(-) diff --git a/mps/code/buffer.c b/mps/code/buffer.c index 31ba7af7ec5..55253c2c5ff 100644 --- a/mps/code/buffer.c +++ b/mps/code/buffer.c @@ -1174,11 +1174,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; } diff --git a/mps/code/mpm.h b/mps/code/mpm.h index 2e7c251d5d6..31aefeb0232 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -672,9 +672,9 @@ extern Res SegSplit(Seg *segLoReturn, Seg *segHiReturn, Seg seg, Addr at); extern Res SegDescribe(Seg seg, mps_lib_FILE *stream, Count depth); extern void SegSetSummary(Seg seg, RefSet summary); extern Bool SegHasBuffer(Seg seg); -extern Bool SegGetBuffer(Buffer *bufferReturn, Seg seg); -extern Buffer SegBuffer(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); diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index 065088e9cf0..6ae1dd6c9e6 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -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 */ diff --git a/mps/code/mpmtypes.h b/mps/code/mpmtypes.h index 5d8070eaa46..db8845f4f10 100644 --- a/mps/code/mpmtypes.h +++ b/mps/code/mpmtypes.h @@ -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); diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c index 116bfdab465..c3d610392e0 100644 --- a/mps/code/poolamc.c +++ b/mps/code/poolamc.c @@ -197,7 +197,7 @@ static void AMCSegSketch(Seg seg, char *pbSketch, size_t cbSketch) pbSketch[2] = 'W'; /* White */ } - if (!SegGetBuffer(&buffer, seg)) { + if (!SegBuffer(&buffer, seg)) { pbSketch[3] = '_'; } else { Bool mut = BufferIsMutator(buffer); @@ -284,7 +284,7 @@ static Res AMCSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) if(res != ResOK) return res; - if (SegGetBuffer(&buffer, seg)) + if (SegBuffer(&buffer, seg)) init = BufferGetInit(buffer); else init = limit; @@ -1111,7 +1111,7 @@ static Res AMCWhiten(Pool pool, Trace trace, Seg seg) AVERT(Trace, trace); - if (SegGetBuffer(&buffer, seg)) { + if (SegBuffer(&buffer, seg)) { AVERT(Buffer, buffer); if(!BufferIsMutator(buffer)) { /* forwarding buffer */ @@ -1269,7 +1269,7 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn, NailboardClearNewNails(board); p = SegBase(seg); - while (SegGetBuffer(&buffer, seg)) { + while (SegBuffer(&buffer, seg)) { limit = BufferScanLimit(buffer); if(p >= limit) { AVER(p == limit); @@ -1370,7 +1370,7 @@ static Res AMCScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) base = AddrAdd(SegBase(seg), format->headerSize); /* */ - while (SegGetBuffer(&buffer, seg)) { + while (SegBuffer(&buffer, seg)) { limit = AddrAdd(BufferScanLimit(buffer), format->headerSize); if(base >= limit) { @@ -1907,7 +1907,7 @@ static Res AMCAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr) arena = PoolArena(pool); base = SegBase(seg); - if (SegGetBuffer(&buffer, seg)) { + 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 diff --git a/mps/code/poolams.c b/mps/code/poolams.c index 11107488727..8ac7a6e4015 100644 --- a/mps/code/poolams.c +++ b/mps/code/poolams.c @@ -543,7 +543,7 @@ static Res AMSSegDescribe(Seg seg, mps_lib_FILE *stream, Count depth) if (res != ResOK) return res; - hasBuffer = SegGetBuffer(&buffer, seg); + hasBuffer = SegBuffer(&buffer, seg); res = WriteF(stream, depth, " AMS $P\n", (WriteFP)amsseg->ams, @@ -1143,7 +1143,7 @@ static Res AMSWhiten(Pool pool, Trace trace, Seg seg) amsseg->allocTableInUse = TRUE; } - if (SegGetBuffer(&buffer, seg)) { /* */ + if (SegBuffer(&buffer, seg)) { /* */ Index scanLimitIndex, limitIndex; scanLimitIndex = AMS_ADDR_INDEX(seg, BufferScanLimit(buffer)); limitIndex = AMS_ADDR_INDEX(seg, BufferLimit(buffer)); @@ -1230,7 +1230,7 @@ static Res amsIterate(Seg seg, AMSObjectFunction f, void *closure) p = SegBase(seg); limit = SegLimit(seg); - hasBuffer = SegGetBuffer(&buffer, seg); + hasBuffer = SegBuffer(&buffer, seg); while (p < limit) { /* loop over the objects in the segment */ if (hasBuffer && p == BufferScanLimit(buffer) && p != BufferLimit(buffer)) { diff --git a/mps/code/poolawl.c b/mps/code/poolawl.c index 1d815707ae4..5831019a972 100644 --- a/mps/code/poolawl.c +++ b/mps/code/poolawl.c @@ -724,7 +724,7 @@ static Res AWLWhiten(Pool pool, Trace trace, Seg seg) /* see */ AVER(SegWhite(seg) == TraceSetEMPTY); - if (!SegGetBuffer(&buffer, seg)) { + if (!SegBuffer(&buffer, seg)) { awlRangeWhiten(awlseg, 0, awlseg->grains); uncondemnedGrains = (Count)0; } else { @@ -792,7 +792,7 @@ static void AWLGrey(Pool pool, Trace trace, Seg seg) AWLSeg awlseg = MustBeA(AWLSeg, seg); SegSetGrey(seg, TraceSetAdd(SegGrey(seg), trace)); - if (SegGetBuffer(&buffer, seg)) { + if (SegBuffer(&buffer, seg)) { Addr base = SegBase(seg); AWLRangeGrey(awlseg, @@ -880,7 +880,7 @@ static Res awlScanSinglePass(Bool *anyScannedReturn, *anyScannedReturn = FALSE; p = base; - if (SegGetBuffer(&buffer, seg) && BufferScanLimit(buffer) != BufferLimit(buffer)) + if (SegBuffer(&buffer, seg) && BufferScanLimit(buffer) != BufferLimit(buffer)) bufferScanLimit = BufferScanLimit(buffer); else bufferScanLimit = limit; @@ -1029,7 +1029,7 @@ static void AWLReclaim(Pool pool, Trace trace, Seg seg) AWLSeg awlseg = MustBeA(AWLSeg, seg); Addr base = SegBase(seg); Buffer buffer; - Bool hasBuffer = SegGetBuffer(&buffer, seg); + Bool hasBuffer = SegBuffer(&buffer, seg); Format format = pool->format; Count reclaimedGrains = (Count)0; Count preservedInPlaceCount = (Count)0; @@ -1162,7 +1162,7 @@ static void AWLWalk(Pool pool, Seg seg, FormattedObjectsVisitor f, Index i; Buffer buffer; - if (SegGetBuffer(&buffer, seg)) { + if (SegBuffer(&buffer, seg)) { if (object == BufferScanLimit(buffer) && BufferScanLimit(buffer) != BufferLimit(buffer)) { /* skip over buffered area */ diff --git a/mps/code/poollo.c b/mps/code/poollo.c index c33ea3af9af..e796f5690e5 100644 --- a/mps/code/poollo.c +++ b/mps/code/poollo.c @@ -313,7 +313,7 @@ static void loSegReclaim(LOSeg loseg, Trace trace) p = base; while(p < limit) { Buffer buffer; - Bool hasBuffer = SegGetBuffer(&buffer, seg); + Bool hasBuffer = SegBuffer(&buffer, seg); Addr q; Index i; @@ -406,7 +406,7 @@ static void LOWalk(Pool pool, Seg seg, FormattedObjectsVisitor f, Index j; Buffer buffer; - if (SegGetBuffer(&buffer, seg)) { + if (SegBuffer(&buffer, seg)) { if(object == BufferScanLimit(buffer) && BufferScanLimit(buffer) != BufferLimit(buffer)) { /* skip over buffered area */ @@ -659,7 +659,7 @@ static Res LOWhiten(Pool pool, Trace trace, Seg seg) grains = loSegGrains(loseg); /* Whiten allocated objects; leave free areas black. */ - if (SegGetBuffer(&buffer, seg)) { + if (SegBuffer(&buffer, seg)) { Addr base = SegBase(seg); Index scanLimitIndex = loIndexOfAddr(base, lo, BufferScanLimit(buffer)); Index limitIndex = loIndexOfAddr(base, lo, BufferLimit(buffer)); diff --git a/mps/code/poolsnc.c b/mps/code/poolsnc.c index 640d637b24a..fd294087fbc 100644 --- a/mps/code/poolsnc.c +++ b/mps/code/poolsnc.c @@ -568,7 +568,7 @@ static Res SNCFramePop(Pool pool, Buffer buf, AllocFrame frame) AVER(foundSeg); AVER(SegPool(seg) == pool); - if (SegGetBuffer(&segBuf, seg) && segBuf == 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); diff --git a/mps/code/seg.c b/mps/code/seg.c index c6f1e46a3fd..2ab652f4f8d 100644 --- a/mps/code/seg.c +++ b/mps/code/seg.c @@ -336,27 +336,17 @@ void SegSetRankAndSummary(Seg seg, RankSet rankSet, RefSet summary) Bool SegHasBuffer(Seg seg) { - return SegBuffer(seg) != NULL; + Buffer buffer; + return SegBuffer(&buffer, seg); } -/* SegBuffer -- return the buffer of a segment */ +/* SegBuffer -- get the buffer of a segment */ -Buffer SegBuffer(Seg seg) +Bool SegBuffer(Buffer *bufferReturn, Seg seg) { AVERT_CRITICAL(Seg, seg); /* .seg.critical */ - return Method(Seg, seg, buffer)(seg); -} - - -Bool SegGetBuffer(Buffer *bufferReturn, Seg seg) -{ - Buffer buffer = SegBuffer(seg); - if (buffer != NULL) { - *bufferReturn = buffer; - return TRUE; - } - return FALSE; + return Method(Seg, seg, buffer)(bufferReturn, seg); } @@ -365,12 +355,20 @@ Bool SegGetBuffer(Buffer *bufferReturn, 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) @@ -380,7 +378,7 @@ Addr SegBufferScanLimit(Seg seg) AVERT(Seg, seg); - if (!SegGetBuffer(&buf, seg)) { + if (!SegBuffer(&buf, seg)) { /* Segment is unbuffered: entire segment scannable */ limit = SegLimit(seg); } else { @@ -665,7 +663,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(!SegGetBuffer(&buffer, seg) || BufferLimit(buffer) <= at); + AVER(!SegBuffer(&buffer, seg) || BufferLimit(buffer) <= at); if (seg->queued) ShieldFlush(arena); /* see */ @@ -847,11 +845,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; } @@ -860,8 +859,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; } @@ -1401,7 +1408,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; @@ -1410,7 +1417,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; } @@ -1431,6 +1443,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. @@ -1641,7 +1662,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; @@ -1666,7 +1688,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; diff --git a/mps/code/segsmss.c b/mps/code/segsmss.c index bb9aa73b822..cbdbef76c4c 100644 --- a/mps/code/segsmss.c +++ b/mps/code/segsmss.c @@ -603,7 +603,7 @@ static void AMSTStressBufferedSeg(Seg seg, Buffer buffer) AVERT(Seg, seg); AVERT(Buffer, buffer); - AVER(SegGetBuffer(&segBuf, seg) && segBuf == buffer); + AVER(SegBuffer(&segBuf, seg) && segBuf == buffer); amstseg = Seg2AMSTSeg(seg); AVERT(AMSTSeg, amstseg); limit = BufferLimit(buffer); From 5e65f8dc6b85c8762b217da7c1fe36922b0404c9 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Sun, 1 May 2016 09:35:24 +0100 Subject: [PATCH 27/52] Epoch now only counts flips in which objects might have moved. Copied from Perforce Change: 191748 ServerID: perforce.ravenbrook.com --- mps/design/arena.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mps/design/arena.txt b/mps/design/arena.txt index 426e6d6da4f..c50d3476982 100644 --- a/mps/design/arena.txt +++ b/mps/design/arena.txt @@ -567,9 +567,10 @@ _`.ld`: The ``historyStruct`` contains fields used to maintain a history of garbage collection and in particular object motion in order to implement location dependency. -_`.ld.epoch`: The ``epoch`` is the "current epoch". This is the -number of 'flips' of traces in the arena since the arena was created. -From the mutator's point of view locations change atomically at flip. +_`.ld.epoch`: The ``epoch`` is the "current epoch". This is the number +of "flips" of traces, in which objects might have moved, in the arena +since it was created. From the mutator's point of view, locations +change atomically at flip. _`.ld.history`: The ``history`` is a circular buffer of ``LDHistoryLENGTH`` elements of type ``RefSet``. These are the @@ -619,7 +620,7 @@ Document History Copyright and License --------------------- -Copyright © 2001-2014 Ravenbrook Limited . +Copyright © 2001-2016 Ravenbrook Limited . All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options. From 0297b380b9134211c1ef3f4691c2d1cc5a2edb38 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Mon, 2 May 2016 13:06:07 +0100 Subject: [PATCH 28/52] Clear the emergency before removing the trace from busytraces, to avoid violating . Copied from Perforce Change: 191774 ServerID: perforce.ravenbrook.com --- mps/code/global.c | 7 ++++--- mps/code/trace.c | 8 +++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/mps/code/global.c b/mps/code/global.c index fa2eb684c5b..9fd8d7aeed8 100644 --- a/mps/code/global.c +++ b/mps/code/global.c @@ -1,7 +1,7 @@ /* global.c: ARENA-GLOBAL INTERFACES * * $Id$ - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * Portions copyright (C) 2002 Global Graphics Software. * * .sources: See . design.mps.thread-safety is relevant @@ -188,7 +188,8 @@ Bool GlobalsCheck(Globals arenaGlobals) CHECKL(RingCheck(&arenaRing)); CHECKL(BoolCheck(arena->emergency)); - /* There can only be an emergency when a trace is busy. */ + /* .emergency.invariant: There can only be an emergency when a trace + * is busy. */ CHECKL(!arena->emergency || arena->busyTraces != TraceSetEMPTY); if (arenaGlobals->defaultChain != NULL) @@ -1066,7 +1067,7 @@ Bool ArenaEmergency(Arena arena) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2014 Ravenbrook Limited . + * Copyright (C) 2001-2016 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/trace.c b/mps/code/trace.c index 2672799dd38..02c04e4b841 100644 --- a/mps/code/trace.c +++ b/mps/code/trace.c @@ -846,12 +846,14 @@ void TraceDestroyFinished(Trace trace) EVENT1(TraceDestroy, trace); + /* Hopefully the trace reclaimed some memory, so clear any emergency. + * Do this before removing the trace from busyTraces, to avoid + * violating . */ + ArenaSetEmergency(trace->arena, FALSE); + trace->sig = SigInvalid; trace->arena->busyTraces = TraceSetDel(trace->arena->busyTraces, trace); trace->arena->flippedTraces = TraceSetDel(trace->arena->flippedTraces, trace); - - /* Hopefully the trace reclaimed some memory, so clear any emergency. */ - ArenaSetEmergency(trace->arena, FALSE); } From bf65b1e6229ad61a07515884cbaff7a3fa6ed58b Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Mon, 2 May 2016 13:49:43 +0100 Subject: [PATCH 29/52] Patch the mfs pool's alloc method instead of rewriting its class -- the latter violates the class invariants and so asserts when deep checking is turned on. Copied from Perforce Change: 191779 ServerID: perforce.ravenbrook.com --- mps/code/fotest.c | 80 +++++++++++++++------------------------------ mps/code/poolmfs.c | 8 ++--- mps/code/poolmfs.h | 6 ++-- mps/code/poolmv2.c | 18 ++-------- mps/code/poolmvff.c | 18 ++-------- 5 files changed, 36 insertions(+), 94 deletions(-) diff --git a/mps/code/fotest.c b/mps/code/fotest.c index 33ec227b19a..09ba0a2d8db 100644 --- a/mps/code/fotest.c +++ b/mps/code/fotest.c @@ -1,7 +1,7 @@ /* fotest.c: FAIL-OVER TEST * * $Id$ - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * Portions copyright (C) 2002 Global Graphics Software. * * This tests fail-over behaviour in low memory situations. The MVFF @@ -10,9 +10,8 @@ * request due to running out of memory, they fall back to a Freelist * (which has zero memory overhead, at some cost in performance). * - * This is a white box test: it patches the class of the CBS's - * internal block pool (MFS) with a pointer to a dummy class whose - * alloc() method always returns ResMEMORY. + * This is a white box test: it monkey-patches the MFS pool's alloc + * method with a method that always returns a memory error code. */ @@ -36,40 +35,6 @@ #define testLOOPS 10 -/* Accessors for the CBS used to implement a pool. */ - -extern Land _mps_mvff_cbs(Pool); -extern Land _mps_mvt_cbs(Pool); - - -/* "OOM" pool class -- dummy alloc/free pool class whose alloc() - * method always fails and whose free method does nothing. */ - -static Res oomAlloc(Addr *pReturn, Pool pool, Size size) -{ - UNUSED(pReturn); - UNUSED(pool); - UNUSED(size); - switch (rnd() % 3) { - case 0: - return ResRESOURCE; - case 1: - return ResMEMORY; - default: - return ResCOMMIT_LIMIT; - } -} - -DECLARE_CLASS(Pool, OOMPool, AbstractPool); -DEFINE_CLASS(Pool, OOMPool, klass) -{ - INHERIT_CLASS(klass, OOMPool, AbstractPool); - klass->alloc = oomAlloc; - klass->free = PoolTrivFree; - klass->size = sizeof(PoolStruct); -} - - /* make -- allocate one object */ static mps_res_t make(mps_addr_t *p, mps_ap_t ap, size_t size) @@ -86,20 +51,33 @@ static mps_res_t make(mps_addr_t *p, mps_ap_t ap, size_t size) } -/* set_oom -- set blockPool of CBS to OOM or MFS according to argument. */ +/* oomAlloc -- allocation function that always fails + * + * Returns a randomly chosen memory error code. + */ -static void set_oom(Land land, int oom) +static Res oomAlloc(Addr *pReturn, Pool pool, Size size) { - CBS cbs = MustBeA(CBS, land); - SetClassOfPoly(cbs->blockPool, oom ? CLASS(OOMPool) : PoolClassMFS()); + UNUSED(pReturn); + UNUSED(pool); + UNUSED(size); + switch (rnd() % 3) { + case 0: + return ResRESOURCE; + case 1: + return ResMEMORY; + default: + return ResCOMMIT_LIMIT; + } } /* stress -- create an allocation point and allocate in it */ static mps_res_t stress(size_t (*size)(unsigned long, mps_align_t), - mps_align_t alignment, mps_pool_t pool, Land cbs) + mps_align_t alignment, mps_pool_t pool) { + PoolAllocMethod mfs_alloc = CLASS_STATIC(MFSPool).alloc; mps_res_t res = MPS_RES_OK; mps_ap_t ap; unsigned long i, k; @@ -146,9 +124,9 @@ static mps_res_t stress(size_t (*size)(unsigned long, mps_align_t), goto allocFail; } - set_oom(cbs, rnd() % 2); + CLASS_STATIC(MFSPool).alloc = rnd() % 2 ? mfs_alloc : oomAlloc; } - set_oom(cbs, 0); + CLASS_STATIC(MFSPool).alloc = mfs_alloc; allocFail: mps_ap_destroy(ap); @@ -187,10 +165,7 @@ int main(int argc, char *argv[]) MPS_ARGS_ADD(args, MPS_KEY_MVFF_FIRST_FIT, rnd() % 2); die(mps_pool_create_k(&pool, arena, mps_class_mvff(), args), "create MVFF"); } MPS_ARGS_END(args); - { - die(stress(randomSizeAligned, alignment, pool, _mps_mvff_cbs(pool)), - "stress MVFF"); - } + die(stress(randomSizeAligned, alignment, pool), "stress MVFF"); mps_pool_destroy(pool); mps_arena_destroy(arena); @@ -206,10 +181,7 @@ int main(int argc, char *argv[]) MPS_ARGS_ADD(args, MPS_KEY_MVT_FRAG_LIMIT, (rnd() % 101) / 100.0); die(mps_pool_create_k(&pool, arena, mps_class_mvt(), args), "create MVFF"); } MPS_ARGS_END(args); - { - die(stress(randomSizeAligned, alignment, pool, _mps_mvt_cbs(pool)), - "stress MVT"); - } + die(stress(randomSizeAligned, alignment, pool), "stress MVT"); mps_pool_destroy(pool); mps_arena_destroy(arena); @@ -220,7 +192,7 @@ int main(int argc, char *argv[]) /* C. COPYRIGHT AND LICENSE * - * Copyright (c) 2001-2014 Ravenbrook Limited . + * Copyright (c) 2001-2016 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/poolmfs.c b/mps/code/poolmfs.c index 92627aaf4f8..3195eac6102 100644 --- a/mps/code/poolmfs.c +++ b/mps/code/poolmfs.c @@ -1,7 +1,7 @@ /* poolmfs.c: MANUAL FIXED SMALL UNIT POOL * * $Id$ - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * * This is the implementation of the MFS pool class. * @@ -39,10 +39,6 @@ SRCID(poolmfs, "$Id$"); -typedef MFS MFSPool; -DECLARE_CLASS(Pool, MFSPool, AbstractPool); - - /* ROUND -- Round up * * Rounds n up to the nearest multiple of unit. @@ -386,7 +382,7 @@ Bool MFSCheck(MFS mfs) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2014 Ravenbrook Limited . + * Copyright (C) 2001-2016 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/poolmfs.h b/mps/code/poolmfs.h index 70d4124cb42..e17054140c6 100644 --- a/mps/code/poolmfs.h +++ b/mps/code/poolmfs.h @@ -2,7 +2,7 @@ * * $Id$ * - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * * The MFS pool is used to manage small fixed-size chunks of memory. It * stores control structures in the memory it manages, rather than to one @@ -32,6 +32,8 @@ #include "mpscmfs.h" typedef struct MFSStruct *MFS; +typedef MFS MFSPool; +DECLARE_CLASS(Pool, MFSPool, AbstractPool); #define MFSPool(mfs) (&(mfs)->poolStruct) @@ -55,7 +57,7 @@ extern void MFSFinishTracts(Pool pool, MFSTractVisitor visitor, /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2014 Ravenbrook Limited . + * Copyright (C) 2001-2016 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/poolmv2.c b/mps/code/poolmv2.c index f563922588a..f029525b031 100644 --- a/mps/code/poolmv2.c +++ b/mps/code/poolmv2.c @@ -1,7 +1,7 @@ /* poolmv2.c: MANUAL VARIABLE-SIZED TEMPORAL POOL * * $Id$ - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * * .purpose: A manual-variable pool designed to take advantage of * placement according to predicted deathtime. @@ -1352,23 +1352,9 @@ static Bool MVTCheckFit(Addr base, Addr limit, Size min, Arena arena) } -/* Return the CBS of an MVT pool for the benefit of fotest.c. */ - -extern Land _mps_mvt_cbs(Pool); -Land _mps_mvt_cbs(Pool pool) { - MVT mvt; - - AVERT(Pool, pool); - mvt = PoolMVT(pool); - AVERT(MVT, mvt); - - return MVTFreePrimary(mvt); -} - - /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2014 Ravenbrook Limited . + * Copyright (C) 2001-2016 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/poolmvff.c b/mps/code/poolmvff.c index dda5779eddc..de19688a142 100644 --- a/mps/code/poolmvff.c +++ b/mps/code/poolmvff.c @@ -1,7 +1,7 @@ /* poolmvff.c: First Fit Manual Variable Pool * * $Id$ - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * Portions copyright (C) 2002 Global Graphics Software. * * .purpose: This is a pool class for manually managed objects of @@ -796,23 +796,9 @@ static Bool MVFFCheck(MVFF mvff) } -/* Return the CBS of an MVFF pool for the benefit of fotest.c. */ - -extern Land _mps_mvff_cbs(Pool); -Land _mps_mvff_cbs(Pool pool) { - MVFF mvff; - - AVERT(Pool, pool); - mvff = PoolMVFF(pool); - AVERT(MVFF, mvff); - - return MVFFFreePrimary(mvff); -} - - /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2014 Ravenbrook Limited . + * Copyright (C) 2001-2016 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * From 38614c785ed316cc24c1b274ac797121b32b9c8a Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Tue, 3 May 2016 17:25:27 +0100 Subject: [PATCH 30/52] Make shield assertions robust against deep checking -- when shieldcover is called from shieldraise there is one unsynced segment that has not yet been queued. record this fact in a new queuepending flag in the shield structure. Remove incorrect shield assertion "shield->depth == 0 || shield->suspended" -- depth may be increased without suspending the mutator if the segment did not need protecting. Copied from Perforce Change: 191812 ServerID: perforce.ravenbrook.com --- mps/code/mpmst.h | 5 +++-- mps/code/shield.c | 25 ++++++++++++++----------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/mps/code/mpmst.h b/mps/code/mpmst.h index 065088e9cf0..3ab10ec7561 100644 --- a/mps/code/mpmst.h +++ b/mps/code/mpmst.h @@ -695,7 +695,9 @@ typedef struct SortStruct { typedef struct ShieldStruct { Sig sig; /* design.mps.sig */ - Bool inside; /* design.mps.shield.def.inside */ + BOOLFIELD(inside); /* design.mps.shield.def.inside */ + BOOLFIELD(suspended); /* mutator suspended? */ + BOOLFIELD(queuePending); /* queue insertion pending? */ Seg *queue; /* queue of unsynced segs */ Count length; /* number of elements in shield queue */ Index next; /* next free element in shield queue */ @@ -703,7 +705,6 @@ typedef struct ShieldStruct { Count depth; /* sum of depths of all segs */ Count unsynced; /* number of unsynced segments */ Count holds; /* number of holds */ - Bool suspended; /* mutator suspended? */ SortStruct sortStruct; /* workspace for queue sort */ } ShieldStruct; diff --git a/mps/code/shield.c b/mps/code/shield.c index 84b7c0d9c70..6ec0405f612 100644 --- a/mps/code/shield.c +++ b/mps/code/shield.c @@ -18,6 +18,8 @@ SRCID(shield, "$Id$"); void ShieldInit(Shield shield) { shield->inside = FALSE; + shield->suspended = FALSE; + shield->queuePending = FALSE; shield->queue = NULL; shield->length = 0; shield->next = 0; @@ -25,7 +27,6 @@ void ShieldInit(Shield shield) shield->depth = 0; shield->unsynced = 0; shield->holds = 0; - shield->suspended = FALSE; shield->sig = ShieldSig; } @@ -64,11 +65,10 @@ static Bool SegIsSynced(Seg seg); Bool ShieldCheck(Shield shield) { CHECKS(Shield, shield); - CHECKL(BoolCheck(shield->inside)); + /* Can't check Boolean bitfields */ CHECKL(shield->queue == NULL || shield->length > 0); CHECKL(shield->limit <= shield->length); CHECKL(shield->next <= shield->limit); - CHECKL(BoolCheck(shield->suspended)); /* The mutator is not suspended while outside the shield (design.mps.shield.inv.outside.running). */ @@ -78,9 +78,6 @@ Bool ShieldCheck(Shield shield) (design.mps.shield.inv.unsynced.suspended). */ CHECKL(shield->unsynced == 0 || shield->suspended); - /* If any segment is exposed, the mutator is suspended. */ - CHECKL(shield->depth == 0 || shield->suspended); - /* The total depth is zero while outside the shield (design.mps.shield.inv.outside.depth). */ CHECKL(shield->inside || shield->depth == 0); @@ -90,7 +87,7 @@ Bool ShieldCheck(Shield shield) /* Every unsynced segment should be on the queue, because we have to remember to sync it before we return to the mutator. */ - CHECKL(shield->limit >= shield->unsynced); + CHECKL(shield->limit + shield->queuePending >= shield->unsynced); /* The mutator is suspeneded if there are any holds. */ CHECKL(shield->holds == 0 || shield->suspended); @@ -100,18 +97,15 @@ Bool ShieldCheck(Shield shield) 16. */ #if defined(AVER_AND_CHECK_ALL) { - Count depth = 0; Count unsynced = 0; Index i; for (i = 0; i < shield->limit; ++i) { Seg seg = shield->queue[i]; CHECKD(Seg, seg); - depth += SegDepth(seg); if (!SegIsSynced(seg)) ++unsynced; } - CHECKL(depth == shield->depth); - CHECKL(unsynced == shield->unsynced); + CHECKL(unsynced + shield->queuePending == shield->unsynced); } #endif @@ -539,9 +533,14 @@ static void shieldQueue(Arena arena, Seg seg) void (ShieldRaise)(Arena arena, Seg seg, AccessSet mode) { + Shield shield; + SHIELD_AVERT(Arena, arena); SHIELD_AVERT(Seg, seg); AVERT(AccessSet, mode); + shield = ArenaShield(arena); + AVER(!shield->queuePending); + shield->queuePending = TRUE; /* design.mps.shield.inv.prot.shield preserved */ shieldSetSM(ArenaShield(arena), seg, BS_UNION(SegSM(seg), mode)); @@ -549,6 +548,7 @@ void (ShieldRaise)(Arena arena, Seg seg, AccessSet mode) /* Ensure design.mps.shield.inv.unsynced.suspended and design.mps.shield.inv.unsynced.depth */ shieldQueue(arena, seg); + shield->queuePending = FALSE; /* Check queue and segment consistency. */ AVERT(Arena, arena); @@ -619,6 +619,7 @@ static void shieldDebugCheck(Arena arena) Shield shield; Seg seg; Count queued = 0; + Count depth = 0; AVERT(Arena, arena); shield = ArenaShield(arena); @@ -626,6 +627,7 @@ static void shieldDebugCheck(Arena arena) if (SegFirst(&seg, arena)) do { + depth += SegDepth(seg); if (shield->limit == 0) { AVER(!seg->queued); AVER(SegIsSynced(seg)); @@ -638,6 +640,7 @@ static void shieldDebugCheck(Arena arena) } } while(SegNext(&seg, arena, seg)); + AVER(depth == shield->depth); AVER(queued == shield->limit); } #endif From 63b301ca93421ef8cd0d71143d422b126339d39a Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Thu, 2 Jun 2016 15:02:05 +0100 Subject: [PATCH 31/52] New program mpseventpy emits python data structures representing telemetry events. Copied from Perforce Change: 191895 ServerID: perforce.ravenbrook.com --- mps/code/comm.gmk | 7 ++- mps/code/commpost.nmk | 10 +++- mps/code/commpre.nmk | 2 +- mps/code/eventpy.c | 103 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 mps/code/eventpy.c diff --git a/mps/code/comm.gmk b/mps/code/comm.gmk index b61c48a1e0e..5042cb126df 100644 --- a/mps/code/comm.gmk +++ b/mps/code/comm.gmk @@ -73,9 +73,9 @@ endif # EXTRA TARGETS # # Don't build mpseventsql by default (might not have sqlite3 installed), -# but do build mpseventcnv and mpseventtxt. +# but do build mpseventcnv, mpseventpy and mpseventtxt. -EXTRA_TARGETS ?= mpseventcnv mpseventtxt +EXTRA_TARGETS ?= mpseventcnv mpseventpy mpseventtxt # @@ -572,6 +572,9 @@ $(PFM)/$(VARIETY)/zmess: $(PFM)/$(VARIETY)/zmess.o \ $(PFM)/$(VARIETY)/mpseventcnv: $(PFM)/$(VARIETY)/eventcnv.o \ $(PFM)/$(VARIETY)/mps.a +$(PFM)/$(VARIETY)/mpseventpy: $(PFM)/$(VARIETY)/eventpy.o \ + $(PFM)/$(VARIETY)/mps.a + $(PFM)/$(VARIETY)/mpseventtxt: $(PFM)/$(VARIETY)/eventtxt.o \ $(PFM)/$(VARIETY)/mps.a diff --git a/mps/code/commpost.nmk b/mps/code/commpost.nmk index 0917fe86431..2e5a999744c 100644 --- a/mps/code/commpost.nmk +++ b/mps/code/commpost.nmk @@ -1,7 +1,7 @@ # commpost.nmk: SECOND COMMON FRAGMENT FOR PLATFORMS USING NMAKE -*- makefile -*- # # $Id$ -# Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. +# Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. # # DESCRIPTION # @@ -315,6 +315,9 @@ $(PFM)\$(VARIETY)\ztfm.exe: $(PFM)\$(VARIETY)\ztfm.obj \ $(PFM)\$(VARIETY)\mpseventcnv.exe: $(PFM)\$(VARIETY)\eventcnv.obj \ $(PFM)\$(VARIETY)\mps.lib +$(PFM)\$(VARIETY)\mpseventpy.exe: $(PFM)\$(VARIETY)\eventpy.obj \ + $(PFM)\$(VARIETY)\mps.lib + $(PFM)\$(VARIETY)\mpseventtxt.exe: $(PFM)\$(VARIETY)\eventtxt.obj \ $(PFM)\$(VARIETY)\mps.lib @@ -335,6 +338,9 @@ $(PFM)\$(VARIETY)\replaysw.obj: $(PFM)\$(VARIETY)\replay.obj $(PFM)\$(VARIETY)\mpseventcnv.obj: $(PFM)\$(VARIETY)\eventcnv.obj copy $** $@ >nul: +$(PFM)\$(VARIETY)\mpseventpy.obj: $(PFM)\$(VARIETY)\eventpy.obj + copy $** $@ >nul: + $(PFM)\$(VARIETY)\mpseventtxt.obj: $(PFM)\$(VARIETY)\eventtxt.obj copy $** $@ >nul: @@ -385,7 +391,7 @@ $(PFM)\$(VARIETY)\sqlite3.obj: # C. COPYRIGHT AND LICENSE # -# Copyright (C) 2001-2014 Ravenbrook Limited . +# Copyright (c) 2001-2016 Ravenbrook Limited . # All rights reserved. This is an open source license. Contact # Ravenbrook for commercial licensing options. # diff --git a/mps/code/commpre.nmk b/mps/code/commpre.nmk index 7141d83dd2e..8a79096f42c 100644 --- a/mps/code/commpre.nmk +++ b/mps/code/commpre.nmk @@ -105,7 +105,7 @@ TEST_TARGETS=\ # Stand-alone programs go in EXTRA_TARGETS if they should always be # built, or in OPTIONAL_TARGETS if they should only be built if -EXTRA_TARGETS=mpseventcnv.exe mpseventtxt.exe +EXTRA_TARGETS=mpseventcnv.exe mpseventpy.exe mpseventtxt.exe OPTIONAL_TARGETS=mpseventsql.exe # This target records programs that we were once able to build but diff --git a/mps/code/eventpy.c b/mps/code/eventpy.c new file mode 100644 index 00000000000..23d14c5f63c --- /dev/null +++ b/mps/code/eventpy.c @@ -0,0 +1,103 @@ +/* eventpy.c: GENERATE PYTHON INTERFACE TO EVENTS + * + * $Id$ + * Copyright (c) 2016 Ravenbrook Limited. See end of file for license. + * + * This command-line program emits Python data structures that can be + * used to parse an event stream in text format (as output by the + * mpseventcnv program). + */ + +#include /* printf, puts */ + +#include "event.h" + +int main(int argc, char *argv[]) +{ + UNUSED(argc); + UNUSED(argv); + + puts("from collections import namedtuple"); + + printf("__version__ = %d, %d, %d\n", EVENT_VERSION_MAJOR, + EVENT_VERSION_MEDIAN, EVENT_VERSION_MINOR); + + puts("EventKind = namedtuple('EventKind', 'name code doc')"); + puts("class kind:"); +#define ENUM(_, NAME, DOC) \ + printf(" " #NAME " = EventKind('" #NAME "', %d, \"%s\")\n", \ + EventKind ## NAME, DOC); + EventKindENUM(ENUM, _); +#undef ENUM + + puts("kinds = {"); +#define ENUM(_, NAME, _1) \ + printf(" %d: kind." #NAME ",\n", EventKind ## NAME); + EventKindENUM(ENUM, _); +#undef ENUM + puts("}"); + + puts("EventParam = namedtuple('EventParam', 'sort, name')"); + puts("Event = namedtuple('Event', 'name code always kind params')"); + puts("class event:"); +#define EVENT_PARAM(X, INDEX, SORT, NAME) \ + puts(" EventParam('" #SORT "', '" #NAME "'),"); +#define EVENT_DEFINE(X, NAME, CODE, ALWAYS, KIND) \ + printf(" " #NAME " = Event('" #NAME "', %d, %s, kind." #KIND ", [\n", \ + CODE, ALWAYS ? "True" : "False"); \ + EVENT_ ## NAME ## _PARAMS(EVENT_PARAM, X); \ + puts(" ]);"); + EVENT_LIST(EVENT_DEFINE, 0); +#undef EVENT + + puts("events = {"); +#define EVENT_ITEM(X, NAME, CODE, ALWAYS, KIND) \ + printf(" %d: event." #NAME ",\n", CODE); + EVENT_LIST(EVENT_ITEM, 0); +#undef EVENT + puts("}"); + + return 0; +} + + +/* C. COPYRIGHT AND LICENSE + * + * Copyright (c) 2016 Ravenbrook Limited . + * All rights reserved. This is an open source license. Contact + * Ravenbrook for commercial licensing options. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Redistributions in any form must be accompanied by information on how + * to obtain complete source code for this software and any accompanying + * software that uses this software. The source code must either be + * included in the distribution or be available for no more than the cost + * of distribution plus a nominal fee, and must be freely redistributable + * under reasonable conditions. For an executable file, complete source + * code means the source code for all modules it contains. It does not + * include source code for modules or files that typically accompany the + * major components of the operating system on which the executable file + * runs. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ From 04a2891a674b22c3fe837e1fd5e47601193bd94a Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Fri, 2 Sep 2016 13:25:11 +0100 Subject: [PATCH 32/52] Fix typos and other problems with the manual. Copied from Perforce Change: 192091 ServerID: perforce.ravenbrook.com --- mps/design/prot.txt | 12 ++--- mps/design/protocol.txt | 13 ++--- mps/design/strategy.txt | 4 +- mps/manual/source/extensions/mps/designs.py | 33 ++++++------ mps/manual/source/guide/advanced.rst | 6 +-- mps/manual/source/release.rst | 8 +++ mps/manual/source/topic/arena.rst | 6 ++- mps/manual/source/topic/deprecated.rst | 59 +++++++++++++++++---- mps/manual/source/topic/finalization.rst | 2 +- mps/manual/source/topic/format.rst | 11 ++-- mps/manual/source/topic/location.rst | 4 +- mps/manual/source/topic/plinth.rst | 4 +- mps/manual/source/topic/porting.rst | 5 +- mps/manual/source/topic/telemetry.rst | 12 +++-- mps/manual/source/topic/thread.rst | 3 +- 15 files changed, 115 insertions(+), 67 deletions(-) diff --git a/mps/design/prot.txt b/mps/design/prot.txt index 0cdd8d38fcd..a3ff8e35a38 100644 --- a/mps/design/prot.txt +++ b/mps/design/prot.txt @@ -55,11 +55,11 @@ write-protected segment. See ``TraceSegAccess()``.) Design ------ -_`.sol.sync`: If memory protection is not available, only way to meet -`.req.consistent`_, is ensure that no protection is required, -essentially by running the collector until it has no more incremental -work to do. (This makes it impossible to meet real-time requirements -on pause times, but may be the best that can be done.) +_`.sol.sync`: If memory protection is not available, the only way to +meet `.req.consistent`_ is to ensure that no protection is required, +by running the collector until it has no more incremental work to do. +(This makes it impossible to meet real-time requirements on pause +times, but may be the best that can be done.) _`.sol.fault.handle`: The protection module handles protection faults by decoding the context of the fault (see @@ -165,7 +165,7 @@ Document History Copyright and License --------------------- -Copyright © 2013-2014 Ravenbrook Limited . +Copyright © 2013-2016 Ravenbrook Limited . All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options. diff --git a/mps/design/protocol.txt b/mps/design/protocol.txt index b2bd308adeb..f3ed7246896 100644 --- a/mps/design/protocol.txt +++ b/mps/design/protocol.txt @@ -90,8 +90,8 @@ describes it, like this:: _`.overview.prefix`: We make use of the fact that we can cast between structures with common prefixes, or between structures and their first -members, to provide dynamic typing and subtyping (see [K&R_1998]_, -A.8.3). +members, to provide dynamic typing and subtyping (see +[Kernighan_1988]_, A.8.3). _`.overview.method`: The ``InstClassStruct`` it itself at the start of a class structure contains pointers to functions that can be called to @@ -575,6 +575,8 @@ level. The level is statically defined using enum constants, and the id is the address of the canonical class object, so the test is fast and simple. +.. _RB: http://www.ravenbrook.com/consultants/rb/ + A. References ------------- @@ -582,14 +584,14 @@ A. References .. [Cohen_1991] "Type-Extension Type Tests Can Be Performed In Constant Time"; Norman H Cohen; IBM Thomas J Watson Research Center; ACM Transactions on Programming Languages and Systems, - Vol. 13 No. 4, pp626-629; 1991-10. + Vol. 13 No. 4, pp. 626-629; 1991-10. .. [Gibbs_2004] "Fast Dynamic Casting"; Michael Gibbs, Bjarne Stroustrup; 2004; . -.. [K&R_1988] "The C Programming language 2nd Edition"; - Brian W. Kernighan, Dennis M. Ritchie; 1998. +.. [Kernighan_1988] "The C Programming language 2nd Edition"; Brian W. + Kernighan, Dennis M. Ritchie; 1988. B. Document History @@ -612,7 +614,6 @@ B. Document History - 2016-04-19 RB_ Miscellaneous clean-up in response to review by GDR_. -.. _RB: http://www.ravenbrook.com/consultants/rb/ .. _GDR: http://www.ravenbrook.com/consultants/gdr/ diff --git a/mps/design/strategy.txt b/mps/design/strategy.txt index db6965c59e5..ab22849df4a 100644 --- a/mps/design/strategy.txt +++ b/mps/design/strategy.txt @@ -549,11 +549,13 @@ clock time when the MPS was entered; ``moreWork`` and ``tracedWork`` are the results of the last call to ``TracePoll()``. _`.policy.poll.impl`: The implementation keep doing work until either -the maximum pause time is exceeded (see design.mps.arena.pause-time_), +the maximum pause time is exceeded (see `design.mps.arena.pause-time`_), or there is no more work to do. Then it schedules the next collection so that there is approximately one call to ``TracePoll()`` for every ``ArenaPollALLOCTIME`` bytes of allocation. +.. _design.mps.arena.pause-time: arena#pause-time + References ---------- diff --git a/mps/manual/source/extensions/mps/designs.py b/mps/manual/source/extensions/mps/designs.py index 18149092a19..234e99d2c94 100644 --- a/mps/manual/source/extensions/mps/designs.py +++ b/mps/manual/source/extensions/mps/designs.py @@ -32,7 +32,7 @@ TYPES = ''' mode = re.compile(r'\.\. mode: .*\n') prefix = re.compile(r'^:Tag: ([a-z][a-z.0-9-]*[a-z0-9])$', re.MULTILINE) -rst_tag = re.compile(r'^:(?:Author|Date|Status|Revision|Copyright|Organization|Format|Index terms):.*?$\n', re.MULTILINE | re.IGNORECASE) +rst_tag = re.compile(r'^:(?:Author|Date|Status|Revision|Copyright|Organization|Format|Index terms|Readership):.*?$\n', re.MULTILINE | re.IGNORECASE) mps_tag = re.compile(r'_`\.([a-z][A-Za-z.0-9_-]*[A-Za-z0-9])`:') mps_ref = re.compile(r'`(\.[a-z][A-Za-z.0-9_-]*[A-Za-z0-9])`_(?: )?') funcdef = re.compile(r'^``([^`]*\([^`]*\))``$', re.MULTILINE) @@ -61,10 +61,10 @@ def secnum_sub(m): # .. [THVV_1995] Tom Van Vleck. 1995. "`Structure Marking `__". citation = re.compile( r''' - ^\.\.\s+(?P\[.*?\])\s* - "(?P[^"]*?)"\s* - ;\s*(?P<author>[^;]*?)\s* - (?:;\s*(?P<organization>[^;]*?)\s*)? + ^\.\.\s+(?P<ref>\[[^\n\]]+\])\s* + "(?P<title>[^"]+?)"\s* + ;\s*(?P<author>[^;]+?)\s* + (?:;\s*(?P<organization>[^;]+?)\s*)? ;\s*(?P<date>[0-9-]+)\s* (?:;\s*<\s*(?P<url>[^>]*?)\s*>\s*)? \. @@ -72,21 +72,18 @@ citation = re.compile( re.VERBOSE | re.MULTILINE | re.IGNORECASE | re.DOTALL ) def citation_sub(m): - groups = m.groupdict() - for key in groups: - if groups[key]: - groups[key] = re.sub(r'\s+', ' ', groups[key]) - result = '.. {ref} {author}.'.format(**groups) - if groups.get('organization'): - result += ' {organization}.'.format(**groups) - result += ' {date}.'.format(**groups) - if groups.get('url'): - result += ' "`{title} <{url}>`__".'.format(**groups) + groups = {k: re.sub(r'\s+', ' ', v) for k, v in m.groupdict().items() if v} + fmt = '.. {ref} {author}.' + if 'organization' in groups: + fmt += ' {organization}.' + fmt += ' {date}.' + if 'url' in groups: + fmt += ' "`{title} <{url}>`__".' else: - result += ' "{title}".'.format(**groups) - return result + fmt += ' "{title}".' + return fmt.format(**groups) -index = re.compile(r'^:Index\s+terms:(.*$\n(?:[ \t]+.*$\n)*)', re.MULTILINE | re.IGNORECASE) +index = re.compile(r'^:Index\s+terms:(.*$\n(?:[ \t]+.*$\n)*)', re.IGNORECASE) # <http://sphinx-doc.org/markup/misc.html#directive-index> index_term = re.compile(r'^\s*(\w+):\s*(.*?)\s*$', re.MULTILINE) diff --git a/mps/manual/source/guide/advanced.rst b/mps/manual/source/guide/advanced.rst index b56edf14fa4..c7cc53af363 100644 --- a/mps/manual/source/guide/advanced.rst +++ b/mps/manual/source/guide/advanced.rst @@ -141,9 +141,9 @@ releasing the resource (here, the Scheme function But this raises the possibility that a port will be closed twice: once via ``close-input-port`` and a second time via finalization. So it's -necessary to make ports robust against be closed multiple times. The -toy Scheme interpreter does so by setting ``stream`` to ``NULL``: this -ensures that the file handle won't be closed more than once. +necessary to make ports robust against being closed multiple times. +The toy Scheme interpreter does so by setting ``stream`` to ``NULL``: +this ensures that the file handle won't be closed more than once. .. code-block:: c :emphasize-lines: 6 diff --git a/mps/manual/source/release.rst b/mps/manual/source/release.rst index d39467f495c..db37e516ca3 100644 --- a/mps/manual/source/release.rst +++ b/mps/manual/source/release.rst @@ -508,6 +508,14 @@ Interface changes ``dont-handle-bad-access`` or to request special handling of ``SIGBUS``. +#. The (undocumented) reservoir functions + :c:func:`mps_ap_fill_with_reservoir_permit`, + :c:func:`mps_reservoir_available`, :c:func:`mps_reservoir_limit`, + :c:func:`mps_reservoir_limit_set`, and + :c:func:`mps_reserve_with_reservoir_permit`, together with the + ``has_reservoir_permit`` arguments to :c:func:`mps_sac_alloc` and + :c:func:`MPS_SAC_ALLOC_FAST` are deprecated. + Other changes ............. diff --git a/mps/manual/source/topic/arena.rst b/mps/manual/source/topic/arena.rst index ba46a746b6f..0aed4a1b582 100644 --- a/mps/manual/source/topic/arena.rst +++ b/mps/manual/source/topic/arena.rst @@ -15,8 +15,10 @@ An arena is an object that encapsulates the state of the Memory Pool System, and tells it where to get the memory it manages. You typically start a session with the MPS by creating an arena with :c:func:`mps_arena_create_k` and end the session by destroying it with -:c:func:`mps_arena_destroy`. The only function you might need to call -before making an arena is :c:func:`mps_telemetry_control`. +:c:func:`mps_arena_destroy`. The only functions you might need to call +before making an arena are :term:`telemetry` functions like +:c:func:`mps_telemetry_set` and the :term:`plinth` function +:c:func:`mps_lib_assert_fail_install`. Before destroying an arena, you must first destroy all objects and data in it, as usual for abstract data types in the MPS. If you can't diff --git a/mps/manual/source/topic/deprecated.rst b/mps/manual/source/topic/deprecated.rst index cb1cbc6d8f4..95da1a44d90 100644 --- a/mps/manual/source/topic/deprecated.rst +++ b/mps/manual/source/topic/deprecated.rst @@ -25,6 +25,15 @@ supported interface. Deprecated in version 1.115 ........................... +.. c:function:: mps_res_t mps_ap_fill_with_reservoir_permit(mps_addr_t *p_o, mps_ap_t mps_ap, size_t size) + + .. deprecated:: + + Identical to :c:func:`mps_ap_fill`, which should be used + instead. Formerly, this function gave the MPS permission to + draw on the ‘low-memory reservoir’, but this no longer exists. + + .. c:type:: typedef mps_pool_class_t mps_class_t .. deprecated:: @@ -118,6 +127,41 @@ Deprecated in version 1.115 is the sum of allocated space and free space. +.. c:function:: mps_res_t mps_reserve_with_reservoir_permit(mps_addr_t *p_o, mps_ap_t mps_ap, size_t size) + + .. deprecated:: + + Identical to :c:func:`mps_reserve`, which should be used + instead. Formerly, this function gave the MPS permission to + draw on the ‘low-memory reservoir’, but this no longer + exists. + + +.. c:function:: void mps_reservoir_limit_set(mps_arena_t arena, size_t size) + + .. deprecated:: + + Has no effect. Formerly, it updated the recommended size of + the ‘low-memory reservoir’, but this no longer exists. + + +.. c:function:: size_t mps_reservoir_limit(mps_arena_t arena) + + .. deprecated:: + + Returns zero. Formerly, it returned the recommended size of + the ‘low-memory reservoir’, but this no longer exists. + + +.. c:function:: size_t mps_reservoir_available(mps_arena_t arena) + + .. deprecated:: + + Returns zero. Formerly, it returned the size of the available + memory in the ‘low-memory reservoir’, but this no longer + exists. + + .. c:function:: mps_res_t mps_root_create_reg(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_thr_t thr, mps_reg_scan_t reg_scan, void *p, size_t s) .. deprecated:: @@ -275,16 +319,15 @@ Deprecated in version 1.115 .. deprecated:: - This function is equivalent to:: + Use :c:func:`mps_root_create_area_tagged` instead, passing + zero for the ``pattern`` argument. This function is equivalent + to:: mps_root_create_area_tagged(root_o, arena, rank, rm, base, base + size, mps_scan_area_tagged, mask, 0) - Use :c:func:`mps_root_create_area_masked` instead, passing - zero for the ``pattern`` argument. - Register a :term:`root` that consists of a vector of :term:`tagged references` whose pattern is zero. @@ -323,18 +366,12 @@ Deprecated in version 1.115 :ref:`topic-scanning`. - .. note:: - - :term:`Client programs` are not expected to - write scanning functions of this type. The built-in MPS - function :c:func:`mps_stack_scan_ambig` must be used. - .. c:function:: mps_reg_scan_t mps_stack_scan_ambig .. deprecated:: - Use :c:func:`mps_root_create_thread` instead, passing + Use :c:func:`mps_root_create_thread_tagged` instead, passing ``sizeof(mps_word_t) - 1`` for the ``mask`` argument, and ``0`` for the ``pattern`` argument. diff --git a/mps/manual/source/topic/finalization.rst b/mps/manual/source/topic/finalization.rst index 7edadb9e3cc..c0648599ab2 100644 --- a/mps/manual/source/topic/finalization.rst +++ b/mps/manual/source/topic/finalization.rst @@ -194,7 +194,7 @@ Cautions are finalized is to maintain a table of :term:`weak references (1)` to all such objects. The weak references don't prevent the objects from being finalized, but you can iterate - over the list at an appropriate point and finalize any + over the table at an appropriate point and finalize any remaining objects yourself. #. Not all :term:`pool classes` support finalization. In general, only diff --git a/mps/manual/source/topic/format.rst b/mps/manual/source/topic/format.rst index ec1f707aea3..ccf6c27ec65 100644 --- a/mps/manual/source/topic/format.rst +++ b/mps/manual/source/topic/format.rst @@ -243,11 +243,12 @@ Cautions a. call library code; - b. perform a non-local exit (for example, by calling ``longjmp``); + b. perform a non-local exit (for example, by throwing an exception, + or calling :c:func:`longjmp`); - c. call any functions in the MPS other than the fix functions - (:c:func:`mps_fix`, :c:func:`MPS_FIX1`, :c:func:`MPS_FIX12`, and - :c:func:`MPS_FIX2`). + c. call any functions or macros in the MPS other than the fix + macros :c:func:`MPS_FIX1`, :c:func:`MPS_FIX12`, and + :c:func:`MPS_FIX2`. It's permissible to call other functions in the client program, but see :c:func:`MPS_FIX_CALL` for a restriction on passing the @@ -368,7 +369,7 @@ Format methods object format has a non-zero :c:macro:`MPS_KEY_FMT_HEADER_SIZE`. - .. note:: + .. note:: The MPS will ask for padding objects of any size aligned to the pool alignment, no matter what size objects the pool diff --git a/mps/manual/source/topic/location.rst b/mps/manual/source/topic/location.rst index fa928756a69..aa70a071683 100644 --- a/mps/manual/source/topic/location.rst +++ b/mps/manual/source/topic/location.rst @@ -77,8 +77,8 @@ the function :c:func:`mps_ld_reset`. .. note:: - This means that it is not possible to statically create a location - dependency that has been reset. + It is not possible to statically create a location dependency that + has been reset. You can call :c:func:`mps_ld_reset` at any later point to clear all dependencies from the structure. For example, this is normally done diff --git a/mps/manual/source/topic/plinth.rst b/mps/manual/source/topic/plinth.rst index f771f6c1c31..e138cb60347 100644 --- a/mps/manual/source/topic/plinth.rst +++ b/mps/manual/source/topic/plinth.rst @@ -468,8 +468,8 @@ Library module A :term:`plinth` function to supply a default value for the :term:`telemetry filter` from the environment. See - :c:func:`mps_telemetry_control` for more information on the - significant of the value. + :envvar:`MPS_TELEMETRY_CONTROL` for more information on the + significance of the value. Returns the default value of the telemetry filter, as derived from the environment. It is recommended that the environment be diff --git a/mps/manual/source/topic/porting.rst b/mps/manual/source/topic/porting.rst index 0d04c04f3a4..571e7dc9b09 100644 --- a/mps/manual/source/topic/porting.rst +++ b/mps/manual/source/topic/porting.rst @@ -66,9 +66,8 @@ usable. There is a generic implementation in ``protan.c``, which can't provide memory protection, so it forces memory to be scanned until - that there is no further need to protect it. This means it can't - support incremental collection, and has no control over pause - times. + there is no further need to protect it. This means it can't support + incremental collection, and has no control over pause times. #. The **protection mutator context** module figures out what the :term:`mutator` was doing when it caused a :term:`protection diff --git a/mps/manual/source/topic/telemetry.rst b/mps/manual/source/topic/telemetry.rst index 2c9136ce7da..09445c9a66c 100644 --- a/mps/manual/source/topic/telemetry.rst +++ b/mps/manual/source/topic/telemetry.rst @@ -491,9 +491,10 @@ used in queries, for example: .. note:: If the ``User`` event category is not turned on in the - :term:`telemetry filter` (via :c:func:`mps_telemetry_control`) - then the string is not sent to the telemetry stream. A label - is still returned in this case, but it is useless. + :term:`telemetry filter` (via :c:func:`mps_telemetry_set` or + :envvar:`MPS_TELEMETRY_CONTROL`) then the string is not sent + to the telemetry stream. A label is still returned in this + case, but it is useless. .. c:function:: void mps_telemetry_label(mps_addr_t addr, mps_label_t label) @@ -512,8 +513,9 @@ used in queries, for example: .. note:: If the ``User`` event category is not turned on in the - :term:`telemetry filter` (via :c:func:`mps_telemetry_control`) - then calling this function has no effect. + :term:`telemetry filter` (via :c:func:`mps_telemetry_set` or + :envvar:`MPS_TELEMETRY_CONTROL`) then calling this function + has no effect. .. index:: diff --git a/mps/manual/source/topic/thread.rst b/mps/manual/source/topic/thread.rst index 0697daac301..e814fbe939a 100644 --- a/mps/manual/source/topic/thread.rst +++ b/mps/manual/source/topic/thread.rst @@ -44,8 +44,7 @@ access that memory. This means that threads must be registered with the MPS by calling :c:func:`mps_thread_reg` (and thread roots created; see :ref:`topic-root-thread`). -For simplicity, we recommend that a thread must be registered with an -:term:`arena` if: +A thread must be registered with an :term:`arena` if: * its :term:`control stack` and :term:`registers` form a root (this is enforced by :c:func:`mps_root_create_thread`); or From b050eaefb013e64f5020a3aac448df4f08d0b575 Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Fri, 2 Sep 2016 13:27:05 +0100 Subject: [PATCH 33/52] Deprecation of reservoir functions was in release 1.115. Copied from Perforce Change: 192092 ServerID: perforce.ravenbrook.com --- mps/manual/source/release.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mps/manual/source/release.rst b/mps/manual/source/release.rst index db37e516ca3..fdf28461f50 100644 --- a/mps/manual/source/release.rst +++ b/mps/manual/source/release.rst @@ -112,6 +112,14 @@ Interface changes #. The :ref:`pool-snc` pool class now implements :c:func:`mps_pool_total_size` and :c:func:`mps_pool_free_size`. +#. The (undocumented) reservoir functions + :c:func:`mps_ap_fill_with_reservoir_permit`, + :c:func:`mps_reservoir_available`, :c:func:`mps_reservoir_limit`, + :c:func:`mps_reservoir_limit_set`, and + :c:func:`mps_reserve_with_reservoir_permit`, together with the + ``has_reservoir_permit`` arguments to :c:func:`mps_sac_alloc` and + :c:func:`MPS_SAC_ALLOC_FAST` are now deprecated. + Other changes ............. @@ -508,14 +516,6 @@ Interface changes ``dont-handle-bad-access`` or to request special handling of ``SIGBUS``. -#. The (undocumented) reservoir functions - :c:func:`mps_ap_fill_with_reservoir_permit`, - :c:func:`mps_reservoir_available`, :c:func:`mps_reservoir_limit`, - :c:func:`mps_reservoir_limit_set`, and - :c:func:`mps_reserve_with_reservoir_permit`, together with the - ``has_reservoir_permit`` arguments to :c:func:`mps_sac_alloc` and - :c:func:`MPS_SAC_ALLOC_FAST` are deprecated. - Other changes ............. From c737a08bc20588fa90259c11b54ac01e90ad3a03 Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Fri, 2 Sep 2016 14:11:08 +0100 Subject: [PATCH 34/52] Fix assertion text in the manual. Place a cross-reference by each assertion the appears in the manual, to assist in keeping the manual up to date. Copied from Perforce Change: 192097 ServerID: perforce.ravenbrook.com --- mps/code/buffer.c | 2 +- mps/code/dbgpool.c | 8 ++++---- mps/code/format.c | 6 +++--- mps/code/global.c | 10 +++++----- mps/code/lockix.c | 6 +++--- mps/code/lockli.c | 6 +++--- mps/code/lockw3.c | 6 +++--- mps/code/locus.c | 2 +- mps/code/mpsi.c | 6 +++--- mps/code/poolams.c | 2 +- mps/code/poolsnc.c | 2 +- mps/code/seg.c | 2 +- mps/code/trace.c | 4 ++-- mps/design/check.txt | 14 +++++++++++++- mps/manual/source/topic/error.rst | 4 ++-- 15 files changed, 46 insertions(+), 34 deletions(-) diff --git a/mps/code/buffer.c b/mps/code/buffer.c index a35b7b55a12..1c9cca6b7da 100644 --- a/mps/code/buffer.c +++ b/mps/code/buffer.c @@ -485,7 +485,7 @@ Res BufferReserve(Addr *pReturn, Buffer buffer, Size size) AVERT(Buffer, buffer); AVER(size > 0); AVER(SizeIsAligned(size, BufferPool(buffer)->alignment)); - AVER(BufferIsReady(buffer)); + AVER(BufferIsReady(buffer)); /* <design/check/#.common> */ /* Is there enough room in the unallocated portion of the buffer to */ /* satisfy the request? If so, just increase the alloc marker and */ diff --git a/mps/code/dbgpool.c b/mps/code/dbgpool.c index 8068dc64b97..69b39650034 100644 --- a/mps/code/dbgpool.c +++ b/mps/code/dbgpool.c @@ -1,7 +1,7 @@ /* dbgpool.c: POOL DEBUG MIXIN * * $Id$ - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * Portions copyright (C) 2002 Global Graphics Software. * * .source: design.mps.object-debug @@ -523,7 +523,7 @@ static void fenceFree(PoolDebugMixin debug, { Size alignedFenceSize, alignedSize; - ASSERT(fenceCheck(debug, pool, old, size), "fencepost check on free"); + ASSERT(fenceCheck(debug, pool, old, size), "fencepost check on free"); /* <design/check/#.common> */ alignedFenceSize = SizeAlignUp(debug->fenceSize, PoolAlignment(pool)); alignedSize = SizeAlignUp(size, PoolAlignment(pool)); @@ -738,7 +738,7 @@ void DebugPoolFreeCheck(Pool pool, Addr base, Addr limit) AVERT(PoolDebugMixin, debug); if (debug->freeSize != 0) ASSERT(freeCheck(debug, pool, base, limit), - "free space corrupted on release"); + "free space corrupted on release"); /* <design/check/#.common> */ } } @@ -784,7 +784,7 @@ void PoolClassMixInDebug(PoolClass klass) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>. + * Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/format.c b/mps/code/format.c index fadeadce489..b9c4a59fb14 100644 --- a/mps/code/format.c +++ b/mps/code/format.c @@ -1,7 +1,7 @@ /* format.c: OBJECT FORMATS * * $Id$ - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * Portions copyright (c) 2002 Global Graphics Software. * * DESIGN @@ -168,7 +168,7 @@ Res FormatCreate(Format *formatReturn, Arena arena, ArgList args) void FormatDestroy(Format format) { AVERT(Format, format); - AVER(format->poolCount == 0); + AVER(format->poolCount == 0); /* <design/check/#.common> */ RingRemove(&format->arenaRing); @@ -250,7 +250,7 @@ Res FormatDescribe(Format format, mps_lib_FILE *stream, Count depth) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>. + * Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/global.c b/mps/code/global.c index 9fd8d7aeed8..02b2f04928e 100644 --- a/mps/code/global.c +++ b/mps/code/global.c @@ -464,12 +464,12 @@ void GlobalsPrepareToDestroy(Globals arenaGlobals) * and so RingCheck dereferences a pointer into that unmapped memory * and we get a crash instead of an assertion. See job000652. */ - AVER(RingIsSingle(&arena->formatRing)); - AVER(RingIsSingle(&arena->chainRing)); + AVER(RingIsSingle(&arena->formatRing)); /* <design/check/#.common> */ + AVER(RingIsSingle(&arena->chainRing)); /* <design/check/#.common> */ AVER(RingIsSingle(&arena->messageRing)); - AVER(RingIsSingle(&arena->threadRing)); + AVER(RingIsSingle(&arena->threadRing)); /* <design/check/#.common> */ AVER(RingIsSingle(&arena->deadRing)); - AVER(RingIsSingle(&arenaGlobals->rootRing)); + AVER(RingIsSingle(&arenaGlobals->rootRing)); /* <design/check/#.common> */ for(rank = RankMIN; rank < RankLIMIT; ++rank) AVER(RingIsSingle(&arena->greyRing[rank])); @@ -479,7 +479,7 @@ void GlobalsPrepareToDestroy(Globals arenaGlobals) * 2. arena->controlPoolStruct.blockPoolStruct * 3. arena->controlPoolStruct.spanPoolStruct */ - AVER(RingLength(&arenaGlobals->poolRing) == 4); + AVER(RingLength(&arenaGlobals->poolRing) == 4); /* <design/check/#.common> */ } diff --git a/mps/code/lockix.c b/mps/code/lockix.c index c982bf0cb17..d43e458f430 100644 --- a/mps/code/lockix.c +++ b/mps/code/lockix.c @@ -1,7 +1,7 @@ /* lockix.c: RECURSIVE LOCKS FOR POSIX SYSTEMS * * $Id$ - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * * .posix: The implementation uses a POSIX interface, and should be reusable * for many Unix-like operating systems. @@ -122,7 +122,7 @@ void (LockClaim)(Lock lock) res = pthread_mutex_lock(&lock->mut); /* pthread_mutex_lock will error if we own the lock already. */ - AVER(res == 0); + AVER(res == 0); /* <design/check/#.common> */ /* This should be the first claim. Now we own the mutex */ /* it is ok to check this. */ @@ -245,7 +245,7 @@ void (LockReleaseGlobal)(void) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>. + * Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/lockli.c b/mps/code/lockli.c index 0dc98fb8a25..a3369abda90 100644 --- a/mps/code/lockli.c +++ b/mps/code/lockli.c @@ -1,7 +1,7 @@ /* lockli.c: RECURSIVE LOCKS FOR POSIX SYSTEMS * * $Id$ - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * * .linux: This implementation currently just supports LinuxThreads * (platform MPS_OS_LI), Single Unix i/f. @@ -136,7 +136,7 @@ void (LockClaim)(Lock lock) res = pthread_mutex_lock(&lock->mut); /* pthread_mutex_lock will error if we own the lock already. */ - AVER(res == 0); + AVER(res == 0); /* <design/check/#.common> */ /* This should be the first claim. Now we own the mutex */ /* it is ok to check this. */ @@ -259,7 +259,7 @@ void (LockReleaseGlobal)(void) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>. + * Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/lockw3.c b/mps/code/lockw3.c index 53da970aed2..daf2473d4e3 100644 --- a/mps/code/lockw3.c +++ b/mps/code/lockw3.c @@ -1,7 +1,7 @@ /* lockw3.c: RECURSIVE LOCKS IN WIN32 * * $Id$ - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * * .design: These are implemented using critical sections. * See the section titled "Synchronization functions" in the Groups @@ -75,7 +75,7 @@ void (LockClaim)(Lock lock) EnterCriticalSection(&lock->cs); /* This should be the first claim. Now we are inside the * critical section it is ok to check this. */ - AVER(lock->claims == 0); + AVER(lock->claims == 0); /* <design/check/#.common> */ lock->claims = 1; } @@ -158,7 +158,7 @@ void (LockReleaseGlobal)(void) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>. + * Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/locus.c b/mps/code/locus.c index 4e68cbcb8c8..30f8e4a5076 100644 --- a/mps/code/locus.c +++ b/mps/code/locus.c @@ -269,7 +269,7 @@ void ChainDestroy(Chain chain) size_t i; AVERT(Chain, chain); - AVER(chain->activeTraces == TraceSetEMPTY); + AVER(chain->activeTraces == TraceSetEMPTY); /* <design/check/#.common> */ arena = chain->arena; genCount = chain->genCount; diff --git a/mps/code/mpsi.c b/mps/code/mpsi.c index 2bc48179b3a..080b660fac3 100644 --- a/mps/code/mpsi.c +++ b/mps/code/mpsi.c @@ -1,7 +1,7 @@ /* mpsi.c: MEMORY POOL SYSTEM C INTERFACE LAYER * * $Id$ - * Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * Portions copyright (c) 2002 Global Graphics Software. * * .purpose: This code bridges between the MPS interface to C, @@ -1060,7 +1060,7 @@ mps_res_t mps_ap_fill(mps_addr_t *p_o, mps_ap_t mps_ap, size_t size) AVER(p_o != NULL); AVERT(Buffer, buf); AVER(size > 0); - AVER(SizeIsAligned(size, BufferPool(buf)->alignment)); + AVER(SizeIsAligned(size, BufferPool(buf)->alignment)); /* <design/check/#.common> */ res = BufferFill(&p, buf, size); @@ -2141,7 +2141,7 @@ void _mps_args_set_key(mps_arg_s args[MPS_ARGS_MAX], unsigned i, /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>. + * Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/poolams.c b/mps/code/poolams.c index 8218fa53f81..96a82628d60 100644 --- a/mps/code/poolams.c +++ b/mps/code/poolams.c @@ -1491,7 +1491,7 @@ static Res AMSFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) case RankFINAL: case RankWEAK: AVER_CRITICAL(AddrIsAligned(base, PoolAlignment(pool))); - AVER_CRITICAL(AMS_ALLOCED(seg, i)); + AVER_CRITICAL(AMS_ALLOCED(seg, i)); /* <design/check/#.common> */ if (AMS_IS_WHITE(seg, i)) { ss->wasMarked = FALSE; if (ss->rank == RankWEAK) { /* then splat the reference */ diff --git a/mps/code/poolsnc.c b/mps/code/poolsnc.c index db0cb5f6173..ae8f11d64aa 100644 --- a/mps/code/poolsnc.c +++ b/mps/code/poolsnc.c @@ -564,7 +564,7 @@ static Res SNCFramePop(Pool pool, Buffer buf, AllocFrame frame) arena = PoolArena(pool); addr = (Addr)frame; foundSeg = SegOfAddr(&seg, arena, addr); - AVER(foundSeg); + AVER(foundSeg); /* <design/check/#.common> */ AVER(SegPool(seg) == pool); if (SegBuffer(seg) == buf) { diff --git a/mps/code/seg.c b/mps/code/seg.c index 88b34fe6e55..fe52b961898 100644 --- a/mps/code/seg.c +++ b/mps/code/seg.c @@ -1086,7 +1086,7 @@ static void gcSegFinish(Seg seg) gcseg->sig = SigInvalid; /* Don't leave a dangling buffer allocating into hyperspace. */ - AVER(gcseg->buffer == NULL); + AVER(gcseg->buffer == NULL); /* <design/check/#.common> */ RingFinish(&gcseg->greyRing); diff --git a/mps/code/trace.c b/mps/code/trace.c index 02c04e4b841..cd056b1a178 100644 --- a/mps/code/trace.c +++ b/mps/code/trace.c @@ -1178,7 +1178,7 @@ static Res traceScanSegRes(TraceSet ts, Rank rank, Arena arena, Seg seg) /* .verify.segsummary: were the seg contents, as found by this * scan, consistent with the recorded SegSummary? */ - AVER(RefSetSub(ScanStateUnfixedSummary(ss), SegSummary(seg))); + AVER(RefSetSub(ScanStateUnfixedSummary(ss), SegSummary(seg))); /* <design/check/#.common> */ /* Write barrier deferral -- see design.mps.write-barrier.deferral. */ /* Did the segment refer to the white set? */ @@ -1373,7 +1373,7 @@ mps_res_t _mps_fix2(mps_ss_t mps_ss, mps_addr_t *mps_ref_io) if (!BTGet(chunk->allocTable, i)) { /* Reference points into a chunk but not to an allocated tract. * See <design/trace/#exact.legal> */ - AVER_CRITICAL(ss->rank < RankEXACT); + AVER_CRITICAL(ss->rank < RankEXACT); /* <design/check/#.common> */ goto done; } diff --git a/mps/design/check.txt b/mps/design/check.txt index 2cf5bf091c6..7f89027c5b4 100644 --- a/mps/design/check.txt +++ b/mps/design/check.txt @@ -122,6 +122,18 @@ reference this tag. The structure could be considered for addition to ``mpmst.h``. +Common assertions +----------------- + +_`.common`: Some assertions are commonly triggered by mistakes in the +:term:`client program`. These are listed in the section "Common +assertions and their causes" in the MPS Reference, together with an +explanation of their likely cause, and advice for fixing the problem. +To assist with keeping the MPS Reference up to date, these assertions +are marked with a cross-reference to this tag. When you update the +assertion, you must also update the MPS Reference. + + Document History ---------------- @@ -138,7 +150,7 @@ Document History Copyright and License --------------------- -Copyright © 2013-2014 Ravenbrook Limited <http://www.ravenbrook.com/>. +Copyright © 2013-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options. diff --git a/mps/manual/source/topic/error.rst b/mps/manual/source/topic/error.rst index 796edda1699..b47e24858e5 100644 --- a/mps/manual/source/topic/error.rst +++ b/mps/manual/source/topic/error.rst @@ -286,7 +286,7 @@ this documentation. It is necessary to call :c:func:`mps_fmt_destroy` first. -``global.c: RingIsSingle(&arena->rootRing)`` +``global.c: RingIsSingle(&arenaGlobals->rootRing)`` The client program called :c:func:`mps_arena_destroy` without destroying all the :term:`roots` belonging to the arena. @@ -300,7 +300,7 @@ this documentation. It is necessary to call :c:func:`mps_thread_dereg` first. -``global.c: RingLength(&arenaGlobals->poolRing) == 5`` +``global.c: RingLength(&arenaGlobals->poolRing) == 4`` The client program called :c:func:`mps_arena_destroy` without destroying all the :term:`pools` belonging to the arena. From 68d219c53b00a413f016644ce634b3d704f4ce10 Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Fri, 2 Sep 2016 19:07:45 +0100 Subject: [PATCH 35/52] Fix glossary references. Copied from Perforce Change: 192102 ServerID: perforce.ravenbrook.com --- mps/manual/source/topic/arena.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mps/manual/source/topic/arena.rst b/mps/manual/source/topic/arena.rst index 0aed4a1b582..f1386781572 100644 --- a/mps/manual/source/topic/arena.rst +++ b/mps/manual/source/topic/arena.rst @@ -16,7 +16,7 @@ System, and tells it where to get the memory it manages. You typically start a session with the MPS by creating an arena with :c:func:`mps_arena_create_k` and end the session by destroying it with :c:func:`mps_arena_destroy`. The only functions you might need to call -before making an arena are :term:`telemetry` functions like +before making an arena are :term:`telemetry system` functions like :c:func:`mps_telemetry_set` and the :term:`plinth` function :c:func:`mps_lib_assert_fail_install`. @@ -472,8 +472,8 @@ Arena properties When the pause time is short, the MPS needs to take more slices of time in order to make :term:`garbage collection` progress, and make more use of :term:`barriers (1)` to support - :term:`incremental collection`. This increases time overheads, - and especially operating system overheads. + :term:`incremental garbage collection`. This increases time + overheads, and especially operating system overheads. The pause time may be set to zero, in which case the MPS returns as soon as it can, without regard for overall efficiency. This @@ -487,7 +487,7 @@ Arena properties The pause time may be set to infinity, in which case the MPS completes all outstanding :term:`garbage collection` work before returning from an operation. The consequence is that the MPS will - be able to save on the overheads due to :term:`incremental + be able to save on the overheads due to :term:`incremental garbage collection`, leading to lower total time spent in collection. This value is suitable for non-interactive applications where total time is important. From 24d8b79bece2e56f23e91c44ced7c5165cd80165 Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Fri, 2 Sep 2016 19:08:13 +0100 Subject: [PATCH 36/52] Index regexp needs multiline flag. Copied from Perforce Change: 192103 ServerID: perforce.ravenbrook.com --- mps/manual/source/extensions/mps/designs.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mps/manual/source/extensions/mps/designs.py b/mps/manual/source/extensions/mps/designs.py index 234e99d2c94..ff532d63a92 100644 --- a/mps/manual/source/extensions/mps/designs.py +++ b/mps/manual/source/extensions/mps/designs.py @@ -83,7 +83,8 @@ def citation_sub(m): fmt += ' "{title}".' return fmt.format(**groups) -index = re.compile(r'^:Index\s+terms:(.*$\n(?:[ \t]+.*$\n)*)', re.IGNORECASE) +index = re.compile(r'^:Index\s+terms:(.*$\n(?:[ \t]+.*$\n)*)', + re.MULTILINE | re.IGNORECASE) # <http://sphinx-doc.org/markup/misc.html#directive-index> index_term = re.compile(r'^\s*(\w+):\s*(.*?)\s*$', re.MULTILINE) From 4fd5435a518de6bd0130a292e3c1959fbc9367e7 Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Fri, 2 Sep 2016 19:20:58 +0100 Subject: [PATCH 37/52] Avoid strict aliasing errors in the mps test suite, so that it compiles and runs using gcc 6.1. Update the manual entries for mps_alloc and mps_sac_alloc with notes highlighting the problem. Copied from Perforce Change: 192104 ServerID: perforce.ravenbrook.com --- mps/code/apss.c | 13 +++++---- mps/code/fotest.c | 9 ++++-- mps/code/mpmss.c | 13 +++++---- mps/code/mv2test.c | 18 +++++++----- mps/code/sacss.c | 15 ++++++---- mps/manual/source/topic/allocation.rst | 14 +++++++++ mps/manual/source/topic/cache.rst | 40 +++++++++++++++----------- 7 files changed, 80 insertions(+), 42 deletions(-) diff --git a/mps/code/apss.c b/mps/code/apss.c index fbe58f249df..0e855b07733 100644 --- a/mps/code/apss.c +++ b/mps/code/apss.c @@ -1,7 +1,7 @@ /* apss.c: AP MANUAL ALLOC STRESS TEST * * $Id$ - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * Portions copyright (C) 2002 Global Graphics Software. */ @@ -77,11 +77,12 @@ static mps_res_t stress(mps_arena_t arena, mps_pool_debug_option_s *options, /* allocate a load of objects */ for (i=0; i<testSetSIZE; ++i) { + mps_addr_t obj; ss[i] = (*size)(i, align); - - res = make((mps_addr_t *)&ps[i], ap, ss[i]); + res = make(&obj, ap, ss[i]); if (res != MPS_RES_OK) goto allocFail; + ps[i] = obj; allocated += ss[i] + debugOverhead; if (ss[i] >= sizeof(ps[i])) *ps[i] = 1; /* Write something, so it gets swap. */ @@ -121,10 +122,12 @@ static mps_res_t stress(mps_arena_t arena, mps_pool_debug_option_s *options, } /* allocate some new objects */ for (i=testSetSIZE/2; i<testSetSIZE; ++i) { + mps_addr_t obj; ss[i] = (*size)(i, align); - res = make((mps_addr_t *)&ps[i], ap, ss[i]); + res = make(&obj, ap, ss[i]); if (res != MPS_RES_OK) goto allocFail; + ps[i] = obj; allocated += ss[i] + debugOverhead; } check_allocated_size(pool, ap, allocated); @@ -259,7 +262,7 @@ int main(int argc, char *argv[]) /* C. COPYRIGHT AND LICENSE * - * Copyright (c) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>. + * Copyright (c) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/fotest.c b/mps/code/fotest.c index 09ba0a2d8db..61f1d8745a4 100644 --- a/mps/code/fotest.c +++ b/mps/code/fotest.c @@ -88,11 +88,12 @@ static mps_res_t stress(size_t (*size)(unsigned long, mps_align_t), /* allocate a load of objects */ for (i=0; i<testSetSIZE; ++i) { + mps_addr_t obj; ss[i] = (*size)(i, alignment); - - res = make((mps_addr_t *)&ps[i], ap, ss[i]); + res = make(&obj, ap, ss[i]); if (res != MPS_RES_OK) goto allocFail; + ps[i] = obj; if (ss[i] >= sizeof(ps[i])) *ps[i] = 1; /* Write something, so it gets swap. */ } @@ -118,10 +119,12 @@ static mps_res_t stress(size_t (*size)(unsigned long, mps_align_t), } /* allocate some new objects */ for (i=testSetSIZE/2; i<testSetSIZE; ++i) { + mps_addr_t obj; ss[i] = (*size)(i, alignment); - res = make((mps_addr_t *)&ps[i], ap, ss[i]); + res = make(&obj, ap, ss[i]); if (res != MPS_RES_OK) goto allocFail; + ps[i] = obj; } CLASS_STATIC(MFSPool).alloc = rnd() % 2 ? mfs_alloc : oomAlloc; diff --git a/mps/code/mpmss.c b/mps/code/mpmss.c index 31616425a65..2e1d9f970c0 100644 --- a/mps/code/mpmss.c +++ b/mps/code/mpmss.c @@ -1,7 +1,7 @@ /* mpmss.c: MPM STRESS TEST * * $Id$ - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * Portions copyright (C) 2002 Global Graphics Software. */ @@ -57,11 +57,12 @@ static mps_res_t stress(mps_arena_t arena, mps_pool_debug_option_s *options, /* allocate a load of objects */ for (i=0; i<testSetSIZE; ++i) { + mps_addr_t obj; ss[i] = (*size)(i); - - res = mps_alloc((mps_addr_t *)&ps[i], pool, ss[i]); + res = mps_alloc(&obj, pool, ss[i]); if (res != MPS_RES_OK) return res; + ps[i] = obj; allocated += alignUp(ss[i], align) + debugOverhead; if (ss[i] >= sizeof(ps[i])) *ps[i] = 1; /* Write something, so it gets swap. */ @@ -93,10 +94,12 @@ static mps_res_t stress(mps_arena_t arena, mps_pool_debug_option_s *options, } /* allocate some new objects */ for (i=testSetSIZE/2; i<testSetSIZE; ++i) { + mps_addr_t obj; ss[i] = (*size)(i); - res = mps_alloc((mps_addr_t *)&ps[i], pool, ss[i]); + res = mps_alloc(&obj, pool, ss[i]); if (res != MPS_RES_OK) return res; + ps[i] = obj; allocated += alignUp(ss[i], align) + debugOverhead; } check_allocated_size(pool, allocated); @@ -241,7 +244,7 @@ int main(int argc, char *argv[]) /* C. COPYRIGHT AND LICENSE * - * Copyright (c) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>. + * Copyright (c) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/mv2test.c b/mps/code/mv2test.c index 4670abbf076..a47a520af7f 100644 --- a/mps/code/mv2test.c +++ b/mps/code/mv2test.c @@ -1,7 +1,7 @@ /* mv2test.c: POOLMVT STRESS TEST * * $Id$ - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. */ #include <math.h> @@ -102,13 +102,15 @@ static mps_res_t stress(mps_arena_t arena, mps_align_t align, /* allocate a load of objects */ for(i=0; i<TEST_SET_SIZE; ++i) { + mps_addr_t obj; ss[i] = (*size)(i); - - res = make((mps_addr_t *)&ps[i], ap, ss[i], align); - if(res != MPS_RES_OK) + res = make(&obj, ap, ss[i], align); + if (res != MPS_RES_OK) { ss[i] = 0; - else + } else { + ps[i]= obj; *ps[i] = 1; /* Write something, so it gets swap. */ + } if (verbose) { if (i && i%4==0) @@ -146,10 +148,12 @@ static mps_res_t stress(mps_arena_t arena, mps_align_t align, } /* allocate some new objects */ for(i=x; i<TEST_SET_SIZE; ++i) { + mps_addr_t obj; size_t s = (*size)(i); - res = make((mps_addr_t *)&ps[i], ap, s, align); + res = make(&obj, ap, s, align); if(res != MPS_RES_OK) break; + ps[i] = obj; ss[i] = s; if (verbose) { @@ -218,7 +222,7 @@ int main(int argc, char *argv[]) /* C. COPYRIGHT AND LICENSE * - * Copyright (c) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>. + * Copyright (c) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/sacss.c b/mps/code/sacss.c index d85b3ae5073..59550490910 100644 --- a/mps/code/sacss.c +++ b/mps/code/sacss.c @@ -1,7 +1,7 @@ /* sacss.c: SAC MANUAL ALLOC STRESS TEST * * $Id$ - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * Portions copyright (C) 2002 Global Graphics Software. */ @@ -74,11 +74,12 @@ static mps_res_t stress(mps_arena_t arena, mps_align_t align, /* allocate a load of objects */ for (i = 0; i < testSetSIZE; ++i) { + mps_addr_t obj; ss[i] = (*size)(i); - - res = make((mps_addr_t *)&ps[i], sac, ss[i]); + res = make(&obj, sac, ss[i]); if (res != MPS_RES_OK) return res; + ps[i] = obj; if (ss[i] >= sizeof(ps[i])) *ps[i] = 1; /* Write something, so it gets swap. */ } @@ -113,17 +114,19 @@ static mps_res_t stress(mps_arena_t arena, mps_align_t align, } /* allocate some new objects */ for (i=testSetSIZE/2; i<testSetSIZE; ++i) { + mps_addr_t obj; ss[i] = (*size)(i); switch (k % 2) { case 0: - res = make((mps_addr_t *)&ps[i], sac, ss[i]); + res = make(&obj, sac, ss[i]); break; default: - res = mps_sac_alloc((mps_addr_t *)&ps[i], sac, ss[i], FALSE); + res = mps_sac_alloc(&obj, sac, ss[i], FALSE); break; } if (res != MPS_RES_OK) return res; + ps[i] = obj; } } @@ -246,7 +249,7 @@ int main(int argc, char *argv[]) /* C. COPYRIGHT AND LICENSE * - * Copyright (c) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>. + * Copyright (c) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/manual/source/topic/allocation.rst b/mps/manual/source/topic/allocation.rst index 445f9c4583e..bab89bc2d79 100644 --- a/mps/manual/source/topic/allocation.rst +++ b/mps/manual/source/topic/allocation.rst @@ -45,6 +45,20 @@ Manual allocation unaligned, it will be rounded up to the pool's :term:`alignment` (unless the pool documentation says otherwise). + .. note:: + + It is tempting to call :c:func:`mps_alloc` with a cast from + the desired pointer type to ``mps_addr_t *``, like this:: + + my_object *obj; + res = mps_alloc((mps_addr_t *)&obj, pool, sizeof *p); + if (res != MPS_RES_OK) + error(...); + + but this is :term:`type punning`, and its behaviour is not + defined in ANSI/ISO Standard C. See :ref:`topic-interface-pun` + for more details. + .. c:function:: void mps_free(mps_pool_t pool, mps_addr_t addr, size_t size) diff --git a/mps/manual/source/topic/cache.rst b/mps/manual/source/topic/cache.rst index d4446d7a97b..041c2d22ab4 100644 --- a/mps/manual/source/topic/cache.rst +++ b/mps/manual/source/topic/cache.rst @@ -285,26 +285,34 @@ Allocation interface .. note:: - There's also a macro :c:func:`MPS_SAC_ALLOC_FAST` that does - the same thing. The macro is faster, but generates more code - and does less checking. + 1. There's also a macro :c:func:`MPS_SAC_ALLOC_FAST` that does + the same thing. The macro is faster, but generates more + code and does less checking. - .. note:: + 2. The :term:`client program` is responsible for synchronizing + the access to the cache, but if the cache decides to access + the pool, the MPS will properly synchronize with any other + :term:`threads` that might be accessing the same pool. - The :term:`client program` is responsible for synchronizing - the access to the cache, but if the cache decides to access - the pool, the MPS will properly synchronize with any other - :term:`threads` that might be accessing the same - pool. + 3. Blocks allocated through a segregated allocation cache + should only be freed through a segregated allocation cache + with the same class structure. Calling :c:func:`mps_free` + on them can cause :term:`memory leaks`, because the size of + the block might be larger than you think. Naturally, the + cache must also be attached to the same pool. - .. note:: + 4. It is tempting to call :c:func:`mps_sac_alloc` with a cast + from the desired pointer type to ``mps_addr_t *``, like + this:: - Blocks allocated through a segregated allocation cache should - only be freed through a segregated allocation cache with the - same class structure. Calling :c:func:`mps_free` on them can - cause :term:`memory leaks`, because the size of - the block might be larger than you think. Naturally, the cache - must also be attached to the same pool. + my_object *obj; + res = mps_alloc((mps_addr_t *)&obj, sac, sizeof *p, 0); + if (res != MPS_RES_OK) + error(...); + + but this is :term:`type punning`, and its behaviour is not + defined in ANSI/ISO Standard C. See + :ref:`topic-interface-pun` for more details. .. c:function:: MPS_SAC_ALLOC_FAST(mps_res_t res_v, mps_addr_t *p_v, mps_sac_t sac, size_t size, mps_bool_t has_reservoir_permit) From f1b3655bd59bd67c3ce7a6bd2aa3822f635c50d6 Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Sun, 4 Sep 2016 11:56:09 +0100 Subject: [PATCH 38/52] Add a case for rootthread to rootcheck. Add test coverage for mps_root_create_thread_scanned and mps_root_create_area; improve coverage for mps_root_create_area_tagged, mps_scan_area_tagged, mps_scan_area. Copied from Perforce Change: 192111 ServerID: perforce.ravenbrook.com --- mps/code/mpsicv.c | 52 ++++++++++++++++++++++++++++++++++++----------- mps/code/root.c | 8 ++++++++ 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/mps/code/mpsicv.c b/mps/code/mpsicv.c index d026f2cd684..d1a9759a3b8 100644 --- a/mps/code/mpsicv.c +++ b/mps/code/mpsicv.c @@ -1,7 +1,7 @@ /* mpsicv.c: MPSI COVERAGE TEST * * $Id$ - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * Portions copyright (c) 2002 Global Graphics Software. */ @@ -338,7 +338,8 @@ static void *test(void *arg, size_t s) mps_arena_t arena; mps_fmt_t format; mps_chain_t chain; - mps_root_t exactRoot, ambigRoot, singleRoot, fmtRoot; + mps_root_t exactAreaRoot, exactTableRoot, ambigAreaRoot, ambigTableRoot, + singleRoot, fmtRoot; unsigned long i; /* Leave arena clamped until we have allocated this many objects. is 0 when arena has not been clamped. */ @@ -386,14 +387,29 @@ static void *test(void *arg, size_t s) ambigRoots[j] = rnd_addr(); } - die(mps_root_create_table_masked(&exactRoot, arena, + die(mps_root_create_area_tagged(&exactAreaRoot, arena, + mps_rank_exact(), (mps_rm_t)0, + &exactRoots[0], + &exactRoots[exactRootsCOUNT / 2], + mps_scan_area_tagged, + MPS_WORD_CONST(1), 0), + "root_create_area_tagged(exact)"); + die(mps_root_create_table_masked(&exactTableRoot, arena, mps_rank_exact(), (mps_rm_t)0, - &exactRoots[0], exactRootsCOUNT, + &exactRoots[exactRootsCOUNT / 2], + (exactRootsCOUNT + 1) / 2, MPS_WORD_CONST(1)), - "root_create_table(exact)"); - die(mps_root_create_table(&ambigRoot, arena, + "root_create_table_masked(exact)"); + die(mps_root_create_area(&ambigAreaRoot, arena, + mps_rank_ambig(), (mps_rm_t)0, + &ambigRoots[0], + &ambigRoots[ambigRootsCOUNT / 2], + mps_scan_area, NULL), + "root_create_area(ambig)"); + die(mps_root_create_table(&ambigTableRoot, arena, mps_rank_ambig(), (mps_rm_t)0, - &ambigRoots[0], ambigRootsCOUNT), + &ambigRoots[ambigRootsCOUNT / 2], + (ambigRootsCOUNT + 1) / 2), "root_create_table(ambig)"); obj = objNULL; @@ -519,8 +535,10 @@ static void *test(void *arg, size_t s) mps_ap_destroy(ap); mps_root_destroy(fmtRoot); mps_root_destroy(singleRoot); - mps_root_destroy(exactRoot); - mps_root_destroy(ambigRoot); + mps_root_destroy(exactAreaRoot); + mps_root_destroy(exactTableRoot); + mps_root_destroy(ambigAreaRoot); + mps_root_destroy(ambigTableRoot); mps_pool_destroy(amcpool); mps_chain_destroy(chain); mps_fmt_destroy(format); @@ -551,15 +569,25 @@ int main(int argc, char *argv[]) } MPS_ARGS_END(args); die(mps_thread_reg(&thread, arena), "thread_reg"); - if (rnd() % 2) { + switch (rnd() % 3) { + default: + case 0: die(mps_root_create_reg(®_root, arena, mps_rank_ambig(), (mps_rm_t)0, thread, &mps_stack_scan_ambig, marker, (size_t)0), "root_create_reg"); - } else { + break; + case 1: die(mps_root_create_thread(®_root, arena, thread, marker), "root_create_thread"); + break; + case 2: + die(mps_root_create_thread_scanned(®_root, arena, mps_rank_ambig(), + (mps_rm_t)0, thread, mps_scan_area, + NULL, marker), + "root_create_thread"); + break; } mps_tramp(&r, test, arena, 0); @@ -574,7 +602,7 @@ int main(int argc, char *argv[]) /* C. COPYRIGHT AND LICENSE * - * Copyright (c) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>. + * Copyright (c) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/root.c b/mps/code/root.c index c241430ab63..e6322a60d9b 100644 --- a/mps/code/root.c +++ b/mps/code/root.c @@ -129,6 +129,14 @@ Bool RootCheck(Root root) scan. */ break; + case RootTHREAD: + CHECKD_NOSIG(Thread, root->the.thread.thread); /* <design/check/#hidden-type> */ + CHECKL(FUNCHECK(root->the.thread.scan_area)); + /* Can't check anything about closure as it could mean anything to + scan_area. */ + /* Can't check anything about stackCold. */ + break; + case RootTHREAD_TAGGED: CHECKD_NOSIG(Thread, root->the.thread.thread); /* <design/check/#hidden-type> */ CHECKL(FUNCHECK(root->the.thread.scan_area)); From 4a46ff870e7020abe7e2d3077b5cd001131cb725 Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Sun, 4 Sep 2016 12:15:34 +0100 Subject: [PATCH 39/52] Fix type punning examples. Copied from Perforce Change: 192116 ServerID: perforce.ravenbrook.com --- mps/manual/source/topic/allocation.rst | 2 +- mps/manual/source/topic/cache.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mps/manual/source/topic/allocation.rst b/mps/manual/source/topic/allocation.rst index bab89bc2d79..08f33d08771 100644 --- a/mps/manual/source/topic/allocation.rst +++ b/mps/manual/source/topic/allocation.rst @@ -51,7 +51,7 @@ Manual allocation the desired pointer type to ``mps_addr_t *``, like this:: my_object *obj; - res = mps_alloc((mps_addr_t *)&obj, pool, sizeof *p); + res = mps_alloc((mps_addr_t *)&obj, pool, sizeof *obj); if (res != MPS_RES_OK) error(...); diff --git a/mps/manual/source/topic/cache.rst b/mps/manual/source/topic/cache.rst index 041c2d22ab4..1d722049776 100644 --- a/mps/manual/source/topic/cache.rst +++ b/mps/manual/source/topic/cache.rst @@ -306,7 +306,7 @@ Allocation interface this:: my_object *obj; - res = mps_alloc((mps_addr_t *)&obj, sac, sizeof *p, 0); + res = mps_alloc((mps_addr_t *)&obj, sac, sizeof *obj, 0); if (res != MPS_RES_OK) error(...); From 47bf1c564c7568abfe0ab007b66f1b2d7c6c02d5 Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Sun, 4 Sep 2016 12:20:37 +0100 Subject: [PATCH 40/52] Update release notes for job004036 and job004037. Copied from Perforce Change: 192117 ServerID: perforce.ravenbrook.com --- mps/manual/source/release.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mps/manual/source/release.rst b/mps/manual/source/release.rst index fdf28461f50..51b487fe04e 100644 --- a/mps/manual/source/release.rst +++ b/mps/manual/source/release.rst @@ -36,6 +36,15 @@ Other changes .. _job004011: https://www.ravenbrook.com/project/mps/issue/job004011/ +#. Roots created by :c:func:`mps_root_create_thread_scanned` no longer + cause an assertion failure. See job004036_. + + .. _job004036: https://www.ravenbrook.com/project/mps/issue/job004036/ + +#. The MPS test suite now compiles and passes with GCC 6.1. See job004037_. + + .. _job004037: https://www.ravenbrook.com/project/mps/issue/job004037/ + .. _release-notes-1.115: From 6932a51b2ff33d75c2b9a2c24e8b051a48f6c9c3 Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Sun, 4 Sep 2016 13:55:39 +0100 Subject: [PATCH 41/52] New preprocessor constants config_pthreadext_sigsuspend and config_pthreadext_sigresume for configuring the signals used to suspend and resume threads. Copied from Perforce Change: 192122 ServerID: perforce.ravenbrook.com --- mps/code/config.h | 23 +++++++++++++++++++++ mps/code/pthrdext.c | 13 ++---------- mps/design/config.txt | 10 +++++++++ mps/design/pthreadext.txt | 17 ++++++++++----- mps/manual/source/release.rst | 3 +++ mps/manual/source/topic/thread.rst | 33 +++++++++++++++++++++--------- 6 files changed, 73 insertions(+), 26 deletions(-) diff --git a/mps/code/config.h b/mps/code/config.h index b5a5b6d1a93..7e3d2ac5461 100644 --- a/mps/code/config.h +++ b/mps/code/config.h @@ -610,6 +610,29 @@ #endif +/* POSIX thread extensions configuration -- see <code/pthrdext.c> */ + +#if defined(MPS_OS_LI) || defined(MPS_OS_FR) + +/* PTHREADEXT_SIGSUSPEND -- signal used to suspend a thread + * See <design/pthreadext/#impl.signals> + */ +#if defined(CONFIG_PTHREADEXT_SIGSUSPEND) +#define PTHREADEXT_SIGSUSPEND CONFIG_PTHREADEXT_SIGSUSPEND +#else +#define PTHREADEXT_SIGSUSPEND SIGXFSZ +#endif + +/* PTHREADEXT_SIGRESUME -- signal used to resume a thread + * See <design/pthreadext/#impl.signals> + */ +#if defined(CONFIG_PTHREADEXT_SIGRESUME) +#define PTHREADEXT_SIGRESUME CONFIG_PTHREADEXT_SIGRESUME +#else +#define PTHREADEXT_SIGRESUME SIGXCPU +#endif + +#endif /* Tracer Configuration -- see <code/trace.c> */ diff --git a/mps/code/pthrdext.c b/mps/code/pthrdext.c index 59d5899c326..19f39c0b470 100644 --- a/mps/code/pthrdext.c +++ b/mps/code/pthrdext.c @@ -1,7 +1,7 @@ /* pthreadext.c: POSIX THREAD EXTENSIONS * * $Id$ - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * * .purpose: Provides extension to Pthreads. * @@ -28,15 +28,6 @@ SRCID(pthreadext, "$Id$"); -/* PTHREADEXT_SIGSUSPEND, PTHREADEXT_SIGRESUME -- signals used - * - * See <design/pthreadext/#impl.signals> - */ - -#define PTHREADEXT_SIGSUSPEND SIGXFSZ -#define PTHREADEXT_SIGRESUME SIGXCPU - - /* Static data initialized on first use of the module * See <design/pthreadext/#impl.static>.* */ @@ -366,7 +357,7 @@ unlock: /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>. + * Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/design/config.txt b/mps/design/config.txt index 544b9a61ed1..458ccdfe890 100644 --- a/mps/design/config.txt +++ b/mps/design/config.txt @@ -550,6 +550,16 @@ happen if requested explicitly via ``mps_arena_collect()`` or ``mps_arena_step()``, but it also means that protection is not needed, and so shield operations can be replaced with no-ops in ``mpm.h``. +_`.opt.signal.suspend`: ``CONFIG_PTHREADEXT_SIGSUSPEND`` names the +signal used to suspend a thread, on platforms using the POSIX thread +extensions module. See design.pthreadext.impl.signals_. + +.. _design.pthreadext.impl.signals: pthreadext#impl.signals + +_`.opt.signal.resume`: ``CONFIG_PTHREADEXT_SIGRESUME`` names the +signal used to resume a thread, on platforms using the POSIX thread +extensions module. See design.pthreadext.impl.signals_. + To document ----------- diff --git a/mps/design/pthreadext.txt b/mps/design/pthreadext.txt index b2d886b75a5..2f05c7413c9 100644 --- a/mps/design/pthreadext.txt +++ b/mps/design/pthreadext.txt @@ -324,10 +324,17 @@ likely to be generated and/or handled by other parts of the application and so should not be used (for example, ``SIGSEGV``). Some implementations of PThreads use some signals for themselves, so they may not be used; for example, LinuxThreads uses ``SIGUSR1`` and -``SIGUSR2`` for its own purposes. The design abstractly names the -signals ``PTHREADEXT_SIGSUSPEND`` and ``PTHREAD_SIGRESUME``, so that -they may be easily mapped to appropriate real signal values. Candidate -choices are ``SIGXFSZ`` and ``SIGPWR``. +``SIGUSR2`` for its own purposes, and so do popular tools like +Valgrind that we would like to be compatible with the MPS. The design +therefore abstractly names the signals ``PTHREADEXT_SIGSUSPEND`` and +``PTHREAD_SIGRESUME``, so that they may be easily mapped to +appropriate real signal values. Candidate choices are ``SIGXFSZ`` and +``SIGXCPU``. + +_`.impl.signals.config`: The identity of the signals used to suspend +and resume threads can be configured at compilation time using the +preprocessor constants ``CONFIG_PTHREADEXT_SIGSUSPEND`` and +``CONFIG_PTHREADEXT_SIGRESUME`` respectively. Attachments @@ -368,7 +375,7 @@ Document History Copyright and License --------------------- -Copyright © 2013-2014 Ravenbrook Limited <http://www.ravenbrook.com/>. +Copyright © 2013-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. All rights reserved. This is an open source license. Contact Ravenbrook for commercial licensing options. diff --git a/mps/manual/source/release.rst b/mps/manual/source/release.rst index 51b487fe04e..a5095f4088c 100644 --- a/mps/manual/source/release.rst +++ b/mps/manual/source/release.rst @@ -15,6 +15,9 @@ Interface changes #. Allocation frames are no longer deprecated. See :ref:`topic-frame`. +#. On Linux and FreeBSD, it is now possible to configure the signals + used to suspend and resume threads. See :ref:`topic-thread-signal`. + Other changes ............. diff --git a/mps/manual/source/topic/thread.rst b/mps/manual/source/topic/thread.rst index e814fbe939a..96e80c06ea1 100644 --- a/mps/manual/source/topic/thread.rst +++ b/mps/manual/source/topic/thread.rst @@ -69,17 +69,30 @@ Signal and exception handling issues .. warning:: - On Unix platforms (except OS X), the MPS suspends and resumes - threads by sending them signals. There's a shortage of available - signals that aren't already dedicated to other purposes (for - example, ValGrind uses ``SIGUSR1`` and ``SIGUSR2``), so the MPS uses - ``SIGXCPU`` and ``SIGXFSZ``. This means that programs must not mask - these two signals. + On Linux and FreeBSD, the MPS suspends and resumes threads by + sending them signals. There's a shortage of available signals that + aren't already dedicated to other purposes (for example, ValGrind + uses ``SIGUSR1`` and ``SIGUSR2``), so the MPS uses ``SIGXCPU`` and + ``SIGXFSZ``. This means that programs must not mask or handle + either of these signals. - If your program needs to handle these signals, then it must - co-operate with the MPS. At present, there's no documented - mechanism for co-operating: if you are in this situation, please - :ref:`contact us <contact>`. + If your program needs to mask or handle either of these signals, + then you can configure the MPS to use another pair of signals of + your choosing, by defining these preprocessor constants: + + .. c:macro:: CONFIG_PTHREADEXT_SIGSUSPEND + + If this preprocessor constant is defined, its definition names + the signal used to suspend a thread. For example:: + + cc -DCONFIG_PTHREADEXT_SIGSUSPEND=SIGUSR1 -c mps.c + + .. c:macro:: CONFIG_PTHREADEXT_SIGRESUME + + If this preprocessor constant is defined, its definition names + the signal used to resume a thread. For example:: + + cc -DCONFIG_PTHREADEXT_SIGSUSPEND=SIGUSR2 -c mps.c .. warning:: From 48b3a425af50efd726ea8003dd889850a3685457 Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Sun, 4 Sep 2016 14:23:07 +0100 Subject: [PATCH 42/52] Support registering a thread with the mps multiple times on os x. Restore test case. Copied from Perforce Change: 192127 ServerID: perforce.ravenbrook.com --- mps/code/amcssth.c | 13 +++++++++---- mps/code/protxc.c | 7 ++++--- mps/manual/source/release.rst | 7 +++++++ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/mps/code/amcssth.c b/mps/code/amcssth.c index 3ce82054931..d914427eb46 100644 --- a/mps/code/amcssth.c +++ b/mps/code/amcssth.c @@ -120,13 +120,17 @@ typedef struct closure_s { static void *kid_thread(void *arg) { void *marker = ▮ - mps_thr_t thread; + mps_thr_t thread1, thread2; mps_root_t reg_root; mps_ap_t ap; closure_t cl = arg; - die(mps_thread_reg(&thread, (mps_arena_t)arena), "thread_reg"); - die(mps_root_create_thread(®_root, arena, thread, marker), + /* Register the thread twice to check this is supported -- see + * <design/thread-manager/#req.register.multi> + */ + die(mps_thread_reg(&thread1, arena), "thread_reg"); + die(mps_thread_reg(&thread2, arena), "thread_reg"); + die(mps_root_create_thread(®_root, arena, thread1, marker), "root_create"); die(mps_ap_create(&ap, cl->pool, mps_rank_exact()), "BufferCreate(fooey)"); @@ -136,7 +140,8 @@ static void *kid_thread(void *arg) mps_ap_destroy(ap); mps_root_destroy(reg_root); - mps_thread_dereg(thread); + mps_thread_dereg(thread2); + mps_thread_dereg(thread1); return NULL; } diff --git a/mps/code/protxc.c b/mps/code/protxc.c index 7e8f230d061..0d29010c771 100644 --- a/mps/code/protxc.c +++ b/mps/code/protxc.c @@ -1,7 +1,7 @@ /* protxc.c: PROTECTION EXCEPTION HANDLER FOR OS X MACH * * $Id$ - * Copyright (c) 2013-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2013-2016 Ravenbrook Limited. See end of file for license. * * This is the protection exception handling code for OS X using the * Mach interface (not pthreads). @@ -338,7 +338,8 @@ extern void ProtThreadRegister(Bool setup) mach_error("ERROR: MPS thread_swap_exception_ports", kr); /* .trans.must */ AVER(old_exception_masks == EXC_MASK_BAD_ACCESS); AVER(old_exception_count == 1); - AVER(old_exception_ports == MACH_PORT_NULL); /* .assume.only-port */ + AVER(old_exception_ports == MACH_PORT_NULL + || old_exception_ports == protExcPort); /* .assume.only-port */ } @@ -401,7 +402,7 @@ void ProtSetup(void) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2013-2014 Ravenbrook Limited <http://www.ravenbrook.com/>. + * Copyright (C) 2013-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/manual/source/release.rst b/mps/manual/source/release.rst index a5095f4088c..9d2961faec2 100644 --- a/mps/manual/source/release.rst +++ b/mps/manual/source/release.rst @@ -22,6 +22,13 @@ Interface changes Other changes ............. +#. It is now possible to register a thread with the MPS multiple times + on OS X, thus supporting the use case where a program that does not + use the MPS is calling into MPS-using code from multiple threads. + (This was already supported on other platforms.) See job003559_. + + .. _job003559: https://www.ravenbrook.com/project/mps/issue/job003559/ + #. Objects in :ref:`pool-snc` pools are no longer scanned after their :term:`allocation frame` is popped, and so do not keep objects in automatically managed pools alive. See job003883_. From a90a02704aca460e85f2e6090f598c9c0d3e98fc Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Sun, 4 Sep 2016 14:28:28 +0100 Subject: [PATCH 43/52] Initialize in/out parameter old_exception_count before passing it to thread_swap_exception_ports. Copied from Perforce Change: 192128 ServerID: perforce.ravenbrook.com --- mps/code/protxc.c | 2 +- mps/manual/source/release.rst | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/mps/code/protxc.c b/mps/code/protxc.c index 0d29010c771..f955e438286 100644 --- a/mps/code/protxc.c +++ b/mps/code/protxc.c @@ -292,7 +292,7 @@ static void *protCatchThread(void *p) { extern void ProtThreadRegister(Bool setup) { kern_return_t kr; - mach_msg_type_number_t old_exception_count; + mach_msg_type_number_t old_exception_count = 1; exception_mask_t old_exception_masks; exception_behavior_t behavior; mach_port_t old_exception_ports; diff --git a/mps/manual/source/release.rst b/mps/manual/source/release.rst index 9d2961faec2..dbb3342e896 100644 --- a/mps/manual/source/release.rst +++ b/mps/manual/source/release.rst @@ -55,6 +55,11 @@ Other changes .. _job004037: https://www.ravenbrook.com/project/mps/issue/job004037/ +#. The MPS no longer passes an uninitialized variable to + :c:func:`thread_swap_exception_ports` on OS X. See job004040_. + + .. _job004040: https://www.ravenbrook.com/project/mps/issue/job004040/ + .. _release-notes-1.115: From d558f6acb29f9b6e914931f72e1a2edabe6736ed Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Sun, 4 Sep 2016 14:47:08 +0100 Subject: [PATCH 44/52] Build and test the toy scheme interpreter during continuous integration, to reduce the risk of accidentally breaking it. Copied from Perforce Change: 192133 ServerID: perforce.ravenbrook.com --- mps/Makefile.in | 2 +- mps/code/comm.gmk | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/mps/Makefile.in b/mps/Makefile.in index 71673c67db3..cdefe0890ea 100644 --- a/mps/Makefile.in +++ b/mps/Makefile.in @@ -71,7 +71,7 @@ make-install-dirs: install: @INSTALL_TARGET@ test-make-build: - $(MAKE) $(TARGET_OPTS) testci testratio + $(MAKE) $(TARGET_OPTS) testci testratio testscheme $(MAKE) -C code -f anan$(MPS_BUILD_NAME).gmk VARIETY=cool clean testansi $(MAKE) -C code -f anan$(MPS_BUILD_NAME).gmk VARIETY=cool CFLAGS="-DCONFIG_POLL_NONE" clean testpollnone diff --git a/mps/code/comm.gmk b/mps/code/comm.gmk index 5042cb126df..b65ca3d025a 100644 --- a/mps/code/comm.gmk +++ b/mps/code/comm.gmk @@ -332,8 +332,7 @@ RATIO=$$(awk "BEGIN{print int(100 * $$TIME_HOT / $$TIME_RASH)}"); \ printf "Performance ratio (hot/rash) for $(2): %d%%\n" $$RATIO endef -.PHONY: testratio -testratio: +testratio: phony $(MAKE) -f $(PFM).gmk VARIETY=hot djbench gcbench $(MAKE) -f $(PFM).gmk VARIETY=rash djbench gcbench $(call ratio,gcbench,amc) @@ -354,6 +353,12 @@ $(PFM)/$(VARIETY)/testmmqa: (cd ../test && $(MMQA) runset testsets/passing) +# == Toy Scheme interpreter == + +testscheme: phony + $(MAKE) -C ../example/scheme test + + # These convenience targets allow one to type "make foo" to build target # foo in selected varieties (or none, for the latter rule). From 46ca1d0c86971bae6508c2fc32fcbeaac3868916 Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Sun, 4 Sep 2016 15:28:25 +0100 Subject: [PATCH 45/52] Document security issues in the mps. Copied from Perforce Change: 192138 ServerID: perforce.ravenbrook.com --- mps/manual/source/topic/index.rst | 2 +- mps/manual/source/topic/security.rst | 64 ++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 mps/manual/source/topic/security.rst diff --git a/mps/manual/source/topic/index.rst b/mps/manual/source/topic/index.rst index 3f2cb2863bf..b3139c16fb6 100644 --- a/mps/manual/source/topic/index.rst +++ b/mps/manual/source/topic/index.rst @@ -30,4 +30,4 @@ Reference platform porting deprecated - + security diff --git a/mps/manual/source/topic/security.rst b/mps/manual/source/topic/security.rst new file mode 100644 index 00000000000..c9294e834a5 --- /dev/null +++ b/mps/manual/source/topic/security.rst @@ -0,0 +1,64 @@ +.. index:: + single: security issues + +.. _topic-security: + +Security issues +=============== + +This chapter describes security issues that may be present when using +the MPS. + + +.. index:: + pair: security issues; predictable address space layout + single: address space; predictable layout + +Predictable address space layout +-------------------------------- + +The MPS acquires :term:`address space` using the operating system's +:term:`virtual memory` interface (specifically, :c:func:`mmap` on Unix +platforms, and :c:func:`VirtualAlloc` on Windows). None of the +supported platforms randomize the allocated regions of address space, +which means that the :term:`addresses` of :term:`blocks` allocated by +the MPS are predictable: a :term:`client program` that makes an +identical series of calls to the MPS gets an identical series of +addresses back. + +This means that if a program using the MPS has a buffer overflow, the +overflow is more easily exploitable by an attacker than if the program +had used :c:func:`malloc` (which has some randomization of the +allocated addresses), because it is easier for an attacker to +determine the address of allocated structures. + +There is currently no workaround for this issue. If this affects you, +please :ref:`contact us <contact>`. + + +.. index:: + pair: security issues; telemetry + +Telemetry +--------- + +In its :term:`hot` and :term:`cool` varieties, the MPS contains a +:term:`telemetry system` which can be configured to record a stream of +events for later analysis and debugging. When using the default +:term:`plinth`, the behaviour of the telemetry system is under the +control of the environment variable :envvar:`MPS_TELEMETRY_CONTROL`, +and the telemetry stream is written to the file named by the +environment variable :envvar:`MPS_TELEMETRY_FILENAME`. + +This means that an attacker who can set arbitrary environment +variables when running a program that uses the MPS can cause that +program to write a telemetry stream to an arbitrary file. This +behaviour might be unexpected, and might enable a data overwriting +attack, or a denial-of-service attack, since telemetry streams are +typically very large. + +If this is an issue for your program, then you can modify or replace +the :ref:`topic-plinth-io` in the :term:`plinth` so that it meets your +requirements, or distribute the :term:`rash` variety of the MPS, which +omits the :term:`telemetry system` entirely, and use the other +varieties only for development and testing. From df950a4de8adecb29e1281ef6a87cf87442a4323 Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Sun, 4 Sep 2016 16:25:26 +0100 Subject: [PATCH 46/52] Sort the tables of platform codes. document the (working, but not officially supported) platform xci6gc. Copied from Perforce Change: 192143 ServerID: perforce.ravenbrook.com --- mps/manual/build.txt | 7 +++---- mps/manual/source/topic/platform.rst | 24 ++++++++++++++++-------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/mps/manual/build.txt b/mps/manual/build.txt index b462f013ea9..c2aa184997f 100644 --- a/mps/manual/build.txt +++ b/mps/manual/build.txt @@ -136,17 +136,16 @@ well: Platform OS Architecture Compiler Makefile ========== ========= ============= ============ ================= ``fri3gc`` FreeBSD IA-32 GCC ``fri3gc.gmk`` -``fri6gc`` FreeBSD x86_64 GCC ``fri6gc.gmk`` ``fri3ll`` FreeBSD IA-32 Clang ``fri3ll.gmk`` +``fri6gc`` FreeBSD x86_64 GCC ``fri6gc.gmk`` ``fri6ll`` FreeBSD x86_64 Clang ``fri6ll.gmk`` ``lii3gc`` Linux IA-32 GCC ``lii3gc.gmk`` ``lii6gc`` Linux x86_64 GCC ``lii6gc.gmk`` ``lii6ll`` Linux x86_64 Clang ``lii6ll.gmk`` -``xci3ll`` Mac OS X IA-32 Clang ``mps.xcodeproj`` -``xci6ll`` Mac OS X x86_64 Clang ``mps.xcodeproj`` -``xci3gc`` Mac OS X IA-32 GCC (legacy) ``xci3gc.gmk`` ``w3i3mv`` Windows IA-32 Microsoft C ``w3i3mv.nmk`` ``w3i6mv`` Windows x86_64 Microsoft C ``w3i6mv.nmk`` +``xci3ll`` Mac OS X IA-32 Clang ``mps.xcodeproj`` +``xci6ll`` Mac OS X x86_64 Clang ``mps.xcodeproj`` ========== ========= ============= ============ ================= Historically, the MPS worked on a much wider variety of platforms, and diff --git a/mps/manual/source/topic/platform.rst b/mps/manual/source/topic/platform.rst index 15873d27af4..b075ea71e94 100644 --- a/mps/manual/source/topic/platform.rst +++ b/mps/manual/source/topic/platform.rst @@ -142,14 +142,7 @@ Platform interface IA-32 processor architecture, and the GCC compiler. -.. c:macro:: MPS_PF_FRI6GC - - A :term:`C` preprocessor macro that indicates, if defined, that - the :term:`platform` consists of the FreeBSD operating system, the - x86-64 processor architecture, and the GCC compiler. - - -.. c:macro:: MPS_PF_FRI3GC +.. c:macro:: MPS_PF_FRI3LL A :term:`C` preprocessor macro that indicates, if defined, that the :term:`platform` consists of the FreeBSD operating system, the @@ -158,6 +151,13 @@ Platform interface .. c:macro:: MPS_PF_FRI6GC + A :term:`C` preprocessor macro that indicates, if defined, that + the :term:`platform` consists of the FreeBSD operating system, the + x86-64 processor architecture, and the GCC compiler. + + +.. c:macro:: MPS_PF_FRI6LL + A :term:`C` preprocessor macro that indicates, if defined, that the :term:`platform` consists of the FreeBSD operating system, the x86-64 processor architecture, and the Clang/LLVM compiler. @@ -220,6 +220,13 @@ Platform interface IA-32 processor architecture, and the Clang/LLVM compiler. +.. c:macro:: MPS_PF_XCI6GC + + A :term:`C` preprocessor macro that indicates, if defined, that + the :term:`platform` consists of the OS X operating system, the + x86-64 processor architecture, and the GCC compiler. + + .. c:macro:: MPS_PF_XCI6LL A :term:`C` preprocessor macro that indicates, if defined, that @@ -373,6 +380,7 @@ Platform Status ``w3ppmv`` *Not supported* ``xci3gc`` *Not supported* ``xci3ll`` Supported +``xci6gc`` *Not supported* ``xci6ll`` Supported ``xcppgc`` *Not supported* ========== ======================= From e3951fca1ea53732de3bcc32611f390c734199db Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Sun, 4 Sep 2016 19:20:05 +0100 Subject: [PATCH 47/52] Add _critical to assertions on the critical path for manual-allocation-bound programs using mvff. this brings the hot/rash ratio for "djbench mvff" down from over 150% to about 130%. Copied from Perforce Change: 192148 ServerID: perforce.ravenbrook.com --- mps/code/cbs.c | 19 +++++++++++-------- mps/code/land.c | 40 ++++++++++++++++++++++++++-------------- mps/code/mpsi.c | 14 +++++++------- mps/code/pool.c | 34 ++++++++++++++++++++-------------- mps/code/poolmvff.c | 34 +++++++++++++++++++++------------- mps/code/splay.c | 14 +++++++------- mps/code/tract.c | 24 ++++++++++++------------ 7 files changed, 104 insertions(+), 75 deletions(-) diff --git a/mps/code/cbs.c b/mps/code/cbs.c index c081ed61610..e4ed5243362 100644 --- a/mps/code/cbs.c +++ b/mps/code/cbs.c @@ -1,7 +1,7 @@ /* cbs.c: COALESCING BLOCK STRUCTURE IMPLEMENTATION * * $Id$ - * Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * * .intro: This is a portable implementation of coalescing block * structures. @@ -441,6 +441,9 @@ static void cbsBlockInsert(CBS cbs, CBSBlock block) * * .insert.alloc: Will only allocate a block if the range does not * abut an existing range. + * + * .insert.critical: In manual-allocation-bound programs using MVFF + * this is on the critical path. */ static Res cbsInsert(Range rangeReturn, Land land, Range range) @@ -454,9 +457,9 @@ static Res cbsInsert(Range rangeReturn, Land land, Range range) Bool leftMerge, rightMerge; Size oldSize; - AVER(rangeReturn != NULL); - AVERT(Range, range); - AVER(RangeIsAligned(range, LandAlignment(land))); + AVER_CRITICAL(rangeReturn != NULL); + AVERT_CRITICAL(Range, range); + AVER_CRITICAL(RangeIsAligned(range, LandAlignment(land))); base = RangeBase(range); limit = RangeLimit(range); @@ -526,14 +529,14 @@ static Res cbsInsert(Range rangeReturn, Land land, Range range) cbsBlockInsert(cbs, block); } - AVER(newBase <= base); - AVER(newLimit >= limit); + AVER_CRITICAL(newBase <= base); + AVER_CRITICAL(newLimit >= limit); RangeInit(rangeReturn, newBase, newLimit); return ResOK; fail: - AVER(res != ResOK); + AVER_CRITICAL(res != ResOK); return res; } @@ -1163,7 +1166,7 @@ DEFINE_CLASS(Land, CBSZoned, klass) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>. + * Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/land.c b/mps/code/land.c index 3d2bb84bdec..d0434a3a9f8 100644 --- a/mps/code/land.c +++ b/mps/code/land.c @@ -1,7 +1,7 @@ /* land.c: LAND (COLLECTION OF ADDRESS RANGES) IMPLEMENTATION * * $Id$ - * Copyright (c) 2014-2015 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2014-2016 Ravenbrook Limited. See end of file for license. * * .design: <design/land/> */ @@ -190,12 +190,15 @@ void LandFinish(Land land) /* LandSize -- return the total size of ranges in land * * See <design/land/#function.size> + * + * .size.critical: In manual-allocation-bound programs using MVFF this + * is on the critical path. */ Size LandSize(Land land) { /* .enter-leave.simple */ - AVERC(Land, land); + AVERC_CRITICAL(Land, land); return Method(Land, land, sizeMethod)(land); } @@ -204,17 +207,20 @@ Size LandSize(Land land) /* LandInsert -- insert range of addresses into land * * See <design/land/#function.insert> + * + * .insert.critical: In manual-allocation-bound programs using MVFF + * this is on the critical path. */ Res LandInsert(Range rangeReturn, Land land, Range range) { Res res; - AVER(rangeReturn != NULL); - AVERC(Land, land); - AVERT(Range, range); - AVER(RangeIsAligned(range, land->alignment)); - AVER(!RangeIsEmpty(range)); + AVER_CRITICAL(rangeReturn != NULL); + AVERC_CRITICAL(Land, land); + AVERT_CRITICAL(Range, range); + AVER_CRITICAL(RangeIsAligned(range, land->alignment)); + AVER_CRITICAL(!RangeIsEmpty(range)); landEnter(land); res = Method(Land, land, insert)(rangeReturn, land, range); @@ -249,13 +255,16 @@ Res LandDelete(Range rangeReturn, Land land, Range range) /* LandIterate -- iterate over isolated ranges of addresses in land * * See <design/land/#function.iterate> + * + * .iterate.critical: In manual-allocation-bound programs using MVFF + * this is on the critical path. */ Bool LandIterate(Land land, LandVisitor visitor, void *closure) { Bool b; - AVERC(Land, land); - AVER(FUNCHECK(visitor)); + AVERC_CRITICAL(Land, land); + AVER_CRITICAL(FUNCHECK(visitor)); landEnter(land); b = Method(Land, land, iterate)(land, visitor, closure); @@ -274,8 +283,8 @@ Bool LandIterate(Land land, LandVisitor visitor, void *closure) Bool LandIterateAndDelete(Land land, LandDeleteVisitor visitor, void *closure) { Bool b; - AVERC(Land, land); - AVER(FUNCHECK(visitor)); + AVERC_CRITICAL(Land, land); + AVER_CRITICAL(FUNCHECK(visitor)); landEnter(land); b = Method(Land, land, iterateAndDelete)(land, visitor, closure); @@ -426,12 +435,15 @@ static Bool landFlushVisitor(Bool *deleteReturn, Land land, Range range, /* LandFlush -- move ranges from src to dest * * See <design/land/#function.flush> + * + * .flush.critical: In manual-allocation-bound programs using MVFF + * this is on the critical path. */ Bool LandFlush(Land dest, Land src) { - AVERC(Land, dest); - AVERC(Land, src); + AVERC_CRITICAL(Land, dest); + AVERC_CRITICAL(Land, src); return LandIterateAndDelete(src, landFlushVisitor, dest); } @@ -594,7 +606,7 @@ DEFINE_CLASS(Land, Land, klass) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2014-2015 Ravenbrook Limited <http://www.ravenbrook.com/>. + * Copyright (C) 2014-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/mpsi.c b/mps/code/mpsi.c index 080b660fac3..9ae6fcbfa97 100644 --- a/mps/code/mpsi.c +++ b/mps/code/mpsi.c @@ -745,16 +745,16 @@ mps_res_t mps_alloc(mps_addr_t *p_o, mps_pool_t pool, size_t size) Addr p; Res res; - AVER(TESTT(Pool, pool)); + AVER_CRITICAL(TESTT(Pool, pool)); arena = PoolArena(pool); ArenaEnter(arena); ArenaPoll(ArenaGlobals(arena)); /* .poll */ - AVER(p_o != NULL); - AVERT(Pool, pool); - AVER(size > 0); + AVER_CRITICAL(p_o != NULL); + AVERT_CRITICAL(Pool, pool); + AVER_CRITICAL(size > 0); /* Note: class may allow unaligned size, see */ /* <design/class-interface/#alloc.size.align>. */ /* Rest ignored, see .varargs. */ @@ -787,13 +787,13 @@ void mps_free(mps_pool_t pool, mps_addr_t p, size_t size) { Arena arena; - AVER(TESTT(Pool, pool)); + AVER_CRITICAL(TESTT(Pool, pool)); arena = PoolArena(pool); ArenaEnter(arena); - AVERT(Pool, pool); - AVER(size > 0); + AVERT_CRITICAL(Pool, pool); + AVER_CRITICAL(size > 0); /* Note: class may allow unaligned size, see */ /* <design/class-interface/#alloc.size.align>. */ diff --git a/mps/code/pool.c b/mps/code/pool.c index bb1a6f34f74..b6e949ed039 100644 --- a/mps/code/pool.c +++ b/mps/code/pool.c @@ -227,22 +227,24 @@ BufferClass PoolDefaultBufferClass(Pool pool) } -/* PoolAlloc -- allocate a block of memory from a pool */ +/* PoolAlloc -- allocate a block of memory from a pool + * + * .alloc.critical: In manual-allocation-bound programs this is on the + * critical path. + */ Res PoolAlloc(Addr *pReturn, Pool pool, Size size) { Res res; - AVER(pReturn != NULL); - AVERT(Pool, pool); - AVER(size > 0); + AVER_CRITICAL(pReturn != NULL); + AVERT_CRITICAL(Pool, pool); + AVER_CRITICAL(size > 0); res = Method(Pool, pool, alloc)(pReturn, pool, size); if (res != ResOK) return res; /* Make sure that the allocated address was in the pool's memory. */ - /* .hasaddr.critical: The PoolHasAddr check is expensive, and in */ - /* allocation-bound programs this is on the critical path. */ AVER_CRITICAL(PoolHasAddr(pool, *pReturn)); /* All allocations should be aligned to the pool's alignment */ AVER_CRITICAL(AddrIsAligned(*pReturn, pool->alignment)); @@ -257,16 +259,20 @@ Res PoolAlloc(Addr *pReturn, Pool pool, Size size) } -/* PoolFree -- deallocate a block of memory allocated from the pool */ +/* PoolFree -- deallocate a block of memory allocated from the pool + * + * .free.critical: In manual-allocation-bound programs this is on the + * critical path. + */ void PoolFree(Pool pool, Addr old, Size size) { - AVERT(Pool, pool); - AVER(old != NULL); + AVERT_CRITICAL(Pool, pool); + AVER_CRITICAL(old != NULL); /* The pool methods should check that old is in pool. */ - AVER(size > 0); - AVER(AddrIsAligned(old, pool->alignment)); - AVER(PoolHasRange(pool, old, AddrAdd(old, size))); + AVER_CRITICAL(size > 0); + AVER_CRITICAL(AddrIsAligned(old, pool->alignment)); + AVER_CRITICAL(PoolHasRange(pool, old, AddrAdd(old, size))); Method(Pool, pool, free)(pool, old, size); @@ -596,8 +602,8 @@ Bool PoolHasRange(Pool pool, Addr base, Addr limit) Arena arena; Bool managed; - AVERT(Pool, pool); - AVER(base < limit); + AVERT_CRITICAL(Pool, pool); + AVER_CRITICAL(base < limit); arena = PoolArena(pool); managed = PoolOfRange(&rangePool, arena, base, limit); diff --git a/mps/code/poolmvff.c b/mps/code/poolmvff.c index de19688a142..1269d92b528 100644 --- a/mps/code/poolmvff.c +++ b/mps/code/poolmvff.c @@ -297,7 +297,11 @@ static Res mvffFindFree(Range rangeReturn, MVFF mvff, Size size, } -/* MVFFAlloc -- Allocate a block */ +/* MVFFAlloc -- Allocate a block + * + * .alloc.critical: In manual-allocation-bound programs this is on the + * critical path. + */ static Res MVFFAlloc(Addr *aReturn, Pool pool, Size size) { @@ -307,11 +311,11 @@ static Res MVFFAlloc(Addr *aReturn, Pool pool, Size size) LandFindMethod findMethod; FindDelete findDelete; - AVER(aReturn != NULL); - AVERT(Pool, pool); + AVER_CRITICAL(aReturn != NULL); + AVERT_CRITICAL(Pool, pool); mvff = PoolMVFF(pool); - AVERT(MVFF, mvff); - AVER(size > 0); + AVERT_CRITICAL(MVFF, mvff); + AVER_CRITICAL(size > 0); size = SizeAlignUp(size, PoolAlignment(pool)); findMethod = mvff->firstFit ? LandFindFirst : LandFindLast; @@ -321,13 +325,17 @@ static Res MVFFAlloc(Addr *aReturn, Pool pool, Size size) if (res != ResOK) return res; - AVER(RangeSize(&range) == size); + AVER_CRITICAL(RangeSize(&range) == size); *aReturn = RangeBase(&range); return ResOK; } -/* MVFFFree -- free the given block */ +/* MVFFFree -- free the given block + * + * .free.critical: In manual-allocation-bound programs this is on the + * critical path. + */ static void MVFFFree(Pool pool, Addr old, Size size) { @@ -335,18 +343,18 @@ static void MVFFFree(Pool pool, Addr old, Size size) RangeStruct range, coalescedRange; MVFF mvff; - AVERT(Pool, pool); + AVERT_CRITICAL(Pool, pool); mvff = PoolMVFF(pool); - AVERT(MVFF, mvff); + AVERT_CRITICAL(MVFF, mvff); - AVER(old != (Addr)0); - AVER(AddrIsAligned(old, PoolAlignment(pool))); - AVER(size > 0); + AVER_CRITICAL(old != (Addr)0); + AVER_CRITICAL(AddrIsAligned(old, PoolAlignment(pool))); + AVER_CRITICAL(size > 0); RangeInitSize(&range, old, SizeAlignUp(size, PoolAlignment(pool))); res = LandInsert(&coalescedRange, MVFFFreeLand(mvff), &range); /* Insertion must succeed because it fails over to a Freelist. */ - AVER(res == ResOK); + AVER_CRITICAL(res == ResOK); MVFFReduce(mvff); } diff --git a/mps/code/splay.c b/mps/code/splay.c index 0030b4aee65..2ec56398532 100644 --- a/mps/code/splay.c +++ b/mps/code/splay.c @@ -1,7 +1,7 @@ /* splay.c: SPLAY TREE IMPLEMENTATION * * $Id$ - * Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * * .purpose: Splay trees are used to manage potentially unbounded * collections of ordered things. In the MPS these are usually @@ -509,9 +509,9 @@ static Compare SplaySplitRev(SplayStateStruct *stateReturn, Tree middle, leftLast, rightFirst; Compare cmp; - AVERT(SplayTree, splay); - AVER(FUNCHECK(compare)); - AVER(!SplayTreeIsEmpty(splay)); + AVERT_CRITICAL(SplayTree, splay); + AVER_CRITICAL(FUNCHECK(compare)); + AVER_CRITICAL(!SplayTreeIsEmpty(splay)); leftLast = TreeEMPTY; rightFirst = TreeEMPTY; @@ -633,8 +633,8 @@ static void SplayAssembleRev(SplayTree splay, SplayState state) { Tree left, right; - AVERT(SplayTree, splay); - AVER(state->middle != TreeEMPTY); + AVERT_CRITICAL(SplayTree, splay); + AVER_CRITICAL(state->middle != TreeEMPTY); left = TreeLeft(state->middle); left = SplayUpdateRightSpine(splay, state->leftLast, left); @@ -1394,7 +1394,7 @@ Res SplayTreeDescribe(SplayTree splay, mps_lib_FILE *stream, Count depth, /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>. + * Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/tract.c b/mps/code/tract.c index 45fbb668c94..badd7615da0 100644 --- a/mps/code/tract.c +++ b/mps/code/tract.c @@ -1,7 +1,7 @@ /* tract.c: PAGE TABLES * * $Id$ - * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * * .ullagepages: Pages whose page index is < allocBase are recorded as * free but never allocated as alloc starts searching after the tables. @@ -60,8 +60,8 @@ Bool TractCheck(Tract tract) void TractInit(Tract tract, Pool pool, Addr base) { - AVER(tract != NULL); - AVERT(Pool, pool); + AVER_CRITICAL(tract != NULL); + AVERT_CRITICAL(Pool, pool); tract->pool.pool = pool; tract->base = base; @@ -456,11 +456,11 @@ void PageAlloc(Chunk chunk, Index pi, Pool pool) Addr base; Page page; - AVERT(Chunk, chunk); - AVER(pi >= chunk->allocBase); - AVER(pi < chunk->pages); - AVER(!BTGet(chunk->allocTable, pi)); - AVERT(Pool, pool); + AVERT_CRITICAL(Chunk, chunk); + AVER_CRITICAL(pi >= chunk->allocBase); + AVER_CRITICAL(pi < chunk->pages); + AVER_CRITICAL(!BTGet(chunk->allocTable, pi)); + AVERT_CRITICAL(Pool, pool); page = ChunkPage(chunk, pi); tract = PageTract(page); @@ -476,9 +476,9 @@ void PageInit(Chunk chunk, Index pi) { Page page; - AVERT(Chunk, chunk); - AVER(pi < chunk->pages); - + AVERT_CRITICAL(Chunk, chunk); + AVER_CRITICAL(pi < chunk->pages); + page = ChunkPage(chunk, pi); BTRes(chunk->allocTable, pi); @@ -504,7 +504,7 @@ void PageFree(Chunk chunk, Index pi) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>. + * Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * From d84baa6eed29120bba1c22fe6d0dcce6b0fdf60e Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Mon, 5 Sep 2016 11:37:19 +0100 Subject: [PATCH 48/52] Don't pick a grain size that's so large that you can't avoid hitting the commit limit. Copied from Perforce Change: 192154 ServerID: perforce.ravenbrook.com --- mps/code/apss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mps/code/apss.c b/mps/code/apss.c index 0e855b07733..6efcf8a1e8d 100644 --- a/mps/code/apss.c +++ b/mps/code/apss.c @@ -230,7 +230,7 @@ int main(int argc, char *argv[]) testlib_init(argc, argv); - arena_grain_size = rnd_grain(2 * testArenaSIZE); + arena_grain_size = rnd_grain(testArenaSIZE); MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, 2 * testArenaSIZE); MPS_ARGS_ADD(args, MPS_KEY_ARENA_GRAIN_SIZE, arena_grain_size); From af67eaaea50b96fb8319c6483b18b6b0fe056781 Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Mon, 5 Sep 2016 12:03:46 +0100 Subject: [PATCH 49/52] Correct the logic in mvfreesize -- lost spans are not accounted as free. only sum the free space in the spans in checking varieties, otherwise just return the cached sum. Copied from Perforce Change: 192159 ServerID: perforce.ravenbrook.com --- mps/code/poolmv.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/mps/code/poolmv.c b/mps/code/poolmv.c index 821c8eea21f..6849d03a2ba 100644 --- a/mps/code/poolmv.c +++ b/mps/code/poolmv.c @@ -1,7 +1,7 @@ /* poolmv.c: MANUAL VARIABLE POOL * * $Id$ - * Copyright (c) 2001-2015 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2016 Ravenbrook Limited. See end of file for license. * Portions copyright (C) 2002 Global Graphics Software. * * **** RESTRICTION: This pool may not allocate from the arena control @@ -733,22 +733,22 @@ static Size MVTotalSize(Pool pool) static Size MVFreeSize(Pool pool) { - MV mv; - Size size = 0; - Ring node, next; + MV mv = MustBeA(MVPool, pool); - AVERT(Pool, pool); - mv = PoolMV(pool); - AVERT(MV, mv); - - RING_FOR(node, &mv->spans, next) { - MVSpan span = RING_ELT(MVSpan, spans, node); - AVERT(MVSpan, span); - size += span->free; +#if defined(AVER_AND_CHECK_ALL) + { + Size size = 0; + Ring node, next; + RING_FOR(node, &mv->spans, next) { + MVSpan span = RING_ELT(MVSpan, spans, node); + AVERT(MVSpan, span); + size += span->free; + } + AVER(size == mv->free); } +#endif - AVER(size == mv->free + mv->lost); - return size; + return mv->free + mv->lost; } @@ -929,7 +929,7 @@ Bool MVCheck(MV mv) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2015 Ravenbrook Limited <http://www.ravenbrook.com/>. + * Copyright (C) 2001-2016 Ravenbrook Limited <http://www.ravenbrook.com/>. * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * From 484c7e3142080325f1fb28d80b177d5a53a8ec30 Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Mon, 5 Sep 2016 13:17:59 +0100 Subject: [PATCH 50/52] When injecting allocation failures to test the fail-over land, don't also inject failures into the arena's free land's block pool. Copied from Perforce Change: 192164 ServerID: perforce.ravenbrook.com --- mps/code/fotest.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/mps/code/fotest.c b/mps/code/fotest.c index 61f1d8745a4..262414bacf7 100644 --- a/mps/code/fotest.c +++ b/mps/code/fotest.c @@ -51,6 +51,10 @@ static mps_res_t make(mps_addr_t *p, mps_ap_t ap, size_t size) } +/* The original alloc method on the MFS pool. */ +static PoolAllocMethod mfs_alloc; + + /* oomAlloc -- allocation function that always fails * * Returns a randomly chosen memory error code. @@ -58,16 +62,25 @@ static mps_res_t make(mps_addr_t *p, mps_ap_t ap, size_t size) static Res oomAlloc(Addr *pReturn, Pool pool, Size size) { + MFS mfs = MustBeA(MFSPool, pool); UNUSED(pReturn); - UNUSED(pool); UNUSED(size); - switch (rnd() % 3) { - case 0: - return ResRESOURCE; - case 1: - return ResMEMORY; - default: - return ResCOMMIT_LIMIT; + if (mfs->extendSelf) { + /* This is the MFS block pool belonging to the CBS belonging to + * the MVFF or MVT pool under test, so simulate a failure to + * enforce the fail-over behaviour. */ + switch (rnd() % 3) { + case 0: + return ResRESOURCE; + case 1: + return ResMEMORY; + default: + return ResCOMMIT_LIMIT; + } + } else { + /* This is the MFS block pool belonging to the arena's free land, + * so succeed here (see job004041). */ + return mfs_alloc(pReturn, pool, size); } } @@ -77,7 +90,6 @@ static Res oomAlloc(Addr *pReturn, Pool pool, Size size) static mps_res_t stress(size_t (*size)(unsigned long, mps_align_t), mps_align_t alignment, mps_pool_t pool) { - PoolAllocMethod mfs_alloc = CLASS_STATIC(MFSPool).alloc; mps_res_t res = MPS_RES_OK; mps_ap_t ap; unsigned long i, k; @@ -158,6 +170,7 @@ int main(int argc, char *argv[]) die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), "mps_arena_create"); + mfs_alloc = CLASS_STATIC(MFSPool).alloc; alignment = sizeof(void *) << (rnd() % 4); MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_EXTEND_BY, (64 + rnd() % 64) * 1024); From ba8ac77fef5d735260bc2a2fe7b61fa44a004afb Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Mon, 5 Sep 2016 15:33:57 +0100 Subject: [PATCH 51/52] Arenainit and arenafinish no longer exist under those names, and there is no longer anything special about them, so remove design documentation. BufferFinishMethod and BufferDescribeMethod were removed, so remove the design documentation for them. Copied from Perforce Change: 192179 ServerID: perforce.ravenbrook.com --- mps/design/arena.txt | 6 ------ mps/design/buffer.txt | 14 -------------- 2 files changed, 20 deletions(-) diff --git a/mps/design/arena.txt b/mps/design/arena.txt index c50d3476982..eb6c74e5dfd 100644 --- a/mps/design/arena.txt +++ b/mps/design/arena.txt @@ -202,12 +202,6 @@ arguments to ``mps_arena_create_k()`` are class-dependent. .. _design.mps.protocol: protocol -_`.class.init`: However, the generic ``ArenaInit()`` is called from the -class-specific method, rather than vice versa, because the method is -responsible for allocating the memory for the arena descriptor and the -arena lock in the first place. Likewise, ``ArenaFinish()`` is called -from the finish method. - _`.class.fields`: The ``grainSize`` (for allocation and freeing) and ``zoneShift`` (for computing zone sizes and what zone an address is in) fields in the arena are the responsibility of the each class, and diff --git a/mps/design/buffer.txt b/mps/design/buffer.txt index a15a63c76f0..5e2b002fd41 100644 --- a/mps/design/buffer.txt +++ b/mps/design/buffer.txt @@ -212,13 +212,6 @@ class-specific behaviour. _`.replay.init`: The ``init()`` method should emit a ``BufferInit<foo>`` event (if there aren't any extra parameters, ``<foo> = ""``). -``typedef void (*BufferFinishMethod)(Buffer buffer)`` - -_`.class.method.finish`: ``finish()`` is a class-specific finish -method called from ``BufferFinish()``. Client-defined methods must -call their superclass method (via a next-method call) after performing -any class-specific behaviour. - ``typedef void (*BufferAttachMethod)(Buffer buffer, Addr base, Addr limit, Addr init, Size size)`` _`.class.method.attach`: ``attach()`` is a class-specific method @@ -256,13 +249,6 @@ setter method which sets the rank set of a buffer. It is called from ``BufferSetRankSet()``. Clients should not need to define their own methods for this. -``typedef Res (*BufferDescribeMethod)(Buffer buffer, mps_lib_FILE *stream, Count depth)`` - -_`.class.method.describe`: ``describe()`` is a class-specific method -called to describe a buffer, via ``BufferDescribe()``. Client-defined -methods must call their superclass method (via a next-method call) -before describing any class-specific state. - Logging ------- From ebfe96633c5574026a49e5bb9a25feb4540b5bf5 Mon Sep 17 00:00:00 2001 From: Gareth Rees <gdr@ravenbrook.com> Date: Mon, 5 Sep 2016 16:04:51 +0100 Subject: [PATCH 52/52] Describe fix for job004000 in the release notes. Copied from Perforce Change: 192190 ServerID: perforce.ravenbrook.com --- mps/manual/source/release.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mps/manual/source/release.rst b/mps/manual/source/release.rst index 61f910919a8..4569a8b49f1 100644 --- a/mps/manual/source/release.rst +++ b/mps/manual/source/release.rst @@ -41,6 +41,14 @@ Other changes .. _job003883: https://www.ravenbrook.com/project/mps/issue/job003883/ +#. When the MPS collects a set of :term:`generations`, it + :term:`condemns` only the :term:`blocks` in those generations. + Previously, it also condemned blocks that happened to share a + region of memory with blocks currently or formerly allocated in + those generations. See job004000_. + + .. _job004000: https://www.ravenbrook.com/project/mps/issue/job004000/ + #. Memory in :term:`allocation points` no longer contributes to the decision to start a collection, avoid wasted work repeatedly collecting generations with very small capacities. See job004007_.