From b3c0f1467eb3796ccfc17dd6be4b6fe46fad413b Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Thu, 17 Apr 2014 23:40:07 +0100 Subject: [PATCH 01/40] Function now called rangecopy. Copied from Perforce Change: 185646 ServerID: perforce.ravenbrook.com --- mps/design/range.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mps/design/range.txt b/mps/design/range.txt index bf0f924430e..1b42d69ac22 100644 --- a/mps/design/range.txt +++ b/mps/design/range.txt @@ -51,7 +51,7 @@ between ``base`` (inclusive) and ``limit`` (exclusive). It must be the case that ``base <= limit``. If ``base == limit`` then the range is empty. -``void RangeInitCopy(Range dest, Range src)`` +``void RangeCopy(Range dest, Range src)`` Initialize ``dest`` to be a copy of ``src``. From 753634c8b040d9a1eebeea5953b45fed0bf1095c Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Thu, 17 Apr 2014 23:41:09 +0100 Subject: [PATCH 02/40] Explain how to declare and update boolean bitfields. SegPrefs are not necessarily to do with segments. Copied from Perforce Change: 185647 ServerID: perforce.ravenbrook.com --- mps/design/type.txt | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/mps/design/type.txt b/mps/design/type.txt index 6ce0da3c035..900980970dc 100644 --- a/mps/design/type.txt +++ b/mps/design/type.txt @@ -151,6 +151,14 @@ compared ``w3i3mv\hi\amcss.exe`` running with and without the macro for ``BoolCheck`` on the PC Aaron. "With" ran in 97.7% of the time (averaged over 3 runs). +_`.bool.bitfield`: When a Boolean needs to be stored in a bitfield, +the type of the bitfield must be ``unsigned:1``, not ``Bool:1``. +(That's because the two values of the type ``Bool:1`` are ``0`` and +``-1``, which means that assigning ``TRUE`` would require a sign +conversion.) To avoid warnings about loss of data from GCC with the +``-Wconversion`` option, ``misc.h`` provides the ``BOOL`` macro for +coercing a value to an unsigned single-bit field. + ``typedef unsigned BufferMode`` @@ -235,7 +243,8 @@ objects. ``typedef Size Epoch`` _`.epoch`: An ``Epoch`` is a count of the number of flips that have -occurred. It is used in the implementation of location dependencies. +occurred, in which objects may have moved. It is used in the +implementation of location dependencies. ``Epoch`` is converted to ``mps_word_t`` in the MPS C Interface, as a field of ``mps_ld_s``. @@ -351,7 +360,7 @@ references must be scanned in order to respect the properties of references of the ranks. Therefore they are declared explicitly with their integer values. -.. note:: Could ``Rank`` be a ``short``? +.. note:: Could ``Rank`` be an ``unsigned short`` or ``unsigned char``? .. note:: @@ -459,30 +468,35 @@ create a valid registered constant root that contains any references. become invalid; but you can't add them afterwards because the root is supposed to be constant.) -_`.rootmode.conv.c`: ``RootMode`` is converted to ``mps_rm_t`` in the MPS C -Interface. +_`.rootmode.conv.c`: ``RootMode`` is converted to ``mps_rm_t`` in the +MPS C Interface. ``typedef int RootVar`` -_`.rootvar`: The type ``RootVar`` is the type of the -discriminator for the union within ``RootStruct``. +_`.rootvar`: The type ``RootVar`` is the type of the discriminator for +the union within ``RootStruct``. ``typedef int SegPrefKind`` -_`.segprefkind`: The type ``SegPrefKind`` expresses a preference about -where the arena should place a segment. It takes one of the following +_`.segprefkind`: The type ``SegPrefKind`` expresses a preference for +addresses within an address space. It takes one of the following values: ================== ==================================================== Kind Description ================== ==================================================== -``SegPrefHigh`` Place the segment high in the address space. -``SegPrefLow`` Place the segment low in the address space. -``SegPrefZoneSet`` Place the segment in specified zones. +``SegPrefHigh`` Prefer high addresses. +``SegPrefLow`` Prefer low addresses. +``SegPrefZoneSet`` Prefer addresses in specified zones. ================== ==================================================== +.. note:: + + The name is misleading as this is used to refer to address + preferences in general, not just addresses of segments. + ``typedef unsigned Serial`` @@ -490,9 +504,8 @@ _`.serial`: A ``Serial`` is a number which is assigned to a structure when it is initialized. The serial number is taken from a field in the parent structure, which is incremented. Thus, every instance of a structure has a unique "name" which is a path of structures from the -global root. For example:: - - space[3].pool[5].buffer[2] +global root. For example, "the third arena's fifth pool's second +buffer". Why? Consistency checking, debugging, and logging. Not well thought out. @@ -509,6 +522,8 @@ right-hand operand of the ``<<`` or ``>>`` operators) is intended, to make the code clear. It should also be used for structure fields which have this use. +.. note:: Could ``Shift`` be an ``unsigned short`` or ``unsigned char``? + ``typedef unsigned long Sig`` @@ -640,7 +655,7 @@ _`.word.ops`: ``WordIsAligned()``, ``WordAlignUp()``, ``typedef Word ZoneSet`` _`.zoneset`: ``ZoneSet`` is a conservative approximation to a set of -zone. See design.mps.refset_. +zones. See design.mps.refset_. Abstract types From 8187140fbe94c89aeb8eeb95690404830a6047a9 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Thu, 17 Apr 2014 23:41:18 +0100 Subject: [PATCH 03/40] Learn some more types. Copied from Perforce Change: 185648 ServerID: perforce.ravenbrook.com --- mps/manual/source/extensions/mps/designs.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mps/manual/source/extensions/mps/designs.py b/mps/manual/source/extensions/mps/designs.py index 57959f1ea0c..230594e9392 100644 --- a/mps/manual/source/extensions/mps/designs.py +++ b/mps/manual/source/extensions/mps/designs.py @@ -22,10 +22,11 @@ TYPES = ''' Arena Attr Bool BootBlock BT Buffer BufferMode Byte Chain Chunk Clock Compare Count Epoch FindDelete Format FrameState Fun Globals Index Land LD Lock Message MessageType MutatorFaultContext Page - Pointer Pool PThreadext Range Rank RankSet Ref Res Reservoir Ring - Root RootMode RootVar ScanState Seg SegBuf SegPref SegPrefKind - Serial Shift Sig Size Space SplayNode SplayTree StackContext - Thread Trace TraceId TraceSet ULongest VM Word ZoneSet + Pointer Pool PThreadext Range Rank RankSet Ref RefSet Res + Reservoir Ring Root RootMode RootVar ScanState Seg SegBuf SegPref + SegPrefKind Serial Shift Sig Size Space SplayNode SplayTree + StackContext Thread Trace TraceId TraceSet TraceStartWhy + TraceState ULongest VM Word ZoneSet ''' From efee845d4ca6920ed3f27c83cdd72b12ddb23e3b Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Fri, 18 Apr 2014 00:41:33 +0100 Subject: [PATCH 04/40] Fix typo. Copied from Perforce Change: 185649 ServerID: perforce.ravenbrook.com --- mps/manual/source/pool/awl.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mps/manual/source/pool/awl.rst b/mps/manual/source/pool/awl.rst index 79df0258804..094335ba3b8 100644 --- a/mps/manual/source/pool/awl.rst +++ b/mps/manual/source/pool/awl.rst @@ -283,9 +283,9 @@ the format of objects allocated in it: "Aligned pointer" means a word whose numeric value (that is, its value when treated as an unsigned integer) is a multiple of the size - of a pointer. For you're using a 32-bit architecture, that means - that an aligned pointer is a multiple of 4 and its bottom two bits - are both zero. + of a pointer. If you're using a 64-bit architecture, that means that + an aligned pointer is a multiple of 8 and its bottom three bits are + zero. The bottom line is that references from an object in an AWL pool must be untagged and aligned, and integers must be tagged with a From 9c4a5de236f874aa1cfecc2291b5af2385e7d0db Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Fri, 18 Apr 2014 08:55:26 +0100 Subject: [PATCH 05/40] Building open dylan side by side with boehm or mps. Copied from Perforce Change: 185650 ServerID: perforce.ravenbrook.com --- mps/tool/testopendylan | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/mps/tool/testopendylan b/mps/tool/testopendylan index a8aee4a0025..0c185ff2fd0 100755 --- a/mps/tool/testopendylan +++ b/mps/tool/testopendylan @@ -20,8 +20,21 @@ # 2. CONFIGURATION -# MPS sources we are testing against -MPS=$(cd -- "$(dirname "$0")/.." && pwd) +# Check command-line argument +GC=$1 +case "$GC" in + mps) + # MPS sources we are testing against + CONFIGURE=--with-gc-path=$(cd -- "$(dirname "$0")/.." && pwd) + ;; + boehm) + CONFIGURE= + ;; + *) + echo "Backend '$GC' not supported: choose mps or boehm." + exit 1 +esac + # OpenDylan version for bootstrapping VERSION=2013.2 @@ -30,7 +43,7 @@ VERSION=2013.2 REMOTE=https://github.com/dylan-lang/opendylan.git # Directory to put everything in -TESTDIR="$PWD/.test" +TESTDIR="$PWD/.test/$GC" mkdir -p -- "$TESTDIR" cd -- "$TESTDIR" @@ -104,7 +117,7 @@ if [ -f "$REPO/Makefile" ]; then else ( cd -- "$REPO" && ./autogen.sh && - ./configure --with-gc=mps --with-gc-path="$MPS" --prefix="$PREFIX" + ./configure --with-gc="$GC" --prefix="$PREFIX" $CONFIGURE ) fi ( cd -- "$REPO" && From 1d6c7ca8f1e68ce6d969371dbd7466b6f4b1d303 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Fri, 18 Apr 2014 10:24:36 +0100 Subject: [PATCH 06/40] Fix typo. Copied from Perforce Change: 185659 ServerID: perforce.ravenbrook.com --- mps/procedure/release-build.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/mps/procedure/release-build.rst b/mps/procedure/release-build.rst index bdce60df4ca..ee65b5f645d 100644 --- a/mps/procedure/release-build.rst +++ b/mps/procedure/release-build.rst @@ -47,7 +47,7 @@ All relative paths are relative to 1.111.0), where *VERSION* is the number of the version you’re releasing, and *N* is the first unused release number (starting at zero). Look in the index of releases (``release/index.html``) for - existing release numbers for your version:: + existing release numbers for your version. :: VERSION=A.BBB RELEASE=$VERSION.N @@ -111,7 +111,7 @@ Run the script ``tool/release``, passing the options: * ``-P mps`` — project name * ``-b BRANCH`` — branch to make the release from: for example ``version/1.113`` * ``-C CHANGELEVEL`` — changelevel at which to make the release -* ``-d "DESCRIPTION"`` — changelevel at which to make the release +* ``-d "DESCRIPTION"`` — description of the release * ``-y`` — yes, really make the release If omitted, the project and branch are deduced from the current @@ -231,8 +231,6 @@ A. References Ravenbrook Limited; 2008-10-16; http://info.ravenbrook.com/mail/2008/10/16/13-08-20/0.txt -.. [Sphinx] "Sphinx: Python document generator"; http://sphinx-doc.org/ - B. Document History ------------------- From 831e3c1a3e189f9aabe4b46d10e289dbd797eb7a Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Sun, 20 Apr 2014 22:53:49 +0100 Subject: [PATCH 07/40] Improve help text. Copied from Perforce Change: 185701 ServerID: perforce.ravenbrook.com --- mps/tool/p4-bisect | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mps/tool/p4-bisect b/mps/tool/p4-bisect index 5fa77639e30..2886d823c59 100755 --- a/mps/tool/p4-bisect +++ b/mps/tool/p4-bisect @@ -130,7 +130,9 @@ def run(args): exit(result) def main(argv): - parser = argparse.ArgumentParser(prog='p4-bisect') + parser = argparse.ArgumentParser( + prog='p4-bisect', epilog='For help on CMD, use p4-bisect CMD -h') + parser.set_defaults(func=partial(help, parser)) subparsers = parser.add_subparsers() a = subparsers.add_parser From 5cd16daeb4525f2bf8f900a5be99b67d8c214137 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Tue, 22 Apr 2014 14:45:51 +0100 Subject: [PATCH 08/40] Branching master to branch/2014-04-22/condemn. Copied from Perforce Change: 185735 ServerID: perforce.ravenbrook.com From 6ffd4c7df53740579360ee2dfa06e83c63e0cabf Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Tue, 22 Apr 2014 17:53:47 +0100 Subject: [PATCH 09/40] Fix bugs in condemn logic: 1. TraceStartCollectAll now condemns all segments in pools with AttrGC (not just pools attached to generation zero of some chain, as before). 2. ChainDeferral now looks at all generations in the chain, so that the chain is condemned if any generation's new size is greater than its capacity (not just generation zero, as before). 3. ChainCondemnAuto now condemns all generations up to and including the highest generation whose new size is greater than its capacity (rather than, as before, up to and excluding the lowest generation whose new size is lower than its capacity). Update finaltest.c so that it has a mode in which it allocates in generation 1 of a chain and with the arena released so that the above fixes are tested. Remove the MPS_KEY_GEN workarounds from awlut and awluthe as these are no longer needed. Copied from Perforce Change: 185741 ServerID: perforce.ravenbrook.com --- mps/code/awlut.c | 3 -- mps/code/awluthe.c | 3 -- mps/code/chain.h | 1 - mps/code/finaltest.c | 104 +++++++++++++++++++++++++++++++++---------- mps/code/locus.c | 100 +++++++++++++++++------------------------ mps/code/trace.c | 28 ++++++++---- 6 files changed, 140 insertions(+), 99 deletions(-) diff --git a/mps/code/awlut.c b/mps/code/awlut.c index c62153ed44c..464a2dba91f 100644 --- a/mps/code/awlut.c +++ b/mps/code/awlut.c @@ -275,9 +275,6 @@ static void *setup(void *v, size_t s) die(mps_fmt_create_A(&dylanweakfmt, arena, dylan_fmt_A_weak()), "Format Create (weak)\n"); MPS_ARGS_BEGIN(args) { - /* Ask the leafpool to allocate in the nursery, as we're using it to test - weaknesss and want things to die in it promptly. */ - MPS_ARGS_ADD(args, MPS_KEY_GEN, 0); MPS_ARGS_ADD(args, MPS_KEY_FORMAT, dylanfmt); die(mps_pool_create_k(&leafpool, arena, mps_class_lo(), args), "Leaf Pool Create\n"); diff --git a/mps/code/awluthe.c b/mps/code/awluthe.c index d3b2d572319..6ea468977f1 100644 --- a/mps/code/awluthe.c +++ b/mps/code/awluthe.c @@ -277,9 +277,6 @@ static void *setup(void *v, size_t s) die(EnsureHeaderFormat(&dylanfmt, arena), "EnsureHeaderFormat"); die(EnsureHeaderWeakFormat(&dylanweakfmt, arena), "EnsureHeaderWeakFormat"); MPS_ARGS_BEGIN(args) { - /* Ask the leafpool to allocate in the nursery, as we're using it to test - weaknesss and want things to die in it promptly. */ - MPS_ARGS_ADD(args, MPS_KEY_GEN, 0); MPS_ARGS_ADD(args, MPS_KEY_FORMAT, dylanfmt); die(mps_pool_create_k(&leafpool, arena, mps_class_lo(), args), "Leaf Pool Create\n"); diff --git a/mps/code/chain.h b/mps/code/chain.h index e47f8000c0b..ec5bc228ebf 100644 --- a/mps/code/chain.h +++ b/mps/code/chain.h @@ -81,7 +81,6 @@ extern Bool ChainCheck(Chain chain); extern double ChainDeferral(Chain chain); extern Res ChainCondemnAuto(double *mortalityReturn, Chain chain, Trace trace); -extern Res ChainCondemnAll(Chain chain, Trace trace); extern void ChainStartGC(Chain chain, Trace trace); extern void ChainEndGC(Chain chain, Trace trace); extern size_t ChainGens(Chain chain); diff --git a/mps/code/finaltest.c b/mps/code/finaltest.c index 88895027286..a9580bfcbdf 100644 --- a/mps/code/finaltest.c +++ b/mps/code/finaltest.c @@ -6,6 +6,20 @@ * * DESIGN * + * .mode: This test has two modes. + * + * .mode.park: In this mode, we use the arena's default generation + * chain, leave the arena parked and call mps_arena_collect. This + * tests that the default generation chain works and that all segments + * get condemned via TraceStartCollectAll. (See job003771 item 4.) + * + * .mode.poll: In this mode, we use our own generation chain (with + * small generations), allocate into generation 1, unclamp the arena, + * and provoke collection by allocating. This tests that custom + * generation chains work, and that segments get condemned via + * TracePoll even if there is no allocation into generation 0 of the + * chain. (See job003771 item 5.) + * * DEPENDENCIES * * This test uses the dylan object format, but the reliance on this @@ -16,6 +30,7 @@ * This code was created by first copying */ +#include "mpm.h" #include "testlib.h" #include "mpslib.h" #include "mps.h" @@ -30,10 +45,15 @@ #include /* fflush, printf, stdout */ +enum { + ModePARK, /* .mode.park */ + ModePOLL /* .mode.poll */ +}; + #define testArenaSIZE ((size_t)16<<20) #define rootCOUNT 20 -#define maxtreeDEPTH 10 +#define maxtreeDEPTH 9 #define collectionCOUNT 10 @@ -126,17 +146,21 @@ static mps_addr_t test_awl_find_dependent(mps_addr_t addr) static void *root[rootCOUNT]; -static void test_trees(const char *name, mps_arena_t arena, mps_ap_t ap, +static void test_trees(int mode, const char *name, mps_arena_t arena, + mps_ap_t ap, mps_word_t (*make)(mps_word_t, mps_ap_t), void (*reg)(mps_word_t, mps_arena_t)) { size_t collections = 0; size_t finals = 0; size_t i; + int object_alloc; object_count = 0; printf("Making some %s finalized trees of objects.\n", name); + mps_arena_park(arena); + /* make some trees */ for(i = 0; i < rootCOUNT; ++i) { root[i] = (void *)(*make)(maxtreeDEPTH, ap); @@ -151,10 +175,23 @@ static void test_trees(const char *name, mps_arena_t arena, mps_ap_t ap, while (finals < object_count && collections < collectionCOUNT) { mps_word_t final_this_time = 0; - printf("Collecting..."); - (void)fflush(stdout); - die(mps_arena_collect(arena), "collect"); - printf(" Done.\n"); + switch (mode) { + default: + case ModePARK: + printf("Collecting..."); + (void)fflush(stdout); + die(mps_arena_collect(arena), "collect"); + printf(" Done.\n"); + break; + case ModePOLL: + mps_arena_release(arena); + printf("Allocating..."); + (void)fflush(stdout); + object_alloc = 0; + while (object_alloc < 1000 && !mps_message_poll(arena)) + (void)DYLAN_INT(object_alloc++); + break; + } ++ collections; while (mps_message_poll(arena)) { mps_message_t message; @@ -170,10 +207,14 @@ static void test_trees(const char *name, mps_arena_t arena, mps_ap_t ap, " of %"PRIuLONGEST"\n", (ulongest_t)final_this_time, (ulongest_t)finals, (ulongest_t)object_count); } - cdie(finals == object_count, "Not all objects were finalized."); + if (finals != object_count) + error("Not all objects were finalized for %s in mode %s.", + BufferOfAP(ap)->pool->class->name, + mode == ModePOLL ? "POLL" : "PARK"); } -static void *test(mps_arena_t arena, mps_class_t pool_class) +static void test_pool(int mode, mps_arena_t arena, mps_chain_t chain, + mps_class_t pool_class) { mps_ap_t ap; mps_fmt_t fmt; @@ -182,10 +223,13 @@ static void *test(mps_arena_t arena, mps_class_t pool_class) die(mps_fmt_create_A(&fmt, arena, dylan_fmt_A()), "fmt_create\n"); MPS_ARGS_BEGIN(args) { - /* Allocate into generation 0 so that they get finalized quickly. */ - MPS_ARGS_ADD(args, MPS_KEY_GEN, 0); MPS_ARGS_ADD(args, MPS_KEY_FORMAT, fmt); - MPS_ARGS_ADD(args, MPS_KEY_AWL_FIND_DEPENDENT, test_awl_find_dependent); + if (mode == ModePOLL) { + MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain); + MPS_ARGS_ADD(args, MPS_KEY_GEN, 1); + } + if (pool_class == mps_class_awl()) + MPS_ARGS_ADD(args, MPS_KEY_AWL_FIND_DEPENDENT, test_awl_find_dependent); die(mps_pool_create_k(&pool, arena, pool_class, args), "pool_create\n"); } MPS_ARGS_END(args); @@ -194,19 +238,25 @@ static void *test(mps_arena_t arena, mps_class_t pool_class) "root_create\n"); die(mps_ap_create(&ap, pool, mps_rank_exact()), "ap_create\n"); - mps_message_type_enable(arena, mps_message_type_finalization()); - - mps_arena_park(arena); - - test_trees("numbered", arena, ap, make_numbered_tree, register_numbered_tree); - test_trees("indirect", arena, ap, make_indirect_tree, register_indirect_tree); + test_trees(mode, "numbered", arena, ap, make_numbered_tree, + register_numbered_tree); + test_trees(mode, "indirect", arena, ap, make_indirect_tree, + register_indirect_tree); mps_ap_destroy(ap); mps_root_destroy(mps_root); mps_pool_destroy(pool); mps_fmt_destroy(fmt); +} - return NULL; + +static void test_mode(int mode, mps_arena_t arena, mps_chain_t chain) +{ + test_pool(mode, arena, chain, mps_class_amc()); + test_pool(mode, arena, chain, mps_class_amcz()); + test_pool(mode, arena, chain, mps_class_ams()); + /* test_pool(mode, arena, chain, mps_class_lo()); TODO: job003772 */ + /* test_pool(mode, arena, chain, mps_class_awl()); TODO: job003772 */ } @@ -214,19 +264,27 @@ int main(int argc, char *argv[]) { mps_arena_t arena; mps_thr_t thread; + mps_chain_t chain; + mps_gen_param_s params[2]; + size_t gens = 2; + size_t i; testlib_init(argc, argv); die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), "arena_create\n"); + mps_message_type_enable(arena, mps_message_type_finalization()); die(mps_thread_reg(&thread, arena), "thread_reg\n"); + for (i = 0; i < gens; ++i) { + params[i].mps_capacity = 1; + params[i].mps_mortality = 0.5; + } + die(mps_chain_create(&chain, arena, gens, params), "chain_create\n"); - test(arena, mps_class_amc()); - test(arena, mps_class_amcz()); - test(arena, mps_class_ams()); - test(arena, mps_class_awl()); - /* TODO: test(arena, mps_class_lo()); */ + test_mode(ModePOLL, arena, chain); + test_mode(ModePARK, arena, NULL); + mps_chain_destroy(chain); mps_thread_dereg(thread); mps_arena_destroy(arena); diff --git a/mps/code/locus.c b/mps/code/locus.c index a704c8b820b..e69b276ab93 100644 --- a/mps/code/locus.c +++ b/mps/code/locus.c @@ -287,13 +287,20 @@ Res ChainAlloc(Seg *segReturn, Chain chain, Serial genNr, SegClass class, double ChainDeferral(Chain chain) { + double time = DBL_MAX; + size_t i; + AVERT(Chain, chain); - if (chain->activeTraces != TraceSetEMPTY) - return DBL_MAX; - else - return chain->gens[0].capacity * 1024.0 - - (double)GenDescNewSize(&chain->gens[0]); + if (chain->activeTraces == TraceSetEMPTY) + for (i = 0; i < chain->genCount; ++i) { + double genTime = chain->gens[i].capacity * 1024.0 + - (double)GenDescNewSize(&chain->gens[i]); + if (genTime < time) + time = genTime; + } + + return time; } @@ -306,7 +313,7 @@ double ChainDeferral(Chain chain) Res ChainCondemnAuto(double *mortalityReturn, Chain chain, Trace trace) { Res res; - Serial topCondemnedGenSerial, currGenSerial; + size_t topCondemnedGen, i; GenDesc gen; ZoneSet condemnedSet = ZoneSetEMPTY; Size condemnedSize = 0, survivorSize = 0, genNewSize, genTotalSize; @@ -314,33 +321,39 @@ Res ChainCondemnAuto(double *mortalityReturn, Chain chain, Trace trace) AVERT(Chain, chain); AVERT(Trace, trace); - /* Find lowest gen within its capacity, set topCondemnedGenSerial to the */ - /* preceeding one. */ - currGenSerial = 0; - gen = &chain->gens[0]; - AVERT(GenDesc, gen); - genNewSize = GenDescNewSize(gen); - do { /* At this point, we've decided to collect currGenSerial. */ - topCondemnedGenSerial = currGenSerial; + /* Find the highest generation that's over capacity. We will condemn + * this and all lower generations in the chain. */ + topCondemnedGen = chain->genCount; + for (;;) { + /* It's an error to call this function unless some generation is + * over capacity as reported by ChainDeferral. */ + AVER(topCondemnedGen > 0); + if (topCondemnedGen == 0) + return ResFAIL; + -- topCondemnedGen; + gen = &chain->gens[topCondemnedGen]; + AVERT(GenDesc, gen); + genNewSize = GenDescNewSize(gen); + if (genNewSize >= gen->capacity * (Size)1024) + break; + } + + /* At this point, we've decided to condemn topCondemnedGen and all + * lower generations. */ + for (i = 0; i <= topCondemnedGen; ++i) { + gen = &chain->gens[i]; + AVERT(GenDesc, gen); condemnedSet = ZoneSetUnion(condemnedSet, gen->zones); genTotalSize = GenDescTotalSize(gen); + genNewSize = GenDescNewSize(gen); condemnedSize += genTotalSize; survivorSize += (Size)(genNewSize * (1.0 - gen->mortality)) /* predict survivors will survive again */ + (genTotalSize - genNewSize); - - /* is there another one to consider? */ - currGenSerial += 1; - if (currGenSerial >= chain->genCount) - break; /* reached the top */ - gen = &chain->gens[currGenSerial]; - AVERT(GenDesc, gen); - genNewSize = GenDescNewSize(gen); - } while (genNewSize >= gen->capacity * (Size)1024); + } AVER(condemnedSet != ZoneSetEMPTY || condemnedSize == 0); - EVENT3(ChainCondemnAuto, chain, topCondemnedGenSerial, chain->genCount); - UNUSED(topCondemnedGenSerial); /* only used for EVENT */ + EVENT3(ChainCondemnAuto, chain, topCondemnedGen, chain->genCount); /* Condemn everything in these zones. */ if (condemnedSet != ZoneSetEMPTY) { @@ -354,41 +367,6 @@ Res ChainCondemnAuto(double *mortalityReturn, Chain chain, Trace trace) } -/* ChainCondemnAll -- condemn everything in the chain */ - -Res ChainCondemnAll(Chain chain, Trace trace) -{ - Ring node, nextNode; - Bool haveWhiteSegs = FALSE; - Res res; - - /* Condemn every segment in every pool using this chain. */ - /* Finds the pools by iterating over the PoolGens in gen 0. */ - RING_FOR(node, &chain->gens[0].locusRing, nextNode) { - PoolGen nursery = RING_ELT(PoolGen, genRing, node); - Pool pool = nursery->pool; - Ring segNode, nextSegNode; - - AVERT(Pool, pool); - AVER(PoolHasAttr(pool, AttrGC)); - RING_FOR(segNode, PoolSegRing(pool), nextSegNode) { - Seg seg = SegOfPoolRing(segNode); - - res = TraceAddWhite(trace, seg); - if (res != ResOK) - goto failBegin; - haveWhiteSegs = TRUE; - } - } - - return ResOK; - -failBegin: - AVER(!haveWhiteSegs); /* Would leave white sets inconsistent. */ - return res; -} - - /* ChainStartGC -- called to notify start of GC for this chain */ void ChainStartGC(Chain chain, Trace trace) @@ -416,9 +394,11 @@ void ChainEndGC(Chain chain, Trace trace) Res PoolGenInit(PoolGen gen, Chain chain, Serial nr, Pool pool) { /* Can't check gen, because it's not been initialized. */ + AVER(gen != NULL); AVERT(Chain, chain); AVER(nr <= chain->genCount); AVERT(Pool, pool); + AVER(PoolHasAttr(pool, AttrGC)); gen->nr = nr; gen->pool = pool; diff --git a/mps/code/trace.c b/mps/code/trace.c index 61e9d396155..5a656e9489d 100644 --- a/mps/code/trace.c +++ b/mps/code/trace.c @@ -1503,21 +1503,31 @@ static Res traceCondemnAll(Trace trace) { Res res; Arena arena; - Ring chainNode, nextChainNode; + Ring poolNode, nextPoolNode, chainNode, nextChainNode; Bool haveWhiteSegs = FALSE; arena = trace->arena; AVERT(Arena, arena); - /* Condemn all the chains. */ - RING_FOR(chainNode, &arena->chainRing, nextChainNode) { - Chain chain = RING_ELT(Chain, chainRing, chainNode); - AVERT(Chain, chain); - res = ChainCondemnAll(chain, trace); - if(res != ResOK) - goto failBegin; - haveWhiteSegs = TRUE; + /* Condemn all segments in pools with the GC attribute. */ + RING_FOR(poolNode, &ArenaGlobals(arena)->poolRing, nextPoolNode) { + Pool pool = RING_ELT(Pool, arenaRing, poolNode); + AVERT(Pool, pool); + + if (PoolHasAttr(pool, AttrGC)) { + Ring segNode, nextSegNode; + RING_FOR(segNode, PoolSegRing(pool), nextSegNode) { + Seg seg = SegOfPoolRing(segNode); + AVERT(Seg, seg); + + res = TraceAddWhite(trace, seg); + if (res != ResOK) + goto failBegin; + haveWhiteSegs = TRUE; + } + } } + /* Notify all the chains. */ RING_FOR(chainNode, &arena->chainRing, nextChainNode) { Chain chain = RING_ELT(Chain, chainRing, chainNode); From 8815555fd9df1ea39e8ed69605df6b11f4c74ba3 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Tue, 22 Apr 2014 21:40:59 +0100 Subject: [PATCH 10/40] Separate jobs for lo and awl finalization. Copied from Perforce Change: 185743 ServerID: perforce.ravenbrook.com --- mps/code/finaltest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mps/code/finaltest.c b/mps/code/finaltest.c index a9580bfcbdf..f449d7e1acf 100644 --- a/mps/code/finaltest.c +++ b/mps/code/finaltest.c @@ -255,7 +255,7 @@ static void test_mode(int mode, mps_arena_t arena, mps_chain_t chain) test_pool(mode, arena, chain, mps_class_amc()); test_pool(mode, arena, chain, mps_class_amcz()); test_pool(mode, arena, chain, mps_class_ams()); - /* test_pool(mode, arena, chain, mps_class_lo()); TODO: job003772 */ + /* test_pool(mode, arena, chain, mps_class_lo()); TODO: job003773 */ /* test_pool(mode, arena, chain, mps_class_awl()); TODO: job003772 */ } From 204abf130ec599c069af5613584f91b0e1d873ed Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Tue, 22 Apr 2014 21:57:16 +0100 Subject: [PATCH 11/40] Fix indentation. Copied from Perforce Change: 185746 ServerID: perforce.ravenbrook.com --- mps/code/locus.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mps/code/locus.c b/mps/code/locus.c index e69b276ab93..6e6e22128b7 100644 --- a/mps/code/locus.c +++ b/mps/code/locus.c @@ -292,12 +292,13 @@ double ChainDeferral(Chain chain) AVERT(Chain, chain); - if (chain->activeTraces == TraceSetEMPTY) + if (chain->activeTraces == TraceSetEMPTY) { for (i = 0; i < chain->genCount; ++i) { double genTime = chain->gens[i].capacity * 1024.0 - (double)GenDescNewSize(&chain->gens[i]); if (genTime < time) time = genTime; + } } return time; From 4ed2986197d06c80e9c32647d7d79bedaf0af3df Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Tue, 22 Apr 2014 23:18:42 +0100 Subject: [PATCH 12/40] Test the arena default chain. set the commit limit to make sure that the collector can make progress. Copied from Perforce Change: 185749 ServerID: perforce.ravenbrook.com --- mps/code/amsss.c | 90 +++++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 46 deletions(-) diff --git a/mps/code/amsss.c b/mps/code/amsss.c index 1d04f199349..e4e66ae0529 100644 --- a/mps/code/amsss.c +++ b/mps/code/amsss.c @@ -27,7 +27,7 @@ #define totalSizeSTEP 200 * (size_t)1024 /* objNULL needs to be odd so that it's ignored in exactRoots. */ #define objNULL ((mps_addr_t)MPS_WORD_CONST(0xDECEA5ED)) -#define testArenaSIZE ((size_t)16<<20) +#define testArenaSIZE ((size_t)1<<20) #define initTestFREQ 3000 #define splatTestFREQ 6000 static mps_gen_param_s testChain[1] = { { 160, 0.90 } }; @@ -107,7 +107,8 @@ static mps_addr_t make(void) static mps_pool_debug_option_s freecheckOptions = { NULL, 0, (const void *)"Dead", 4 }; -static void *test(void *arg, size_t haveAmbigous) +static void test_pool(mps_class_t pool_class, mps_arg_s args[], + size_t haveAmbiguous) { mps_pool_t pool; mps_root_t exactRoot, ambigRoot = NULL; @@ -116,14 +117,13 @@ static void *test(void *arg, size_t haveAmbigous) mps_ap_t busy_ap; mps_addr_t busy_init; - pool = (mps_pool_t)arg; - + die(mps_pool_create_k(&pool, arena, pool_class, args), "pool_create"); die(mps_ap_create(&ap, pool, mps_rank_exact()), "BufferCreate"); die(mps_ap_create(&busy_ap, pool, mps_rank_exact()), "BufferCreate 2"); for(i = 0; i < exactRootsCOUNT; ++i) exactRoots[i] = objNULL; - if (haveAmbigous) + if (haveAmbiguous) for(i = 0; i < ambigRootsCOUNT; ++i) ambigRoots[i] = rnd_addr(); @@ -132,7 +132,7 @@ static void *test(void *arg, size_t haveAmbigous) &exactRoots[0], exactRootsCOUNT, (mps_word_t)1), "root_create_table(exact)"); - if (haveAmbigous) + if (haveAmbiguous) die(mps_root_create_table(&ambigRoot, arena, mps_rank_ambig(), (mps_rm_t)0, &ambigRoots[0], ambigRootsCOUNT), @@ -154,7 +154,7 @@ static void *test(void *arg, size_t haveAmbigous) } r = (size_t)rnd(); - if (!haveAmbigous || (r & 1)) { + if (!haveAmbiguous || (r & 1)) { i = (r >> 1) % exactRootsCOUNT; if (exactRoots[i] != objNULL) cdie(dylan_check(exactRoots[i]), "dying root check"); @@ -187,10 +187,10 @@ static void *test(void *arg, size_t haveAmbigous) mps_ap_destroy(busy_ap); mps_ap_destroy(ap); mps_root_destroy(exactRoot); - if (haveAmbigous) + if (haveAmbiguous) mps_root_destroy(ambigRoot); - return NULL; + mps_pool_destroy(pool); } @@ -199,68 +199,66 @@ int main(int argc, char *argv[]) mps_thr_t thread; mps_fmt_t format; mps_chain_t chain; - mps_pool_t pool; - void *r; testlib_init(argc, argv); die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), "arena_create"); + die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), "commit_limit_set"); + mps_message_type_enable(arena, mps_message_type_gc_start()); mps_message_type_enable(arena, mps_message_type_gc()); die(mps_thread_reg(&thread, arena), "thread_reg"); die(mps_fmt_create_A(&format, arena, dylan_fmt_A()), "fmt_create"); die(mps_chain_create(&chain, arena, 1, testChain), "chain_create"); - /* TODO: Add tests using the arena default chain. */ + printf("\n\n*** AMS with !CHAIN and SUPPORT_AMBIGUOUS\n"); + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format); + MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, TRUE); + test_pool(mps_class_ams(), args, TRUE); + } MPS_ARGS_END(args); - printf("\n\n****************************** Testing AMS Debug\n"); + printf("\n\n*** AMS with !CHAIN and !SUPPORT_AMBIGUOUS\n"); + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format); + MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, FALSE); + test_pool(mps_class_ams(), args, FALSE); + } MPS_ARGS_END(args); + + printf("\n\n*** AMS with CHAIN and SUPPORT_AMBIGUOUS\n"); + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain); + MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format); + MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, TRUE); + test_pool(mps_class_ams(), args, TRUE); + } MPS_ARGS_END(args); + + printf("\n\n*** AMS with CHAIN and !SUPPORT_AMBIGUOUS\n"); + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain); + MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format); + MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, FALSE); + test_pool(mps_class_ams(), args, FALSE); + } MPS_ARGS_END(args); + + printf("\n\n*** AMS Debug with CHAIN and !SUPPORT_AMBIGUOUS\n"); MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain); MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format); MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, FALSE); MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, &freecheckOptions); - die(mps_pool_create_k(&pool, arena, mps_class_ams_debug(), args), - "pool_create(ams_debug,share)"); + test_pool(mps_class_ams_debug(), args, FALSE); } MPS_ARGS_END(args); - mps_tramp(&r, test, pool, 0); - mps_pool_destroy(pool); - printf("\n\n****************************** Testing AMS Debug\n"); + printf("\n\n*** AMS Debug with CHAIN and SUPPORT_AMBIGUOUS\n"); MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain); MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format); MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, TRUE); MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, &freecheckOptions); - die(mps_pool_create_k(&pool, arena, mps_class_ams_debug(), args), - "pool_create(ams_debug,ambig)"); + test_pool(mps_class_ams_debug(), args, TRUE); } MPS_ARGS_END(args); - mps_tramp(&r, test, pool, 1); - mps_pool_destroy(pool); - - printf("\n\n****************************** Testing AMS\n"); - MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain); - MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format); - MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, TRUE); - MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, &freecheckOptions); - die(mps_pool_create_k(&pool, arena, mps_class_ams(), args), - "pool_create(ams,ambig)"); - } MPS_ARGS_END(args); - mps_tramp(&r, test, pool, 1); - mps_pool_destroy(pool); - - printf("\n\n****************************** Testing AMS\n"); - MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain); - MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format); - MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, FALSE); - MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, &freecheckOptions); - die(mps_pool_create_k(&pool, arena, mps_class_ams(), args), - "pool_create(ams,share)"); - } MPS_ARGS_END(args); - mps_tramp(&r, test, pool, 0); - mps_pool_destroy(pool); mps_chain_destroy(chain); mps_fmt_destroy(format); From ca7dab39da319f4b0500663717da08fc3cc23374 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 23 Apr 2014 19:42:27 +0100 Subject: [PATCH 13/40] Test all 8 combinations of debug, chain, ambig. Copied from Perforce Change: 185763 ServerID: perforce.ravenbrook.com --- mps/code/amsss.c | 65 ++++++++++++++---------------------------------- 1 file changed, 18 insertions(+), 47 deletions(-) diff --git a/mps/code/amsss.c b/mps/code/amsss.c index e4e66ae0529..8538fd354e2 100644 --- a/mps/code/amsss.c +++ b/mps/code/amsss.c @@ -196,6 +196,7 @@ static void test_pool(mps_class_t pool_class, mps_arg_s args[], int main(int argc, char *argv[]) { + int i; mps_thr_t thread; mps_fmt_t format; mps_chain_t chain; @@ -212,53 +213,23 @@ int main(int argc, char *argv[]) die(mps_fmt_create_A(&format, arena, dylan_fmt_A()), "fmt_create"); die(mps_chain_create(&chain, arena, 1, testChain), "chain_create"); - printf("\n\n*** AMS with !CHAIN and SUPPORT_AMBIGUOUS\n"); - MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format); - MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, TRUE); - test_pool(mps_class_ams(), args, TRUE); - } MPS_ARGS_END(args); - - printf("\n\n*** AMS with !CHAIN and !SUPPORT_AMBIGUOUS\n"); - MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format); - MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, FALSE); - test_pool(mps_class_ams(), args, FALSE); - } MPS_ARGS_END(args); - - printf("\n\n*** AMS with CHAIN and SUPPORT_AMBIGUOUS\n"); - MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain); - MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format); - MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, TRUE); - test_pool(mps_class_ams(), args, TRUE); - } MPS_ARGS_END(args); - - printf("\n\n*** AMS with CHAIN and !SUPPORT_AMBIGUOUS\n"); - MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain); - MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format); - MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, FALSE); - test_pool(mps_class_ams(), args, FALSE); - } MPS_ARGS_END(args); - - printf("\n\n*** AMS Debug with CHAIN and !SUPPORT_AMBIGUOUS\n"); - MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain); - MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format); - MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, FALSE); - MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, &freecheckOptions); - test_pool(mps_class_ams_debug(), args, FALSE); - } MPS_ARGS_END(args); - - printf("\n\n*** AMS Debug with CHAIN and SUPPORT_AMBIGUOUS\n"); - MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain); - MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format); - MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, TRUE); - MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, &freecheckOptions); - test_pool(mps_class_ams_debug(), args, TRUE); - } MPS_ARGS_END(args); + for (i = 0; i < 8; i++) { + int debug = i % 2; + int ownChain = (i / 2) % 2; + int ambig = (i / 4) % 2; + printf("\n\n*** AMS%s with %sCHAIN and %sSUPPORT_AMBIGUOUS\n", + debug ? " Debug" : "", + ownChain ? "" : "!", + ambig ? "" : "!"); + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format); + if (chain) + MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain); + MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, ambig); + MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, &freecheckOptions); + test_pool(debug ? mps_class_ams_debug() : mps_class_ams(), args, TRUE); + } MPS_ARGS_END(args); + } mps_chain_destroy(chain); mps_fmt_destroy(format); From b674ece7495d9427be486688ba4da0aead7eee8f Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 23 Apr 2014 20:22:19 +0100 Subject: [PATCH 14/40] Tracecondemnzones could leave the white set inconsistent if traceaddwhite failed. add an assertion to cover this case (corresponding to the similar assertion in tracecondemnall). Copied from Perforce Change: 185765 ServerID: perforce.ravenbrook.com --- mps/code/trace.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mps/code/trace.c b/mps/code/trace.c index 5a656e9489d..76769583748 100644 --- a/mps/code/trace.c +++ b/mps/code/trace.c @@ -390,6 +390,7 @@ Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet) Seg seg; Arena arena; Res res; + Bool haveWhiteSegs = FALSE; AVERT(Trace, trace); AVER(condemnedSet != ZoneSetEMPTY); @@ -414,8 +415,11 @@ Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet) && ZoneSetSuper(condemnedSet, ZoneSetOfSeg(arena, seg))) { res = TraceAddWhite(trace, seg); - if(res != ResOK) + if(res != ResOK) { + AVER(!haveWhiteSegs); /* Would leave white sets inconsistent. */ return res; + } + haveWhiteSegs = TRUE; } } while (SegNext(&seg, arena, seg)); } From b888d047ba835412fc23bf7b0bd705757ecdde63 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Fri, 25 Apr 2014 17:41:56 +0100 Subject: [PATCH 15/40] Explain traceaddwhite failure logic as requested by nb in . Copied from Perforce Change: 185800 ServerID: perforce.ravenbrook.com --- mps/code/trace.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/mps/code/trace.c b/mps/code/trace.c index 76769583748..f94d245fbf7 100644 --- a/mps/code/trace.c +++ b/mps/code/trace.c @@ -415,10 +415,8 @@ Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet) && ZoneSetSuper(condemnedSet, ZoneSetOfSeg(arena, seg))) { res = TraceAddWhite(trace, seg); - if(res != ResOK) { - AVER(!haveWhiteSegs); /* Would leave white sets inconsistent. */ - return res; - } + if(res != ResOK) + goto failBegin; haveWhiteSegs = TRUE; } } while (SegNext(&seg, arena, seg)); @@ -430,6 +428,10 @@ Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet) AVER(ZoneSetSuper(condemnedSet, trace->white)); return ResOK; + +failBegin: + AVER(!haveWhiteSegs); /* See .whiten.fail. */ + return res; } @@ -1541,7 +1543,14 @@ static Res traceCondemnAll(Trace trace) return ResOK; failBegin: - AVER(!haveWhiteSegs); /* Would leave white sets inconsistent. */ + /* .whiten.fail: If we successfully whitened one or more segments, + * but failed to whiten them all, then the white sets would now be + * inconsistent. This can't happen in practice (at time of writing) + * because all PoolWhiten methods always succeed. If we ever have a + * pool class that fails to whiten a segment, then this assertion + * will be triggered. In that case, we'll have to recover here by + * blackening the segments again. */ + AVER(!haveWhiteSegs); return res; } From 0582cdfc38f2b9f4e7a342e50e9b89f25173b211 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Sat, 26 Apr 2014 11:12:45 +0100 Subject: [PATCH 16/40] Fix amsss. Copied from Perforce Change: 185813 ServerID: perforce.ravenbrook.com --- mps/code/amsss.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mps/code/amsss.c b/mps/code/amsss.c index 8538fd354e2..9128561ecf2 100644 --- a/mps/code/amsss.c +++ b/mps/code/amsss.c @@ -108,7 +108,7 @@ static mps_pool_debug_option_s freecheckOptions = { NULL, 0, (const void *)"Dead", 4 }; static void test_pool(mps_class_t pool_class, mps_arg_s args[], - size_t haveAmbiguous) + mps_bool_t haveAmbiguous) { mps_pool_t pool; mps_root_t exactRoot, ambigRoot = NULL; @@ -223,11 +223,11 @@ int main(int argc, char *argv[]) ambig ? "" : "!"); MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format); - if (chain) + if (ownChain) MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain); MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, ambig); MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, &freecheckOptions); - test_pool(debug ? mps_class_ams_debug() : mps_class_ams(), args, TRUE); + test_pool(debug ? mps_class_ams_debug() : mps_class_ams(), args, ambig); } MPS_ARGS_END(args); } From 70c0cb9a94240a12b3714daa15f579a90f9fb752 Mon Sep 17 00:00:00 2001 From: David Lovemore Date: Mon, 28 Apr 2014 13:14:04 +0100 Subject: [PATCH 17/40] Rename bool(v) to boolof(v) to fix clash with the windows header file windows.h Copied from Perforce Change: 185841 ServerID: perforce.ravenbrook.com --- mps/code/buffer.c | 6 +++--- mps/code/global.c | 2 +- mps/code/misc.h | 2 +- mps/code/poolmfs.c | 2 +- mps/code/poolmvff.c | 2 +- mps/code/seg.c | 2 +- mps/code/trace.c | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/mps/code/buffer.c b/mps/code/buffer.c index 27314924600..bbae1f3eacd 100644 --- a/mps/code/buffer.c +++ b/mps/code/buffer.c @@ -1075,7 +1075,7 @@ static Res bufferTrivInit(Buffer buffer, Pool pool, ArgList args) AVERT(Buffer, buffer); AVERT(Pool, pool); UNUSED(args); - EVENT3(BufferInit, buffer, pool, BOOL(buffer->isMutator)); + EVENT3(BufferInit, buffer, pool, BOOLOF(buffer->isMutator)); return ResOK; } @@ -1288,7 +1288,7 @@ static Res segBufInit(Buffer buffer, Pool pool, ArgList args) segbuf->rankSet = RankSetEMPTY; AVERT(SegBuf, segbuf); - EVENT3(BufferInitSeg, buffer, pool, BOOL(buffer->isMutator)); + EVENT3(BufferInitSeg, buffer, pool, BOOLOF(buffer->isMutator)); return ResOK; } @@ -1515,7 +1515,7 @@ static Res rankBufInit(Buffer buffer, Pool pool, ArgList args) BufferSetRankSet(buffer, RankSetSingle(rank)); /* There's nothing to check that the superclass doesn't, so no AVERT. */ - EVENT4(BufferInitRank, buffer, pool, BOOL(buffer->isMutator), rank); + EVENT4(BufferInitRank, buffer, pool, BOOLOF(buffer->isMutator), rank); return ResOK; } diff --git a/mps/code/global.c b/mps/code/global.c index 5f635206bd9..ce4ebbe6faa 100644 --- a/mps/code/global.c +++ b/mps/code/global.c @@ -1140,7 +1140,7 @@ void ArenaSetEmergency(Arena arena, Bool emergency) AVERT(Arena, arena); AVERT(Bool, emergency); - EVENT2(ArenaSetEmergency, arena, BOOL(emergency)); + EVENT2(ArenaSetEmergency, arena, BOOLOF(emergency)); arena->emergency = emergency; } diff --git a/mps/code/misc.h b/mps/code/misc.h index 809fd7e954a..fed416157dd 100644 --- a/mps/code/misc.h +++ b/mps/code/misc.h @@ -178,7 +178,7 @@ typedef const struct SrcIdStruct { */ #define BITFIELD(type, value, width) ((type)value & (((type)1 << (width)) - 1)) -#define BOOL(v) BITFIELD(unsigned, (v), 1) +#define BOOLOF(v) BITFIELD(unsigned, (v), 1) /* Bit Sets -- sets of integers in [0,N-1]. diff --git a/mps/code/poolmfs.c b/mps/code/poolmfs.c index 214b2b232d3..139b3f5c872 100644 --- a/mps/code/poolmfs.c +++ b/mps/code/poolmfs.c @@ -136,7 +136,7 @@ static Res MFSInit(Pool pool, ArgList args) mfs->sig = MFSSig; AVERT(MFS, mfs); - EVENT5(PoolInitMFS, pool, arena, extendBy, BOOL(extendSelf), unitSize); + EVENT5(PoolInitMFS, pool, arena, extendBy, BOOLOF(extendSelf), unitSize); return ResOK; } diff --git a/mps/code/poolmvff.c b/mps/code/poolmvff.c index fc4307d50a2..4971550c76a 100644 --- a/mps/code/poolmvff.c +++ b/mps/code/poolmvff.c @@ -610,7 +610,7 @@ static Res MVFFInit(Pool pool, ArgList args) mvff->sig = MVFFSig; AVERT(MVFF, mvff); EVENT8(PoolInitMVFF, pool, arena, extendBy, avgSize, align, - BOOL(slotHigh), BOOL(arenaHigh), BOOL(firstFit)); + BOOLOF(slotHigh), BOOLOF(arenaHigh), BOOLOF(firstFit)); return ResOK; failInit: diff --git a/mps/code/seg.c b/mps/code/seg.c index 31dd0759ff9..7f0cd4bc907 100644 --- a/mps/code/seg.c +++ b/mps/code/seg.c @@ -593,7 +593,7 @@ Res SegMerge(Seg *mergedSegReturn, Seg segLo, Seg segHi, if (ResOK != res) goto failMerge; - EVENT3(SegMerge, segLo, segHi, BOOL(withReservoirPermit)); + EVENT3(SegMerge, segLo, segHi, BOOLOF(withReservoirPermit)); /* Deallocate segHi object */ ControlFree(arena, segHi, class->size); AVERT(Seg, segLo); diff --git a/mps/code/trace.c b/mps/code/trace.c index f94d245fbf7..bd2b871fb11 100644 --- a/mps/code/trace.c +++ b/mps/code/trace.c @@ -1593,7 +1593,7 @@ static void TraceStartPoolGen(Chain chain, GenDesc desc, Bool top, Index i) Ring n, nn; RING_FOR(n, &desc->locusRing, nn) { PoolGen gen = RING_ELT(PoolGen, genRing, n); - EVENT11(TraceStartPoolGen, chain, BOOL(top), i, desc, + EVENT11(TraceStartPoolGen, chain, BOOLOF(top), i, desc, desc->capacity, desc->mortality, desc->zones, gen->pool, gen->nr, gen->totalSize, gen->newSizeAtCreate); From cc0a22847ddcdcc9e86e1224d5b213d9e5fa7dff Mon Sep 17 00:00:00 2001 From: David Lovemore Date: Mon, 28 Apr 2014 15:30:37 +0100 Subject: [PATCH 18/40] Allow branching from custom/*/main. Copied from Perforce Change: 185845 ServerID: perforce.ravenbrook.com --- mps/tool/branch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mps/tool/branch b/mps/tool/branch index 790dceb0eba..db54da83ce1 100755 --- a/mps/tool/branch +++ b/mps/tool/branch @@ -154,7 +154,7 @@ def main(argv): m = re.match(CHILD_RE, args.child) if not m: raise Error(fmt("Invalid child: {child}")) - if args.customer != m.group(3): + if not args.task and args.customer != m.group(3): raise Error(fmt("Customer mismatch between {parent} and {child}.")) args.date, args.task, _, args.version = m.groups() From e0290cfd38b0685d531acfe61740d1a76eb14183 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 30 Apr 2014 09:48:08 +0100 Subject: [PATCH 19/40] Rename bool to boolof to match change 185841. Copied from Perforce Change: 185868 ServerID: perforce.ravenbrook.com --- mps/design/type.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mps/design/type.txt b/mps/design/type.txt index 900980970dc..baee04ef3d2 100644 --- a/mps/design/type.txt +++ b/mps/design/type.txt @@ -156,7 +156,7 @@ the type of the bitfield must be ``unsigned:1``, not ``Bool:1``. (That's because the two values of the type ``Bool:1`` are ``0`` and ``-1``, which means that assigning ``TRUE`` would require a sign conversion.) To avoid warnings about loss of data from GCC with the -``-Wconversion`` option, ``misc.h`` provides the ``BOOL`` macro for +``-Wconversion`` option, ``misc.h`` provides the ``BOOLOF`` macro for coercing a value to an unsigned single-bit field. From b6e8dddfccdde40c34206441559ce179fbdba8c6 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 30 Apr 2014 15:07:00 +0100 Subject: [PATCH 20/40] Correct links to task branches. Copied from Perforce Change: 185895 ServerID: perforce.ravenbrook.com --- mps/tool/branch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mps/tool/branch b/mps/tool/branch index db54da83ce1..5a3b4d8652d 100755 --- a/mps/tool/branch +++ b/mps/tool/branch @@ -46,7 +46,7 @@ CHILD_RE = r'(?:{}|{})$'.format(TASK_BRANCH_RE, VERSION_BRANCH_RE) TASK_BRANCH_ENTRY = ''' - {date}/{task} + {date}/{task} Changes {desc_html} Active (diffs). From 3bdf7fc87843d8f0b41b7fda0cf0982c83d9e543 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 30 Apr 2014 16:29:42 +0100 Subject: [PATCH 21/40] All prottramp implementations are now the same, so there is no need for separate implementations. Copied from Perforce Change: 185901 ServerID: perforce.ravenbrook.com --- mps/code/mpm.h | 2 -- mps/code/mpsi.c | 2 +- mps/code/protan.c | 17 ++--------------- mps/code/protix.c | 23 ++--------------------- mps/code/protw3.c | 22 ++-------------------- mps/design/prot.txt | 4 ---- mps/design/protli.txt | 5 ----- mps/design/protsu.txt | 5 ----- 8 files changed, 7 insertions(+), 73 deletions(-) diff --git a/mps/code/mpm.h b/mps/code/mpm.h index 0cbad2b0f1c..499ca555113 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -922,8 +922,6 @@ extern void (ShieldFlush)(Arena arena); extern void ProtSetup(void); extern void ProtSet(Addr base, Addr limit, AccessSet mode); -extern void ProtTramp(void **resultReturn, void *(*f)(void *, size_t), - void *p, size_t s); extern void ProtSync(Arena arena); extern Bool ProtCanStepInstruction(MutatorFaultContext context); extern Res ProtStepInstruction(MutatorFaultContext context); diff --git a/mps/code/mpsi.c b/mps/code/mpsi.c index 3df0913df83..45ffff50166 100644 --- a/mps/code/mpsi.c +++ b/mps/code/mpsi.c @@ -1380,7 +1380,7 @@ void (mps_tramp)(void **r_o, AVER(FUNCHECK(f)); /* Can't check p and s as they are interpreted by the client */ - ProtTramp(r_o, f, p, s); + *r_o = (*f)(p, s); } diff --git a/mps/code/protan.c b/mps/code/protan.c index 51b2edd6df8..3709e88be59 100644 --- a/mps/code/protan.c +++ b/mps/code/protan.c @@ -1,7 +1,7 @@ /* protan.c: ANSI MEMORY PROTECTION * * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * * DESIGN @@ -65,22 +65,9 @@ void ProtSync(Arena arena) } -/* ProtTramp -- protection trampoline */ - -void ProtTramp(void **rReturn, void *(*f)(void *, size_t), - void *p, size_t s) -{ - AVER(rReturn != NULL); - AVER(FUNCHECK(f)); - /* Can't check p and s as they are interpreted by the client */ - - *(rReturn) = (*(f))(p, s); -} - - /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2002 Ravenbrook Limited . + * Copyright (C) 2001-2014 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/protix.c b/mps/code/protix.c index 31c272bc5b9..854bfc98174 100644 --- a/mps/code/protix.c +++ b/mps/code/protix.c @@ -1,7 +1,7 @@ /* protix.c: PROTECTION FOR UNIX * * $Id$ - * Copyright (c) 2001,2007 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * Somewhat generic across different Unix systems. Shared between * Darwin (OS X), FreeBSD, and Linux. @@ -114,28 +114,9 @@ void ProtSync(Arena arena) } -/* ProtTramp -- protection trampoline - * - * The protection trampoline is trivial under Unix, as there is - * nothing that needs to be done in the dynamic context of the mutator in - * order to catch faults. (Contrast this with Win32 Structured Exception - * Handling.) - */ - -void ProtTramp(void **resultReturn, void *(*f)(void *, size_t), - void *p, size_t s) -{ - AVER(resultReturn != NULL); - AVER(FUNCHECK(f)); - /* Can't check p and s as they are interpreted by the client */ - - *resultReturn = (*f)(p, s); -} - - /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2007 Ravenbrook Limited . + * Copyright (C) 2001-2014 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/protw3.c b/mps/code/protw3.c index 43e0522c074..84ef680ffb9 100644 --- a/mps/code/protw3.c +++ b/mps/code/protw3.c @@ -1,7 +1,7 @@ /* protw3.c: PROTECTION FOR WIN32 * * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. */ #include "mpm.h" @@ -131,27 +131,9 @@ void ProtSync(Arena arena) } -/* ProtTramp -- wrap a mutator thread in a Structured Exception Handler filter - * - * This was the method by which we installed an exception handler on Windows - * prior to MPS 1.111. Now we are using Vectored Exception Handlers, so this - * is deprecated and just calls through to the mutator function. - */ - -void ProtTramp(void **resultReturn, void *(*f)(void *, size_t), - void *p, size_t s) -{ - AVER(resultReturn != NULL); - AVER(FUNCHECK(f)); - /* Can't check p and s as they are interpreted by the client */ - - *resultReturn = f(p, s); -} - - /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2002 Ravenbrook Limited . + * Copyright (C) 2001-2014 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/design/prot.txt b/mps/design/prot.txt index a56e53db096..0d30017fede 100644 --- a/mps/design/prot.txt +++ b/mps/design/prot.txt @@ -47,10 +47,6 @@ forbidden. A request to forbid read accesses (that is, ``AccessREAD`` is set) may also forbid write accesses, but read accesses will not be forbidden unless ``AccessREAD`` is set. -``void ProtTramp(void **resultReturn, void *(*f)(void *, size_t), void *p, size_t s)`` - -_`.if.tramp`: [undocumented] - ``void ProtSync(Space space)`` _`.if.sync`: ``ProtSync()`` is called to ensure that the actual diff --git a/mps/design/protli.txt b/mps/design/protli.txt index a5cc1d57a15..9b0958ac191 100644 --- a/mps/design/protli.txt +++ b/mps/design/protli.txt @@ -88,11 +88,6 @@ underlying object). _`.fun.sync`: ``ProtSync()`` does nothing in this implementation as ``ProtSet()`` sets the protection without any delay. -_`.fun.tramp`: The protection trampoline, ``ProtTramp()``, is trivial -under Linux, as there is nothing that needs to be done in the dynamic -context of the mutator in order to catch faults. (Contrast this with -Win32 Structured Exception Handling.) - Threads ------- diff --git a/mps/design/protsu.txt b/mps/design/protsu.txt index 616d9134c88..1bd57e1004a 100644 --- a/mps/design/protsu.txt +++ b/mps/design/protsu.txt @@ -110,11 +110,6 @@ access that is compatible with the access of the underlying object). _`.fun.sync`: ``ProtSync()``. This does nothing in this implementation as ProtSet sets the protection without any delay. -_`.fun.tramp`: ``ProtTramp()``. The protection trampoline is trivial -under SunOS, as there is nothing that needs to be done in the dynamic -context of the mutator in order to catch faults. (Contrast this with -Win32 Structured Exception Handling.) - Document History ---------------- From 7620c6fcd1a519c3c07d0ddfb18e2cea9eb6685a Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Thu, 1 May 2014 12:18:00 +0100 Subject: [PATCH 22/40] Fix rash build on os x by adding the unused attribute to functions declared static that are not called in the rash variety. Copied from Perforce Change: 185915 ServerID: perforce.ravenbrook.com --- mps/code/arenacl.c | 2 ++ mps/code/arenavm.c | 2 ++ mps/code/buffer.c | 1 + mps/code/cbs.c | 1 + mps/code/config.h | 9 +++++++++ mps/code/freelist.c | 5 +++-- mps/code/locus.c | 1 + mps/code/mpsi.c | 1 + mps/code/poolamc.c | 5 +++++ mps/code/poolawl.c | 2 ++ mps/code/poollo.c | 3 +++ mps/code/poolmrg.c | 4 ++++ mps/code/poolmv.c | 2 ++ mps/code/poolmv2.c | 1 + mps/code/poolmvff.c | 1 + mps/code/poolsnc.c | 3 +++ mps/code/reserv.c | 1 + mps/code/sac.c | 1 + mps/code/segsmss.c | 2 ++ mps/code/walk.c | 2 ++ 20 files changed, 47 insertions(+), 2 deletions(-) diff --git a/mps/code/arenacl.c b/mps/code/arenacl.c index 3d07f529779..1a0fcf3c6e3 100644 --- a/mps/code/arenacl.c +++ b/mps/code/arenacl.c @@ -61,6 +61,7 @@ typedef struct ClientChunkStruct { /* ClientChunkCheck -- check the consistency of a client chunk */ +ATTRIBUTE_UNUSED static Bool ClientChunkCheck(ClientChunk clChunk) { Chunk chunk; @@ -77,6 +78,7 @@ static Bool ClientChunkCheck(ClientChunk clChunk) /* ClientArenaCheck -- check the consistency of a client arena */ +ATTRIBUTE_UNUSED static Bool ClientArenaCheck(ClientArena clientArena) { CHECKS(ClientArena, clientArena); diff --git a/mps/code/arenavm.c b/mps/code/arenavm.c index 81e0684c436..f878092bd01 100644 --- a/mps/code/arenavm.c +++ b/mps/code/arenavm.c @@ -93,6 +93,7 @@ static void VMCompact(Arena arena, Trace trace); /* VMChunkCheck -- check the consistency of a VM chunk */ +ATTRIBUTE_UNUSED static Bool VMChunkCheck(VMChunk vmchunk) { Chunk chunk; @@ -152,6 +153,7 @@ static Bool VMChunkCheck(VMChunk vmchunk) /* VMArenaCheck -- check the consistency of an arena structure */ +ATTRIBUTE_UNUSED static Bool VMArenaCheck(VMArena vmArena) { Arena arena; diff --git a/mps/code/buffer.c b/mps/code/buffer.c index bbae1f3eacd..a6cb2bee187 100644 --- a/mps/code/buffer.c +++ b/mps/code/buffer.c @@ -994,6 +994,7 @@ AllocPattern AllocPatternRampCollectAll(void) return &AllocPatternRampCollectAllStruct; } +ATTRIBUTE_UNUSED static Bool AllocPatternCheck(AllocPattern pattern) { CHECKL(pattern == &AllocPatternRampCollectAllStruct diff --git a/mps/code/cbs.c b/mps/code/cbs.c index 118d226a603..addebd398ad 100644 --- a/mps/code/cbs.c +++ b/mps/code/cbs.c @@ -80,6 +80,7 @@ Bool CBSCheck(CBS cbs) } +ATTRIBUTE_UNUSED static Bool CBSBlockCheck(CBSBlock block) { /* See .enter-leave.simple. */ diff --git a/mps/code/config.h b/mps/code/config.h index 0afa66c06bb..c07f646a0af 100644 --- a/mps/code/config.h +++ b/mps/code/config.h @@ -241,6 +241,15 @@ #define ATTRIBUTE_NORETURN #endif +/* Attribute for functions that may be unused in some build configurations. + * GCC: + */ +#if defined(MPS_BUILD_GC) || defined(MPS_BUILD_LL) +#define ATTRIBUTE_UNUSED __attribute__((__unused__)) +#else +#define ATTRIBUTE_UNUSED +#endif + /* EPVMDefaultSubsequentSegSIZE is a default for the alignment of * subsequent segments (non-initial at each save level) in EPVM. See diff --git a/mps/code/freelist.c b/mps/code/freelist.c index 6260451ff59..1abc3f73cc8 100644 --- a/mps/code/freelist.c +++ b/mps/code/freelist.c @@ -1,7 +1,7 @@ /* freelist.c: FREE LIST ALLOCATOR IMPLEMENTATION * * $Id$ - * Copyright (c) 2013 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2013-2014 Ravenbrook Limited. See end of file for license. * * .sources: . */ @@ -60,6 +60,7 @@ static Addr FreelistBlockLimit(Freelist fl, FreelistBlock block) /* FreelistBlockCheck -- check a block. */ +ATTRIBUTE_UNUSED static Bool FreelistBlockCheck(FreelistBlock block) { CHECKL(block != NULL); @@ -626,7 +627,7 @@ void FreelistFlushToCBS(Freelist fl, CBS cbs) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2013 Ravenbrook Limited . + * Copyright (C) 2013-2014 Ravenbrook Limited . * 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 6e6e22128b7..10eae03840f 100644 --- a/mps/code/locus.c +++ b/mps/code/locus.c @@ -80,6 +80,7 @@ void SegPrefExpress(SegPref pref, SegPrefKind kind, void *p) /* GenDescCheck -- check a GenDesc */ +ATTRIBUTE_UNUSED static Bool GenDescCheck(GenDesc gen) { CHECKS(GenDesc, gen); diff --git a/mps/code/mpsi.c b/mps/code/mpsi.c index 45ffff50166..f4e3f9e6f02 100644 --- a/mps/code/mpsi.c +++ b/mps/code/mpsi.c @@ -65,6 +65,7 @@ SRCID(mpsi, "$Id$"); * .check.enum.cast: enum comparisons have to be cast to avoid a warning * from the SunPro C compiler. See builder.sc.warn.enum. */ +ATTRIBUTE_UNUSED static Bool mpsi_check(void) { CHECKL(COMPATTYPE(mps_res_t, Res)); diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c index aeb04454efe..6ae51fc4fe6 100644 --- a/mps/code/poolamc.c +++ b/mps/code/poolamc.c @@ -96,6 +96,7 @@ typedef struct amcSegStruct { #define amcSeg2Seg(amcseg) ((Seg)(amcseg)) +ATTRIBUTE_UNUSED static Bool amcSegCheck(amcSeg amcseg) { CHECKS(amcSeg, amcseg); @@ -475,6 +476,7 @@ typedef struct AMCStruct { /* */ /* amcGenCheck -- check consistency of a generation structure */ +ATTRIBUTE_UNUSED static Bool amcGenCheck(amcGen gen) { Arena arena; @@ -524,6 +526,7 @@ typedef struct amcBufStruct { /* amcBufCheck -- check consistency of an amcBuf */ +ATTRIBUTE_UNUSED static Bool amcBufCheck(amcBuf amcbuf) { CHECKS(amcBuf, amcbuf); @@ -2445,6 +2448,8 @@ void mps_amc_apply(mps_pool_t mps_pool, * * See . */ + +ATTRIBUTE_UNUSED static Bool AMCCheck(AMC amc) { CHECKS(AMC, amc); diff --git a/mps/code/poolawl.c b/mps/code/poolawl.c index cbece0b41fe..21edaaec1cb 100644 --- a/mps/code/poolawl.c +++ b/mps/code/poolawl.c @@ -131,6 +131,7 @@ typedef struct AWLSegStruct { extern SegClass AWLSegClassGet(void); +ATTRIBUTE_UNUSED static Bool AWLSegCheck(AWLSeg awlseg) { CHECKS(AWLSeg, awlseg); @@ -1299,6 +1300,7 @@ mps_class_t mps_class_awl(void) /* AWLCheck -- check an AWL pool */ +ATTRIBUTE_UNUSED static Bool AWLCheck(AWL awl) { CHECKS(AWL, awl); diff --git a/mps/code/poollo.c b/mps/code/poollo.c index d8f23584fba..3420e22b9ab 100644 --- a/mps/code/poollo.c +++ b/mps/code/poollo.c @@ -79,6 +79,7 @@ DEFINE_SEG_CLASS(LOSegClass, class) /* LOSegCheck -- check an LO segment */ +ATTRIBUTE_UNUSED static Bool LOSegCheck(LOSeg loseg) { CHECKS(LOSeg, loseg); @@ -184,6 +185,7 @@ static void loSegFinish(Seg seg) } +ATTRIBUTE_UNUSED static Count loSegBits(LOSeg loseg) { LO lo; @@ -805,6 +807,7 @@ mps_class_t mps_class_lo(void) /* LOCheck -- check an LO pool */ +ATTRIBUTE_UNUSED static Bool LOCheck(LO lo) { CHECKS(LO, lo); diff --git a/mps/code/poolmrg.c b/mps/code/poolmrg.c index 93d9f8bd25e..ace97865f1b 100644 --- a/mps/code/poolmrg.c +++ b/mps/code/poolmrg.c @@ -125,6 +125,7 @@ typedef struct MRGStruct { /* MRGCheck -- check an MRG pool */ +ATTRIBUTE_UNUSED static Bool MRGCheck(MRG mrg) { CHECKS(MRG, mrg); @@ -178,6 +179,8 @@ extern SegClass MRGRefSegClassGet(void); * field will be NULL. This will be initialized when the reference * segment is initialized. See . */ + +ATTRIBUTE_UNUSED static Bool MRGLinkSegCheck(MRGLinkSeg linkseg) { Seg seg; @@ -193,6 +196,7 @@ static Bool MRGLinkSegCheck(MRGLinkSeg linkseg) return TRUE; } +ATTRIBUTE_UNUSED static Bool MRGRefSegCheck(MRGRefSeg refseg) { Seg seg; diff --git a/mps/code/poolmv.c b/mps/code/poolmv.c index 0ce4f28c95d..ccce962e42a 100644 --- a/mps/code/poolmv.c +++ b/mps/code/poolmv.c @@ -72,6 +72,7 @@ typedef struct MVBlockStruct { /* MVBlockCheck -- check the consistency of a block structure */ +ATTRIBUTE_UNUSED static Bool MVBlockCheck(MVBlock block) { AVER(block != NULL); @@ -130,6 +131,7 @@ typedef struct MVSpanStruct { /* MVSpanCheck -- check the consistency of a span structure */ +ATTRIBUTE_UNUSED static Bool MVSpanCheck(MVSpan span) { Addr addr, base, limit; diff --git a/mps/code/poolmv2.c b/mps/code/poolmv2.c index f6d85b1b134..b4ac6913fdf 100644 --- a/mps/code/poolmv2.c +++ b/mps/code/poolmv2.c @@ -356,6 +356,7 @@ failCBS: /* MVTCheck -- validate an MVT Pool */ +ATTRIBUTE_UNUSED static Bool MVTCheck(MVT mvt) { CHECKS(MVT, mvt); diff --git a/mps/code/poolmvff.c b/mps/code/poolmvff.c index 4971550c76a..3d569058697 100644 --- a/mps/code/poolmvff.c +++ b/mps/code/poolmvff.c @@ -791,6 +791,7 @@ size_t mps_mvff_size(mps_pool_t mps_pool) /* MVFFCheck -- check the consistency of an MVFF structure */ +ATTRIBUTE_UNUSED static Bool MVFFCheck(MVFF mvff) { CHECKS(MVFF, mvff); diff --git a/mps/code/poolsnc.c b/mps/code/poolsnc.c index e9afe98a96b..139865fc5ec 100644 --- a/mps/code/poolsnc.c +++ b/mps/code/poolsnc.c @@ -84,6 +84,7 @@ typedef struct SNCBufStruct { /* SNCBufCheck -- check consistency of an SNCBuf */ +ATTRIBUTE_UNUSED static Bool SNCBufCheck(SNCBuf sncbuf) { SegBuf segbuf; @@ -214,6 +215,7 @@ typedef struct SNCSegStruct { #define sncSegSetNext(seg, nextseg) \ ((void)(SegSNCSeg(seg)->next = SegSNCSeg(nextseg))) +ATTRIBUTE_UNUSED static Bool SNCSegCheck(SNCSeg sncseg) { CHECKS(SNCSeg, sncseg); @@ -696,6 +698,7 @@ mps_class_t mps_class_snc(void) /* SNCCheck -- Check an SNC pool */ +ATTRIBUTE_UNUSED static Bool SNCCheck(SNC snc) { CHECKS(SNC, snc); diff --git a/mps/code/reserv.c b/mps/code/reserv.c index 02b18d66d88..c7dd0507482 100644 --- a/mps/code/reserv.c +++ b/mps/code/reserv.c @@ -107,6 +107,7 @@ Bool ReservoirCheck(Reservoir reservoir) /* reservoirIsConsistent -- returns FALSE if the reservoir is corrupt */ +ATTRIBUTE_UNUSED static Bool reservoirIsConsistent(Reservoir reservoir) { Size alignment, size = 0; diff --git a/mps/code/sac.c b/mps/code/sac.c index 3caf9ab893f..c85956c8f82 100644 --- a/mps/code/sac.c +++ b/mps/code/sac.c @@ -32,6 +32,7 @@ static Bool sacFreeListBlockCheck(SACFreeListBlock fb) return TRUE; } +ATTRIBUTE_UNUSED static Bool SACCheck(SAC sac) { Index i, j; diff --git a/mps/code/segsmss.c b/mps/code/segsmss.c index 978c352e0dd..7efac5c64a5 100644 --- a/mps/code/segsmss.c +++ b/mps/code/segsmss.c @@ -59,6 +59,7 @@ typedef struct AMSTStruct *AMST; /* AMSTCheck -- the check method for an AMST */ +ATTRIBUTE_UNUSED static Bool AMSTCheck(AMST amst) { CHECKS(AMST, amst); @@ -96,6 +97,7 @@ typedef struct AMSTSegStruct { /* AMSTSegCheck -- check the AMST segment */ +ATTRIBUTE_UNUSED static Bool AMSTSegCheck(AMSTSeg amstseg) { CHECKS(AMSTSeg, amstseg); diff --git a/mps/code/walk.c b/mps/code/walk.c index 4dd0d6b9e98..544c9644498 100644 --- a/mps/code/walk.c +++ b/mps/code/walk.c @@ -26,6 +26,7 @@ typedef struct FormattedObjectsStepClosureStruct { } FormattedObjectsStepClosureStruct; +ATTRIBUTE_UNUSED static Bool FormattedObjectsStepClosureCheck(FormattedObjectsStepClosure c) { CHECKS(FormattedObjectsStepClosure, c); @@ -164,6 +165,7 @@ typedef struct rootsStepClosureStruct { /* rootsStepClosureCheck -- check a rootsStepClosure */ +ATTRIBUTE_UNUSED static Bool rootsStepClosureCheck(rootsStepClosure rsc) { CHECKS(rootsStepClosure, rsc); From f82973bf08dedb279415e315bdb152619e0da6ef Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Thu, 1 May 2014 12:21:17 +0100 Subject: [PATCH 23/40] Fix problems with the xcode project file (introduced in bad merges): * airtest got built as mv2test in the RASH config * airtest and nailboardtest got build with profiling in Debug config * airtest still had bogus WE config Copied from Perforce Change: 185916 ServerID: perforce.ravenbrook.com --- mps/code/mps.xcodeproj/project.pbxproj | 76 +++++++++----------------- 1 file changed, 25 insertions(+), 51 deletions(-) diff --git a/mps/code/mps.xcodeproj/project.pbxproj b/mps/code/mps.xcodeproj/project.pbxproj index 88f110bab01..29e47139571 100644 --- a/mps/code/mps.xcodeproj/project.pbxproj +++ b/mps/code/mps.xcodeproj/project.pbxproj @@ -2644,7 +2644,7 @@ 22FACEE118880983000FDBC1 /* PBXTargetDependency */, ); name = airtest; - productName = mv2test; + productName = airtest; productReference = 22FACEED18880983000FDBC1 /* airtest */; productType = "com.apple.product-type.tool"; }; @@ -4322,42 +4322,42 @@ 2231BB5618CA97D8002D6322 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - PRODUCT_NAME = locbwcss; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 2231BB5718CA97D8002D6322 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - PRODUCT_NAME = locbwcss; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 2231BB5818CA97D8002D6322 /* RASH */ = { isa = XCBuildConfiguration; buildSettings = { - PRODUCT_NAME = locbwcss; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = RASH; }; 2231BB6418CA97DC002D6322 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - PRODUCT_NAME = locusss; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 2231BB6518CA97DC002D6322 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - PRODUCT_NAME = locusss; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 2231BB6618CA97DC002D6322 /* RASH */ = { isa = XCBuildConfiguration; buildSettings = { - PRODUCT_NAME = locusss; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = RASH; }; @@ -4421,7 +4421,7 @@ isa = XCBuildConfiguration; buildSettings = { GCC_TREAT_WARNINGS_AS_ERRORS = NO; - PRODUCT_NAME = "scheme-advanced"; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; @@ -4429,7 +4429,7 @@ isa = XCBuildConfiguration; buildSettings = { GCC_TREAT_WARNINGS_AS_ERRORS = NO; - PRODUCT_NAME = "scheme-advanced"; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; @@ -4437,41 +4437,35 @@ isa = XCBuildConfiguration; buildSettings = { GCC_TREAT_WARNINGS_AS_ERRORS = NO; - PRODUCT_NAME = "scheme-advanced"; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = RASH; }; 22C2ACA118BE3FEC006B3677 /* RASH */ = { isa = XCBuildConfiguration; buildSettings = { - PRODUCT_NAME = mv2test; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = RASH; }; 22C2ACAC18BE400A006B3677 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - GCC_GENERATE_TEST_COVERAGE_FILES = YES; - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; - PRODUCT_NAME = nailboardtest; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 22C2ACAD18BE400A006B3677 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - GCC_GENERATE_TEST_COVERAGE_FILES = NO; - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; - PRODUCT_NAME = nailboardtest; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 22C2ACAE18BE400A006B3677 /* RASH */ = { isa = XCBuildConfiguration; buildSettings = { - GCC_GENERATE_TEST_COVERAGE_FILES = NO; - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; - PRODUCT_NAME = nailboardtest; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = RASH; }; @@ -4492,21 +4486,21 @@ 22F846BA18F437B900982BA7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - PRODUCT_NAME = lockut; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 22F846BB18F437B900982BA7 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - PRODUCT_NAME = lockut; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; 22F846BC18F437B900982BA7 /* RASH */ = { isa = XCBuildConfiguration; buildSettings = { - PRODUCT_NAME = lockut; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = RASH; }; @@ -4527,30 +4521,17 @@ 22FACEEA18880983000FDBC1 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - GCC_GENERATE_TEST_COVERAGE_FILES = YES; - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; - PRODUCT_NAME = airtest; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 22FACEEB18880983000FDBC1 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - GCC_GENERATE_TEST_COVERAGE_FILES = NO; - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; - PRODUCT_NAME = airtest; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; - 22FACEEC18880983000FDBC1 /* WE */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_GENERATE_TEST_COVERAGE_FILES = NO; - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = NO; - PRODUCT_NAME = airtest; - }; - name = WE; - }; 2D07B9751636FC9900DB751B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -4626,7 +4607,6 @@ 3104AFF3156D37A0000A585A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - COMBINE_HIDPI_IMAGES = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -4634,7 +4614,6 @@ 3104AFF4156D37A0000A585A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - COMBINE_HIDPI_IMAGES = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -4923,7 +4902,7 @@ isa = XCBuildConfiguration; buildSettings = { GCC_TREAT_WARNINGS_AS_ERRORS = NO; - PRODUCT_NAME = djbench; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; @@ -4931,7 +4910,7 @@ isa = XCBuildConfiguration; buildSettings = { GCC_TREAT_WARNINGS_AS_ERRORS = NO; - PRODUCT_NAME = djbench; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; @@ -4991,7 +4970,6 @@ 318DA8D51892C0D00089718C /* RASH */ = { isa = XCBuildConfiguration; buildSettings = { - COMBINE_HIDPI_IMAGES = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = RASH; @@ -5000,7 +4978,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - COMBINE_HIDPI_IMAGES = YES; EXECUTABLE_PREFIX = lib; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -5285,7 +5262,7 @@ isa = XCBuildConfiguration; buildSettings = { GCC_TREAT_WARNINGS_AS_ERRORS = NO; - PRODUCT_NAME = djbench; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = RASH; }; @@ -5484,7 +5461,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - COMBINE_HIDPI_IMAGES = YES; EXECUTABLE_PREFIX = lib; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -5494,7 +5470,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - COMBINE_HIDPI_IMAGES = YES; EXECUTABLE_PREFIX = lib; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -5534,7 +5509,7 @@ isa = XCBuildConfiguration; buildSettings = { GCC_TREAT_WARNINGS_AS_ERRORS = NO; - PRODUCT_NAME = gcbench; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; @@ -5542,7 +5517,7 @@ isa = XCBuildConfiguration; buildSettings = { GCC_TREAT_WARNINGS_AS_ERRORS = NO; - PRODUCT_NAME = gcbench; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; @@ -5550,7 +5525,7 @@ isa = XCBuildConfiguration; buildSettings = { GCC_TREAT_WARNINGS_AS_ERRORS = NO; - PRODUCT_NAME = gcbench; + PRODUCT_NAME = "$(TARGET_NAME)"; }; name = RASH; }; @@ -5672,7 +5647,6 @@ buildConfigurations = ( 22FACEEA18880983000FDBC1 /* Debug */, 22FACEEB18880983000FDBC1 /* Release */, - 22FACEEC18880983000FDBC1 /* WE */, 22C2ACA118BE3FEC006B3677 /* RASH */, ); defaultConfigurationIsVisible = 0; From f8b0f015609e21596a221c8a640f8a370e6ce808 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Thu, 1 May 2014 15:51:26 +0100 Subject: [PATCH 24/40] Reorganize the mps branch index so that it contains a roughly prioritized list of branches that are ready for review. Copied from Perforce Change: 185920 ServerID: perforce.ravenbrook.com --- mps/tool/branch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mps/tool/branch b/mps/tool/branch index 5a3b4d8652d..bb54f0d4527 100755 --- a/mps/tool/branch +++ b/mps/tool/branch @@ -49,7 +49,7 @@ TASK_BRANCH_ENTRY = ''' {date}/{task} Changes {desc_html} - Active (diffs). + Diffs ''' From 58400fd7680ec12b4958cb1771eea2e6f7eae58e Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Thu, 1 May 2014 17:38:14 +0100 Subject: [PATCH 25/40] Add refsetsub assertion to the list of common assertions and their causes. Copied from Perforce Change: 185924 ServerID: perforce.ravenbrook.com --- mps/manual/source/topic/error.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mps/manual/source/topic/error.rst b/mps/manual/source/topic/error.rst index 6b2e9452fc2..fb55c9785f1 100644 --- a/mps/manual/source/topic/error.rst +++ b/mps/manual/source/topic/error.rst @@ -293,6 +293,16 @@ this documentation. condition? +``trace.c: RefSetSub(ScanStateUnfixedSummary(ss), SegSummary(seg))`` + + The client program's :term:`scan method` failed to update a + reference to an object that moved. See + :ref:`topic-scanning-protocol`, which says, "If :c:func:`MPS_FIX2` + returns :c:macro:`MPS_RES_OK`, it may have updated the reference. + If necessary, make sure that the updated reference is stored back + to the region being scanned." + + .. index:: single: error handling; varieties single: variety From ef779449b4ff06fa1389a77eb9779e844f7b081f Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Thu, 1 May 2014 18:02:53 +0100 Subject: [PATCH 26/40] Default value for mps_key_ams_support_ambiguous is now the safer value true. Copied from Perforce Change: 185927 ServerID: perforce.ravenbrook.com --- mps/code/config.h | 2 +- mps/manual/source/pool/ams.rst | 12 ++++++------ mps/manual/source/release.rst | 5 +++++ 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/mps/code/config.h b/mps/code/config.h index c07f646a0af..1dfd7858f86 100644 --- a/mps/code/config.h +++ b/mps/code/config.h @@ -290,7 +290,7 @@ /* Pool AMS Configuration -- see */ -#define AMS_SUPPORT_AMBIGUOUS_DEFAULT FALSE +#define AMS_SUPPORT_AMBIGUOUS_DEFAULT TRUE #define AMS_GEN_DEFAULT 0 diff --git a/mps/manual/source/pool/ams.rst b/mps/manual/source/pool/ams.rst index cb7966661a3..ae1d43f8bed 100644 --- a/mps/manual/source/pool/ams.rst +++ b/mps/manual/source/pool/ams.rst @@ -55,10 +55,11 @@ AMS properties never promoted out of the generation in which they are allocated. * Blocks may contain :term:`exact references` to blocks in the same or - other pools, or :term:`ambiguous references` (if the + other pools, or :term:`ambiguous references` (unless the :c:macro:`MPS_KEY_AMS_SUPPORT_AMBIGUOUS` keyword argument is set to - true when creating the pool). Blocks may not contain :term:`weak - references (1)`, and may not use :term:`remote references`. + ``FALSE`` when creating the pool). Blocks may not contain + :term:`weak references (1)`, and may not use :term:`remote + references`. * Allocations may be variable in size. @@ -126,14 +127,13 @@ AMS interface blocks remain in this generation and are not promoted. * :c:macro:`MPS_KEY_AMS_SUPPORT_AMBIGUOUS` (type - :c:type:`mps_bool_t`, default false) specifies whether references - may be ambiguous. + :c:type:`mps_bool_t`, default ``TRUE``) specifies whether + references to blocks in the pool may be ambiguous. For example:: MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_FORMAT, fmt); - MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, 1); res = mps_pool_create_k(&pool, arena, mps_class_ams(), args); } MPS_ARGS_END(args); diff --git a/mps/manual/source/release.rst b/mps/manual/source/release.rst index 18cc8ed72e9..f9fc0054de5 100644 --- a/mps/manual/source/release.rst +++ b/mps/manual/source/release.rst @@ -35,6 +35,11 @@ Interface changes :c:func:`mps_arena_create_k` when creating a virtual memory arena. See :c:func:`mps_arena_class_vm`. +#. The keyword argument :c:macro:`MPS_KEY_AMS_SUPPORT_AMBIGUOUS` now + defaults to ``TRUE`` in order to better support the general case: + the value ``FALSE`` is appropriate only when you know that all + references are exact. See :ref:`pool-ams`. + Other changes ............. From a7e224e6633d59e34bb35e24e704fda9b722a2c0 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Thu, 1 May 2014 18:46:15 +0100 Subject: [PATCH 27/40] Update manual to describe new condemn logic resulting from fix for job003771. Copied from Perforce Change: 185929 ServerID: perforce.ravenbrook.com --- mps/manual/source/release.rst | 21 +++++++++++++++++++++ mps/manual/source/topic/collection.rst | 25 ++++++++++++------------- mps/manual/source/topic/pattern.rst | 16 ++++++++++++++-- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/mps/manual/source/release.rst b/mps/manual/source/release.rst index f9fc0054de5..0ac53f9020a 100644 --- a/mps/manual/source/release.rst +++ b/mps/manual/source/release.rst @@ -26,6 +26,20 @@ New features :c:macro:`MPS_KEY_INTERIOR` keyword argument to ``FALSE`` when calling :c:func:`mps_pool_create_k`. +#. The logic for deciding which generations should be collected has + changed. Now, a chain may be scheduled for collection if the new + size of *any* of its generations exceeds its capacity, and when a + chain is collected, all generations are collected up to, and + including, the highest generation whose new size exceeds its + capacity. This ensures that all generations are collected reliably + on chains where there is no allocation into the nursery generation. + See :ref:`topic-collection-schedule`. + + (Previously, only the nursery generation in each chain + was considered, and a chain was collected up to, but not including, + the lowest generation whose new size was within its capacity.) + + Interface changes ................. @@ -69,6 +83,13 @@ Other changes .. _job003756: https://www.ravenbrook.com/project/mps/issue/job003756/ +#. :ref:`pool-ams` pools get reliably collected, even in the case + where an AMS pool is the only pool on its generation chain and is + allocating into some generation other than the nursery. See + job003771_. + + .. _job003771: https://www.ravenbrook.com/project/mps/issue/job003771/ + .. _release-notes-1.113: diff --git a/mps/manual/source/topic/collection.rst b/mps/manual/source/topic/collection.rst index de5629e52d6..adf7c058e9e 100644 --- a/mps/manual/source/topic/collection.rst +++ b/mps/manual/source/topic/collection.rst @@ -57,9 +57,9 @@ Create a generation chain by preparing an array of kilobytes) and *predicted mortality* (between 0 and 1) of each generation, and passing them to :c:func:`mps_chain_create`. -When the size of the generation exceeds the capacity, the MPS will be -prepared to start collecting the generation. See -:ref:`topic-collection-schedule` below. +When the *new size* of a generation exceeds its capacity, the MPS will +be prepared to start collecting the chain to which the generation +belongs. See :ref:`topic-collection-schedule` below. For example:: @@ -163,20 +163,19 @@ size* of each generation (other than the topmost) is the same as its total size, but in pools like :ref:`pool-ams` where survivors do not get promoted, the two sizes can be different. -The first generation in a pool's chain is the :term:`nursery space`. -When the nursery's *new size* exceeds its capacity, the MPS considers -collecting the pool. (How long it takes to get around to it depends on -which other collections on other pools are in progress.) +When a generation's *new size* exceeds its capacity, the MPS considers +collecting the chain to which the generation belongs. (How long it +takes to get around to it depends on which other collections are in +progress.) .. note:: - You can affect the decision as to when to collect the nursery - space by using the :ref:`ramp allocation pattern - `. + You can affect the decision as to when to collect the chain by + using the :ref:`ramp allocation pattern `. -If the MPS decides to collect a pool at all, all generations are -collected below the first generation whose *new size* is less than its -capacity. +If the MPS decides to collect a chain, all generations are collected +up to, and including, the highest generation whose *new size* exceeds +its capacity. In pools such as :ref:`pool-amc`, blocks in generation *g* that survive collection get promoted to generation *g*\+1. If the last diff --git a/mps/manual/source/topic/pattern.rst b/mps/manual/source/topic/pattern.rst index 4d798c00b78..f460e019fba 100644 --- a/mps/manual/source/topic/pattern.rst +++ b/mps/manual/source/topic/pattern.rst @@ -110,10 +110,22 @@ cutoff and decline in the live size. This pattern is useful if you are building a structure that involves temporarily allocating much more memory than will fit into your -:term:`nursery generation`. The ramp allocation pattern causes the -collection of the nursery generation to be deferred until the ramp +:term:`nursery generation`. By applying the ramp allocation pattern, +the collection of that generation can be deferred until the ramp allocation is over. +In detail: if the ramp allocation pattern is applied to an +:term:`allocation point`, then allocation on that AP is ignored by the +MPS when it is deciding whether to schedule a collection of the chain +containing the generation into which the AP is allocating. See :ref:`topic-collection-schedule`. + +.. note:: + + This does not prevent the generation from being collected + altogether: there may be other APs allocating into the generation, + or the MPS may have to collect the generation in order to avoid + running out of memory. + .. note:: Ramp allocation is only supported by :ref:`pool-amc`. From e50f28afeba33ec206d4b60dc723c435000eee77 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Fri, 2 May 2014 11:34:38 +0100 Subject: [PATCH 28/40] The mps_args_add_field and mps_args_done now check that the number of arguments is in bounds. Copied from Perforce Change: 185938 ServerID: perforce.ravenbrook.com --- mps/code/airtest.c | 1 - mps/code/fmtscheme.c | 1 - mps/code/mps.h | 19 ++++++++++--------- mps/code/mpsi.c | 18 ++++++++++++++++++ 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/mps/code/airtest.c b/mps/code/airtest.c index 56e1bd8c129..bf840957414 100644 --- a/mps/code/airtest.c +++ b/mps/code/airtest.c @@ -112,7 +112,6 @@ static void test_main(void *marker, int interior, int stack) MPS_ARGS_ADD(args, MPS_KEY_CHAIN, obj_chain); MPS_ARGS_ADD(args, MPS_KEY_FORMAT, obj_fmt); MPS_ARGS_ADD(args, MPS_KEY_INTERIOR, interior); - MPS_ARGS_DONE(args); die(mps_pool_create_k(&obj_pool, scheme_arena, mps_class_amc(), args), "mps_pool_create_k"); } MPS_ARGS_END(args); diff --git a/mps/code/fmtscheme.c b/mps/code/fmtscheme.c index 11900130a71..f43990ec619 100644 --- a/mps/code/fmtscheme.c +++ b/mps/code/fmtscheme.c @@ -452,7 +452,6 @@ void scheme_fmt(mps_fmt_t *fmt) MPS_ARGS_ADD(args, MPS_KEY_FMT_FWD, obj_fwd); MPS_ARGS_ADD(args, MPS_KEY_FMT_ISFWD, obj_isfwd); MPS_ARGS_ADD(args, MPS_KEY_FMT_PAD, obj_pad); - MPS_ARGS_DONE(args); res = mps_fmt_create_k(fmt, scheme_arena, args); } MPS_ARGS_END(args); if (res != MPS_RES_OK) error("Couldn't create obj format"); diff --git a/mps/code/mps.h b/mps/code/mps.h index b948a5f8d7d..18767cec60f 100644 --- a/mps/code/mps.h +++ b/mps/code/mps.h @@ -1,7 +1,7 @@ /* mps.h: RAVENBROOK MEMORY POOL SYSTEM C INTERFACE * * $Id$ - * Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * Portions copyright (c) 2002 Global Graphics Software. * * THIS HEADER IS NOT DOCUMENTATION. @@ -227,20 +227,22 @@ extern const struct mps_key_s _mps_key_fmt_class; /* Maximum length of a keyword argument list. */ #define MPS_ARGS_MAX 32 +extern void _mps_args_set_key(mps_arg_s args[MPS_ARGS_MAX], unsigned i, + mps_key_t key); + #define MPS_ARGS_BEGIN(_var) \ MPS_BEGIN \ mps_arg_s _var[MPS_ARGS_MAX]; \ unsigned _var##_i = 0; \ - _var[_var##_i].key = MPS_KEY_ARGS_END; \ + _mps_args_set_key(_var, _var##_i, MPS_KEY_ARGS_END); \ MPS_BEGIN #define MPS_ARGS_ADD_FIELD(_var, _key, _field, _val) \ MPS_BEGIN \ - /* TODO: AVER(_var##_i + 1 < MPS_ARGS_MAX); */ \ - _var[_var##_i].key = (_key); \ + _mps_args_set_key(_var, _var##_i, _key); \ _var[_var##_i].val._field = (_val); \ ++_var##_i; \ - _var[_var##_i].key = MPS_KEY_ARGS_END; \ + _mps_args_set_key(_var, _var##_i, MPS_KEY_ARGS_END); \ MPS_END #define MPS_ARGS_ADD(_var, _key, _val) \ @@ -248,9 +250,8 @@ extern const struct mps_key_s _mps_key_fmt_class; #define MPS_ARGS_DONE(_var) \ MPS_BEGIN \ - /* TODO: AVER(_var##_i < MPS_ARGS_MAX); */ \ - _var[_var##_i].key = MPS_KEY_ARGS_END; \ - /* TODO: _var##_i = MPS_ARGS_MAX; */ \ + _mps_args_set_key(_var, _var##_i, MPS_KEY_ARGS_END); \ + _var##_i = MPS_ARGS_MAX; \ MPS_END #define MPS_ARGS_END(_var) \ @@ -812,7 +813,7 @@ extern mps_res_t _mps_fix2(mps_ss_t, mps_addr_t *); /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2013 Ravenbrook Limited . + * Copyright (C) 2001-2014 Ravenbrook Limited . * 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 f4e3f9e6f02..0573a6d4256 100644 --- a/mps/code/mpsi.c +++ b/mps/code/mpsi.c @@ -1929,6 +1929,24 @@ void mps_chain_destroy(mps_chain_t chain) } +/* _mps_args_set_key -- set the key for a keyword argument + * + * This sets the key for the i'th keyword argument in the array args, + * with bounds checking on i. It is used by the MPS_ARGS_BEGIN, + * MPS_ARGS_ADD, and MPS_ARGS_DONE macros in mps.h. + * + * We implement this in a function here, rather than in a macro in + * mps.h, so that we can use AVER to do the bounds checking. + */ + +void _mps_args_set_key(mps_arg_s args[MPS_ARGS_MAX], unsigned i, + mps_key_t key) +{ + AVER(i < MPS_ARGS_MAX); + args[i].key = key; +} + + /* C. COPYRIGHT AND LICENSE * * Copyright (C) 2001-2014 Ravenbrook Limited . From b02491dabc26f1e7388089da6ad7cde291d200b1 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Fri, 2 May 2014 11:43:52 +0100 Subject: [PATCH 29/40] Document the assertion that you get when you failed to destroy an object. Copied from Perforce Change: 185939 ServerID: perforce.ravenbrook.com --- mps/manual/source/topic/error.rst | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/mps/manual/source/topic/error.rst b/mps/manual/source/topic/error.rst index fb55c9785f1..29fefc6e1b6 100644 --- a/mps/manual/source/topic/error.rst +++ b/mps/manual/source/topic/error.rst @@ -232,13 +232,6 @@ assertion that is listed here but for which you discovered a different cause), please :ref:`let us know ` so that we can improve this documentation. -``sa.c: BTIsResRange(sa->mapped, 0, sa->length)`` - - The client program called :c:func:`mps_arena_destroy` without - having destroyed all pools in that arena first. (The assertion is - from the virtual memory manager which is checking that all pages - have been unmapped.) - ``dbgpool.c: fencepost check on free`` @@ -293,6 +286,15 @@ this documentation. condition? +``ring.c: ring->next == ring`` + + The client program destroyed an object without having destroyed + all the objects that it owns first. For example, it destroyed an + arena without first destroying all pools in that arena, or it + destroyed a pool without first destroying all allocation points + created on that pool. + + ``trace.c: RefSetSub(ScanStateUnfixedSummary(ss), SegSummary(seg))`` The client program's :term:`scan method` failed to update a From 2200388b1005c5d423deb7b111787a37691bccd5 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Sat, 3 May 2014 10:43:12 +0100 Subject: [PATCH 30/40] Add note explaining that objects are not reclaimed immediately after discarding the finalization message, so you need to ensure they remain valid. Copied from Perforce Change: 185946 ServerID: perforce.ravenbrook.com --- mps/manual/source/topic/finalization.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mps/manual/source/topic/finalization.rst b/mps/manual/source/topic/finalization.rst index 32f618f19e7..2542f2ba1c7 100644 --- a/mps/manual/source/topic/finalization.rst +++ b/mps/manual/source/topic/finalization.rst @@ -85,6 +85,15 @@ calling :c:func:`mps_message_discard`. will cause it to be finalized again should all strong references disappear again. +.. note:: + + Calling :c:func:`mps_message_discard` does not reclaim the space + occupied by the finalized block (that happens at the next + collection, if the block is found to be dead at that point), and + so the block must remain validly formatted (:term:`scannable `, :term:`skippable `, and so on). You might + choose to replace it with a :term:`padding object`. + See :ref:`topic-message` for details of the message mechanism. From 9a10426569aca8a468729d4cd4a2f9caf610782f Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Sat, 3 May 2014 10:45:50 +0100 Subject: [PATCH 31/40] Fix typo. Copied from Perforce Change: 185947 ServerID: perforce.ravenbrook.com --- mps/manual/source/topic/finalization.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mps/manual/source/topic/finalization.rst b/mps/manual/source/topic/finalization.rst index 2542f2ba1c7..745feefed16 100644 --- a/mps/manual/source/topic/finalization.rst +++ b/mps/manual/source/topic/finalization.rst @@ -91,8 +91,8 @@ calling :c:func:`mps_message_discard`. occupied by the finalized block (that happens at the next collection, if the block is found to be dead at that point), and so the block must remain validly formatted (:term:`scannable `, :term:`skippable `, and so on). You might - choose to replace it with a :term:`padding object`. + method>`, :term:`skippable `, and so on). It might + make sense to replace it with a :term:`padding object`. See :ref:`topic-message` for details of the message mechanism. @@ -132,12 +132,12 @@ Cautions finalization. The MPS does not finalize a block until it determines that the block is finalizable, which may require a full garbage collection in the worst case, and such a collection may - not :ref:`scheduled ` for some time. Or - the block may never become finalizable because it is incorrectly - determined to be reachable due to an :term:`ambiguous reference` - pointing to it. Or the block may never become finalizable because - it remains reachable through a reference, even if that reference - might never be used. + not be :ref:`scheduled ` for some time. + Or the block may never become finalizable because it is + incorrectly determined to be reachable due to an :term:`ambiguous + reference` pointing to it. Or the block may never become + finalizable because it remains reachable through a reference, even + if that reference might never be used. #. Even when blocks are finalized in a reasonably timely fashion, the client needs to process the finalization messages in time to avoid From 085b15deb2a5d861030a2a201842de33f6239a01 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Sun, 4 May 2014 20:39:31 +0100 Subject: [PATCH 32/40] Scheme constructors now take an allocation point. Copied from Perforce Change: 185959 ServerID: perforce.ravenbrook.com --- mps/code/airtest.c | 6 ++-- mps/code/fmtscheme.c | 68 ++++++++++++++++++++++---------------------- mps/code/fmtscheme.h | 26 +++++++++-------- 3 files changed, 51 insertions(+), 49 deletions(-) diff --git a/mps/code/airtest.c b/mps/code/airtest.c index bf840957414..a4537a390db 100644 --- a/mps/code/airtest.c +++ b/mps/code/airtest.c @@ -50,14 +50,14 @@ static void test_air(int interior, int stack) } mps_message_type_enable(scheme_arena, mps_message_type_finalization()); for (j = 0; j < OBJ_COUNT; ++j) { - obj_t n = scheme_make_integer((long)j); - obj_t obj = scheme_make_vector(OBJ_LEN, n); + obj_t n = scheme_make_integer(obj_ap, (long)j); + obj_t obj = scheme_make_vector(obj_ap, OBJ_LEN, n); mps_addr_t ref = obj; mps_finalize(scheme_arena, &ref); s[j] = obj->vector.vector; } for (i = 1; i < OBJ_LEN; ++i) { - obj_t n = scheme_make_integer((long)i); + obj_t n = scheme_make_integer(obj_ap, (long)i); mps_message_t msg; for (j = 0; j + 1 < OBJ_COUNT; ++j) { *++s[j] = n; diff --git a/mps/code/fmtscheme.c b/mps/code/fmtscheme.c index f43990ec619..24fa06db871 100644 --- a/mps/code/fmtscheme.c +++ b/mps/code/fmtscheme.c @@ -44,86 +44,86 @@ obj_t scheme_make_bool(int condition) return condition ? obj_true : obj_false; } -obj_t scheme_make_pair(obj_t car, obj_t cdr) +obj_t scheme_make_pair(mps_ap_t ap, obj_t car, obj_t cdr) { obj_t obj; mps_addr_t addr; size_t size = ALIGN_OBJ(sizeof(pair_s)); do { - mps_res_t res = mps_reserve(&addr, obj_ap, size); + mps_res_t res = mps_reserve(&addr, ap, size); if (res != MPS_RES_OK) error("out of memory in make_pair"); obj = addr; obj->pair.type = TYPE_PAIR; CAR(obj) = car; CDR(obj) = cdr; - } while(!mps_commit(obj_ap, addr, size)); + } while(!mps_commit(ap, addr, size)); return obj; } -obj_t scheme_make_integer(long integer) +obj_t scheme_make_integer(mps_ap_t ap, long integer) { obj_t obj; mps_addr_t addr; size_t size = ALIGN_OBJ(sizeof(integer_s)); do { - mps_res_t res = mps_reserve(&addr, obj_ap, size); + mps_res_t res = mps_reserve(&addr, ap, size); if (res != MPS_RES_OK) error("out of memory in make_integer"); obj = addr; obj->integer.type = TYPE_INTEGER; obj->integer.integer = integer; - } while(!mps_commit(obj_ap, addr, size)); + } while(!mps_commit(ap, addr, size)); return obj; } -obj_t scheme_make_symbol(size_t length, char string[]) +obj_t scheme_make_symbol(mps_ap_t ap, size_t length, char string[]) { obj_t obj; mps_addr_t addr; size_t size = ALIGN_OBJ(offsetof(symbol_s, string) + length+1); do { - mps_res_t res = mps_reserve(&addr, obj_ap, size); + mps_res_t res = mps_reserve(&addr, ap, size); if (res != MPS_RES_OK) error("out of memory in make_symbol"); obj = addr; obj->symbol.type = TYPE_SYMBOL; obj->symbol.length = length; memcpy(obj->symbol.string, string, length+1); - } while(!mps_commit(obj_ap, addr, size)); + } while(!mps_commit(ap, addr, size)); return obj; } -obj_t scheme_make_string(size_t length, char string[]) +obj_t scheme_make_string(mps_ap_t ap, size_t length, char string[]) { obj_t obj; mps_addr_t addr; size_t size = ALIGN_OBJ(offsetof(string_s, string) + length+1); do { - mps_res_t res = mps_reserve(&addr, obj_ap, size); + mps_res_t res = mps_reserve(&addr, ap, size); if (res != MPS_RES_OK) error("out of memory in make_string"); obj = addr; obj->string.type = TYPE_STRING; obj->string.length = length; if (string) memcpy(obj->string.string, string, length+1); else memset(obj->string.string, 0, length+1); - } while(!mps_commit(obj_ap, addr, size)); + } while(!mps_commit(ap, addr, size)); return obj; } -obj_t scheme_make_special(char *string) +obj_t scheme_make_special(mps_ap_t ap, char *string) { obj_t obj; mps_addr_t addr; size_t size = ALIGN_OBJ(sizeof(special_s)); do { - mps_res_t res = mps_reserve(&addr, obj_ap, size); + mps_res_t res = mps_reserve(&addr, ap, size); if (res != MPS_RES_OK) error("out of memory in make_special"); obj = addr; obj->special.type = TYPE_SPECIAL; obj->special.name = string; - } while(!mps_commit(obj_ap, addr, size)); + } while(!mps_commit(ap, addr, size)); return obj; } -obj_t scheme_make_operator(char *name, +obj_t scheme_make_operator(mps_ap_t ap, char *name, entry_t entry, obj_t arguments, obj_t body, obj_t env, obj_t op_env) { @@ -131,7 +131,7 @@ obj_t scheme_make_operator(char *name, mps_addr_t addr; size_t size = ALIGN_OBJ(sizeof(operator_s)); do { - mps_res_t res = mps_reserve(&addr, obj_ap, size); + mps_res_t res = mps_reserve(&addr, ap, size); if (res != MPS_RES_OK) error("out of memory in make_operator"); obj = addr; obj->operator.type = TYPE_OPERATOR; @@ -141,70 +141,70 @@ obj_t scheme_make_operator(char *name, obj->operator.body = body; obj->operator.env = env; obj->operator.op_env = op_env; - } while(!mps_commit(obj_ap, addr, size)); + } while(!mps_commit(ap, addr, size)); return obj; } -obj_t scheme_make_port(obj_t name, FILE *stream) +obj_t scheme_make_port(mps_ap_t ap, obj_t name, FILE *stream) { mps_addr_t port_ref; obj_t obj; mps_addr_t addr; size_t size = ALIGN_OBJ(sizeof(port_s)); do { - mps_res_t res = mps_reserve(&addr, obj_ap, size); + mps_res_t res = mps_reserve(&addr, ap, size); if (res != MPS_RES_OK) error("out of memory in make_port"); obj = addr; obj->port.type = TYPE_PORT; obj->port.name = name; obj->port.stream = stream; - } while(!mps_commit(obj_ap, addr, size)); + } while(!mps_commit(ap, addr, size)); port_ref = obj; mps_finalize(scheme_arena, &port_ref); return obj; } -obj_t scheme_make_character(char c) +obj_t scheme_make_character(mps_ap_t ap, char c) { obj_t obj; mps_addr_t addr; size_t size = ALIGN_OBJ(sizeof(character_s)); do { - mps_res_t res = mps_reserve(&addr, obj_ap, size); + mps_res_t res = mps_reserve(&addr, ap, size); if (res != MPS_RES_OK) error("out of memory in make_character"); obj = addr; obj->character.type = TYPE_CHARACTER; obj->character.c = c; - } while(!mps_commit(obj_ap, addr, size)); + } while(!mps_commit(ap, addr, size)); return obj; } -obj_t scheme_make_vector(size_t length, obj_t fill) +obj_t scheme_make_vector(mps_ap_t ap, size_t length, obj_t fill) { obj_t obj; mps_addr_t addr; size_t size = ALIGN_OBJ(offsetof(vector_s, vector) + length * sizeof(obj_t)); do { size_t i; - mps_res_t res = mps_reserve(&addr, obj_ap, size); + mps_res_t res = mps_reserve(&addr, ap, size); if (res != MPS_RES_OK) error("out of memory in make_vector"); obj = addr; obj->vector.type = TYPE_VECTOR; obj->vector.length = length; for(i = 0; i < length; ++i) obj->vector.vector[i] = fill; - } while(!mps_commit(obj_ap, addr, size)); + } while(!mps_commit(ap, addr, size)); return obj; } -obj_t scheme_make_buckets(size_t length) +obj_t scheme_make_buckets(mps_ap_t ap, size_t length) { obj_t obj; mps_addr_t addr; size_t size = ALIGN_OBJ(offsetof(buckets_s, bucket) + length * sizeof(obj->buckets.bucket[0])); do { size_t i; - mps_res_t res = mps_reserve(&addr, obj_ap, size); + mps_res_t res = mps_reserve(&addr, ap, size); if (res != MPS_RES_OK) error("out of memory in make_buckets"); obj = addr; obj->buckets.type = TYPE_BUCKETS; @@ -215,27 +215,27 @@ obj_t scheme_make_buckets(size_t length) obj->buckets.bucket[i].key = NULL; obj->buckets.bucket[i].value = NULL; } - } while(!mps_commit(obj_ap, addr, size)); + } while(!mps_commit(ap, addr, size)); return obj; } -obj_t scheme_make_table(size_t length, hash_t hashf, cmp_t cmpf) +obj_t scheme_make_table(mps_ap_t ap, size_t length, hash_t hashf, cmp_t cmpf) { obj_t obj; mps_addr_t addr; size_t l, size = ALIGN_OBJ(sizeof(table_s)); do { - mps_res_t res = mps_reserve(&addr, obj_ap, size); + mps_res_t res = mps_reserve(&addr, ap, size); if (res != MPS_RES_OK) error("out of memory in make_table"); obj = addr; obj->table.type = TYPE_TABLE; obj->table.buckets = NULL; - } while(!mps_commit(obj_ap, addr, size)); + } while(!mps_commit(ap, addr, size)); obj->table.hash = hashf; obj->table.cmp = cmpf; /* round up to next power of 2 */ for(l = 1; l < length; l *= 2); - obj->table.buckets = scheme_make_buckets(l); + obj->table.buckets = scheme_make_buckets(ap, l); mps_ld_reset(&obj->table.ld, scheme_arena); return obj; } diff --git a/mps/code/fmtscheme.h b/mps/code/fmtscheme.h index fbbbddf8ccd..95a62a53cef 100644 --- a/mps/code/fmtscheme.h +++ b/mps/code/fmtscheme.h @@ -168,18 +168,20 @@ typedef union obj_u { extern obj_t scheme_make_bool(int condition); -extern obj_t scheme_make_pair(obj_t car, obj_t cdr); -extern obj_t scheme_make_integer(long integer); -extern obj_t scheme_make_symbol(size_t length, char string[]); -extern obj_t scheme_make_string(size_t length, char string[]); -extern obj_t scheme_make_special(char *string); -extern obj_t scheme_make_operator(char *name, entry_t entry, obj_t arguments, - obj_t body, obj_t env, obj_t op_env); -extern obj_t scheme_make_port(obj_t name, FILE *stream); -extern obj_t scheme_make_character(char c); -extern obj_t scheme_make_vector(size_t length, obj_t fill); -extern obj_t scheme_make_buckets(size_t length); -extern obj_t scheme_make_table(size_t length, hash_t hashf, cmp_t cmpf); +extern obj_t scheme_make_pair(mps_ap_t ap, obj_t car, obj_t cdr); +extern obj_t scheme_make_integer(mps_ap_t ap, long integer); +extern obj_t scheme_make_symbol(mps_ap_t ap, size_t length, char string[]); +extern obj_t scheme_make_string(mps_ap_t ap, size_t length, char string[]); +extern obj_t scheme_make_special(mps_ap_t ap, char *string); +extern obj_t scheme_make_operator(mps_ap_t ap, char *name, entry_t entry, + obj_t arguments, obj_t body, obj_t env, + obj_t op_env); +extern obj_t scheme_make_port(mps_ap_t ap, obj_t name, FILE *stream); +extern obj_t scheme_make_character(mps_ap_t ap, char c); +extern obj_t scheme_make_vector(mps_ap_t ap, size_t length, obj_t fill); +extern obj_t scheme_make_buckets(mps_ap_t ap, size_t length); +extern obj_t scheme_make_table(mps_ap_t ap, size_t length, hash_t hashf, + cmp_t cmpf); extern void scheme_fmt(mps_fmt_t *fmt); extern mps_arena_t scheme_arena; From 4c52e0390b2b514ca51a9e2a4e161b6c36df02da Mon Sep 17 00:00:00 2001 From: David Lovemore Date: Tue, 6 May 2014 12:19:06 +0100 Subject: [PATCH 33/40] Only include tract loop ion segcheck when check level > minimal. This is to speed up SegCheck in HOT variety. Copied from Perforce Change: 185971 ServerID: perforce.ravenbrook.com --- mps/code/seg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mps/code/seg.c b/mps/code/seg.c index 7f0cd4bc907..c9ff20913c9 100644 --- a/mps/code/seg.c +++ b/mps/code/seg.c @@ -701,6 +701,7 @@ Bool SegCheck(Seg seg) CHECKL(seg->limit > TractBase(seg->firstTract)); /* Each tract of the segment must agree about white traces */ +#ifdef CHECKLEVEL > CheckLevelMINIMAL TRACT_TRACT_FOR(tract, addr, arena, seg->firstTract, seg->limit) { Seg trseg = NULL; /* suppress compiler warning */ @@ -709,6 +710,7 @@ Bool SegCheck(Seg seg) CHECKL(TractWhite(tract) == seg->white); CHECKL(TractPool(tract) == pool); } +#endif CHECKL(addr == seg->limit); /* The segment must belong to some pool, so it should be on a */ From b29e2f818191c3f14dfc459c5684d0e9a6ce0406 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 7 May 2014 23:33:22 +0100 Subject: [PATCH 34/40] Fix typos. Copied from Perforce Change: 185977 ServerID: perforce.ravenbrook.com --- mps/manual/source/topic/arena.rst | 6 +++--- mps/manual/source/topic/interface.rst | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mps/manual/source/topic/arena.rst b/mps/manual/source/topic/arena.rst index 1925117cc84..c62d3c58aae 100644 --- a/mps/manual/source/topic/arena.rst +++ b/mps/manual/source/topic/arena.rst @@ -396,8 +396,8 @@ Arena properties (over-)estimate the size of the heap. If you want to know how much memory the MPS is using then you're - probably interested in the value ``mps_arena_committed() - - mps_arena_spare_committed()``. + probably interested in the value :c:func:`mps_arena_committed()` − + :c:func:`mps_arena_spare_committed`. The amount of committed memory can be limited with the function :c:func:`mps_arena_commit_limit`. @@ -457,7 +457,7 @@ Arena properties Non-virtual-memory arena classes (for example, a :term:`client arena`) do not have spare committed memory. For these arenas, this - function functions sets a value but has no other effect. + function sets a value but has no other effect. Initially the spare commit limit is a configuration-dependent value. The value of the limit can be retrieved by the function diff --git a/mps/manual/source/topic/interface.rst b/mps/manual/source/topic/interface.rst index 478c22b8026..a939ddf302b 100644 --- a/mps/manual/source/topic/interface.rst +++ b/mps/manual/source/topic/interface.rst @@ -226,7 +226,7 @@ Macros implemented as a macro defined in the header, so a library function should not be declared explicitly if its header is included. Any macro definition of a function can be suppressed - locally be enclosing the name of the function in parentheses, + locally by enclosing the name of the function in parentheses, because the name is then not followed by the left parenthesis that indicates expansion of a macro function name. [...] Any invocation of a library function that is implemented as a From 5aee5122778a7b36553e6334a90104555317c09e Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Wed, 7 May 2014 23:38:51 +0100 Subject: [PATCH 35/40] Better to put the example first and discuss it afterwards. Copied from Perforce Change: 185978 ServerID: perforce.ravenbrook.com --- mps/manual/source/topic/arena.rst | 66 +++++++++++++++---------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/mps/manual/source/topic/arena.rst b/mps/manual/source/topic/arena.rst index c62d3c58aae..86e0a39550f 100644 --- a/mps/manual/source/topic/arena.rst +++ b/mps/manual/source/topic/arena.rst @@ -506,7 +506,7 @@ An arena is always in one of three states. In the *unclamped state*, garbage collection may take place, objects may move in memory, references may be updated, :term:`location dependencies` may become stale, virtual memory may - be requested from or return to the operating system, and other + be requested from or returned to the operating system, and other kinds of background activity may occur. This is the normal state. #. .. index:: @@ -531,19 +531,19 @@ An arena is always in one of three states. Here's a summary: -======================================== ================================== ============================= =========================== -State unclamped clamped parked -======================================== ================================== ============================= =========================== -Collections may be running? yes yes no -New collections may start? yes no no -Objects may move? yes no no -Location dependencies may become stale? yes no no -Memory may be returned to the OS? yes no no -Functions that leave arena in this state :c:func:`mps_arena_create`, :c:func:`mps_arena_clamp`, :c:func:`mps_arena_park`, - :c:func:`mps_arena_release`, :c:func:`mps_arena_step` :c:func:`mps_arena_collect` - :c:func:`mps_arena_start_collect`, - :c:func:`mps_arena_step` -======================================== ================================== ============================= =========================== +============================================ ================================== ============================= =========================== +State unclamped clamped parked +============================================ ================================== ============================= =========================== +Collections may be running? yes yes no +New collections may start? yes no no +Objects may move? yes no no +Location dependencies may become stale? yes no no +Memory may be returned to the OS? yes no no +Functions that leave the arena in this state :c:func:`mps_arena_create`, :c:func:`mps_arena_clamp`, :c:func:`mps_arena_park`, + :c:func:`mps_arena_release`, :c:func:`mps_arena_step` :c:func:`mps_arena_collect` + :c:func:`mps_arena_start_collect`, + :c:func:`mps_arena_step` +============================================ ================================== ============================= =========================== The clamped and parked states are important when introspecting and debugging. If you are examining the contents of the heap, you don't @@ -556,7 +556,7 @@ before inspecting memory, and:: (gdb) print mps_arena_release(arena) -afterward. +afterwards. The results of introspection functions like :c:func:`mps_arena_has_addr` only remain valid while the arena remains @@ -692,24 +692,7 @@ provides a function, :c:func:`mps_arena_step`, for making use of idle time to make memory management progress. Here's an example illustrating the use of this function in a program's -event loop. When the program is idle (there are no client actions to -perform), it requests that the MPS spend up to 10 milliseconds on -incremental work, by calling ``mps_arena_step(arena, 0.010, -0.0)``. When this returns false to indicate that there is no more work -to do, the program blocks on the client for two seconds: if this times -out, it predicts that the user will remain idle for at least a further -second, so it calls ``mps_arena_step(arena, 0.010, 100.0)`` to tell -that it's a good time to start a collection taking up to 10 ms × 100 -= 1 second, but not to pause for more than 10 ms. - -The program remains responsive: the MPS doesn't take control for more -than a few milliseconds at a time (at most 10). But at the same time, -major collection work can get done at times when the program would -otherwise be idle. Of course the numbers here are only for -illustration and should be chosen based on the requirements of the -application. - -:: +event loop. :: for (;;) { /* event loop */ for (;;) { @@ -729,6 +712,23 @@ application. } } +When the program is idle (there are no client actions to perform), it +requests that the MPS spend up to 10 milliseconds on incremental work, +by calling ``mps_arena_step(arena, 0.010, 0.0)``. When this returns +false to indicate that there is no more work to do, the program blocks +on the client for two seconds: if this times out, it predicts that the +user will remain idle for at least a further second, so it calls +``mps_arena_step(arena, 0.010, 100.0)`` to tell that it's a good time +to start a collection taking up to 10 ms × 100 = 1 second, but not to +pause for more than 10 ms. + +The program remains responsive: the MPS doesn't take control for more +than a few milliseconds at a time (at most 10). But at the same time, +major collection work can get done at times when the program would +otherwise be idle. Of course the numbers here are only for +illustration; they should be chosen based on the requirements of the +application. + .. c:function:: mps_bool_t mps_arena_step(mps_arena_t arena, double interval, double multiplier) From 3a6a9e1101a70159bfdd949772fb700a035273e3 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Sat, 10 May 2014 09:44:25 +0100 Subject: [PATCH 36/40] Fix compilation of seg.c. 1. "#ifdef CHECKLEVEL > CheckLevelMINIMAL" was bogus: the #ifdef should have been #if, but even then it would not be right, because in the CHECKLEVEL_DYNAMIC configuration, CHECKLEVEL is a variable rather than a preprocessor constant. So use the condition defined(AVER_AND_CHECK_ALL) instead. 2. The final CHECKL(addr == seg->limit) only makes sense if the loop was executed. 3. The variables used by the loop need to be inside the #if to avoid warnings about unused variables. 4. Add reference to the job from a comment. Copied from Perforce Change: 185992 ServerID: perforce.ravenbrook.com --- mps/code/seg.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/mps/code/seg.c b/mps/code/seg.c index c9ff20913c9..45a61abd185 100644 --- a/mps/code/seg.c +++ b/mps/code/seg.c @@ -678,10 +678,8 @@ failControl: Bool SegCheck(Seg seg) { - Tract tract; Arena arena; Pool pool; - Addr addr; Size align; CHECKS(Seg, seg); @@ -700,18 +698,25 @@ Bool SegCheck(Seg seg) CHECKL(AddrIsAligned(seg->limit, align)); CHECKL(seg->limit > TractBase(seg->firstTract)); - /* Each tract of the segment must agree about white traces */ -#ifdef CHECKLEVEL > CheckLevelMINIMAL - TRACT_TRACT_FOR(tract, addr, arena, seg->firstTract, seg->limit) { - Seg trseg = NULL; /* suppress compiler warning */ + /* Each tract of the segment must agree about white traces. Note + * that even if the CHECKs are compiled away there is still a + * significant cost in looping over the tracts, hence the guard. See + * job003778. */ +#if defined(AVER_AND_CHECK_ALL) + { + Tract tract; + Addr addr; + TRACT_TRACT_FOR(tract, addr, arena, seg->firstTract, seg->limit) { + Seg trseg = NULL; /* suppress compiler warning */ - CHECKD_NOSIG(Tract, tract); - CHECKL(TRACT_SEG(&trseg, tract) && (trseg == seg)); - CHECKL(TractWhite(tract) == seg->white); - CHECKL(TractPool(tract) == pool); + CHECKD_NOSIG(Tract, tract); + CHECKL(TRACT_SEG(&trseg, tract) && (trseg == seg)); + CHECKL(TractWhite(tract) == seg->white); + CHECKL(TractPool(tract) == pool); + } + CHECKL(addr == seg->limit); } -#endif - CHECKL(addr == seg->limit); +#endif /* AVER_AND_CHECK_ALL */ /* The segment must belong to some pool, so it should be on a */ /* pool's segment ring. (Actually, this isn't true just after */ From be87b190ed3ad729eb56fa4f5876824b3169612d Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Sat, 10 May 2014 09:45:26 +0100 Subject: [PATCH 37/40] Defined(aver_and_check_all) is a better condition for invalidating the colour tables. Copied from Perforce Change: 185993 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 65b2dcf754f..134d1228be0 100644 --- a/mps/code/poolams.c +++ b/mps/code/poolams.c @@ -172,7 +172,7 @@ static Res amsCreateTables(AMS ams, BT *allocReturn, goto failWhite; } -#if defined(AVER_AND_CHECK) +#if defined(AVER_AND_CHECK_ALL) /* Invalidate the colour tables in checking varieties. The algorithm * is designed not to depend on the initial values of these tables, * so by invalidating them we get some checking of this. From 9166015cf7cebc188ce302132b6fec3cb141567d Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Sat, 10 May 2014 09:47:58 +0100 Subject: [PATCH 38/40] Remove some unused headers. Copied from Perforce Change: 185994 ServerID: perforce.ravenbrook.com --- mps/code/clock.h | 1 - mps/code/misc.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/mps/code/clock.h b/mps/code/clock.h index 253f7a5e0e4..d5fd7bc0e4e 100644 --- a/mps/code/clock.h +++ b/mps/code/clock.h @@ -7,7 +7,6 @@ #ifndef clock_h #define clock_h -#include #include "mpmtypes.h" /* for Word */ diff --git a/mps/code/misc.h b/mps/code/misc.h index fed416157dd..7380421d5c5 100644 --- a/mps/code/misc.h +++ b/mps/code/misc.h @@ -13,8 +13,6 @@ #ifndef misc_h #define misc_h -#include - typedef int Bool; /* */ enum BoolEnum { From f23138db2f6c6b0c5df61b7bb742a73679f5d8bf Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Sun, 11 May 2014 18:16:46 +0100 Subject: [PATCH 39/40] Use xcrun so that we support xcode-select. Copied from Perforce Change: 185998 ServerID: perforce.ravenbrook.com --- mps/Makefile.in | 4 ++-- mps/tool/testcoverage | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mps/Makefile.in b/mps/Makefile.in index 2d558588673..e8899cce95c 100644 --- a/mps/Makefile.in +++ b/mps/Makefile.in @@ -1,7 +1,7 @@ # Makefile.in -- source for autoconf Makefile # # $Id$ -# Copyright (C) 2012-2013 Ravenbrook Limited. See end of file for license. +# Copyright (C) 2012-2014 Ravenbrook Limited. See end of file for license. # # YOU DON'T NEED AUTOCONF TO BUILD THE MPS # This is just here for people who want or expect a configure script. @@ -17,7 +17,7 @@ MPS_TARGET_NAME=@MPS_TARGET_NAME@ EXTRA_TARGETS=@EXTRA_TARGETS@ prefix=$(DESTDIR)@prefix@ TARGET_OPTS=-C code -f $(MPS_TARGET_NAME).gmk EXTRA_TARGETS="$(EXTRA_TARGETS)" -XCODEBUILD=xcodebuild -project code/mps.xcodeproj +XCODEBUILD=xcrun xcodebuild -project code/mps.xcodeproj all: @BUILD_TARGET@ diff --git a/mps/tool/testcoverage b/mps/tool/testcoverage index ff1967031dd..dacae8cd5f4 100755 --- a/mps/tool/testcoverage +++ b/mps/tool/testcoverage @@ -26,14 +26,14 @@ case "$ARCH-$OS" in CONFIGURATION=Debug ( cd -- "$CODE" - xcodebuild -config "$CONFIGURATION" clean - xcodebuild -config "$CONFIGURATION" -target testrun \ + xcrun xcodebuild -config "$CONFIGURATION" clean + xcrun xcodebuild -config "$CONFIGURATION" -target testrun \ GCC_GENERATE_TEST_COVERAGE_FILES=YES \ GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES ) ( cd -- "$CODE/xc/$PROJECT.build/$CONFIGURATION/$PROJECT.build/Objects-normal/$ARCH" - gcov mps.c 2> /dev/null + xcrun gcov mps.c 2> /dev/null ) | "$TOOL/gcovfmt" ;; *) From d60451c8ad988362a6d6dab742a58f3b96bc2578 Mon Sep 17 00:00:00 2001 From: Gareth Rees Date: Sun, 11 May 2014 18:17:40 +0100 Subject: [PATCH 40/40] Check keyword arguments after picking them. Copied from Perforce Change: 185999 ServerID: perforce.ravenbrook.com --- mps/code/arg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mps/code/arg.c b/mps/code/arg.c index e3fea68754d..407487b4060 100644 --- a/mps/code/arg.c +++ b/mps/code/arg.c @@ -159,6 +159,7 @@ Bool ArgPick(ArgStruct *argOut, ArgList args, Key key) { return FALSE; found: + AVER(key->check(&args[i])); *argOut = args[i]; for(;;) { args[i] = args[i + 1];