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/code/airtest.c b/mps/code/airtest.c index 56e1bd8c129..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; @@ -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/amsss.c b/mps/code/amsss.c index 95d735aae1c..988b8258175 100644 --- a/mps/code/amsss.c +++ b/mps/code/amsss.c @@ -28,7 +28,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 } }; @@ -108,7 +108,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[], + mps_bool_t haveAmbiguous) { mps_pool_t pool; mps_root_t exactRoot, ambigRoot = NULL; @@ -117,14 +118,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(); @@ -133,7 +133,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), @@ -157,7 +157,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"); @@ -190,80 +190,49 @@ 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); } int main(int argc, char *argv[]) { + int i; 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****************************** Testing AMS Debug\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)"); - } MPS_ARGS_END(args); - mps_tramp(&r, test, pool, 0); - mps_pool_destroy(pool); - - printf("\n\n****************************** Testing AMS Debug\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)"); - } 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); + 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 (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, ambig); + } MPS_ARGS_END(args); + } mps_chain_destroy(chain); mps_fmt_destroy(format); 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 08f68b6fb75..41259eecc24 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/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]; 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/buffer.c b/mps/code/buffer.c index bb5ef1d995b..53fc1c5dfd6 100644 --- a/mps/code/buffer.c +++ b/mps/code/buffer.c @@ -989,6 +989,7 @@ AllocPattern AllocPatternRampCollectAll(void) return &AllocPatternRampCollectAllStruct; } +ATTRIBUTE_UNUSED static Bool AllocPatternCheck(AllocPattern pattern) { CHECKL(pattern == &AllocPatternRampCollectAllStruct @@ -1070,7 +1071,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; } @@ -1284,7 +1285,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; } @@ -1511,7 +1512,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/cbs.c b/mps/code/cbs.c index c7facb9a98f..9c74cf0f890 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/chain.h b/mps/code/chain.h index 7e62262e1cd..b06596fdae8 100644 --- a/mps/code/chain.h +++ b/mps/code/chain.h @@ -83,7 +83,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/clock.h b/mps/code/clock.h index 2766ccd724c..0453643882f 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/config.h b/mps/code/config.h index 0afa66c06bb..1dfd7858f86 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 @@ -281,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/code/finaltest.c b/mps/code/finaltest.c index 88895027286..f449d7e1acf 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: job003773 */ + /* 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/fmtscheme.c b/mps/code/fmtscheme.c index 11900130a71..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; } @@ -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/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; diff --git a/mps/code/freelist.c b/mps/code/freelist.c index f51f44fbceb..bf0798ccdc0 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/global.c b/mps/code/global.c index 0b8f331b101..24a5e3e748f 100644 --- a/mps/code/global.c +++ b/mps/code/global.c @@ -1152,7 +1152,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/locus.c b/mps/code/locus.c index a6017a6b09c..8b2716000c5 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); @@ -317,13 +318,21 @@ 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; } @@ -336,7 +345,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; @@ -344,33 +353,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) { @@ -384,41 +399,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) @@ -475,9 +455,11 @@ Res ChainDescribe(Chain chain, mps_lib_FILE *stream, Count depth) 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/misc.h b/mps/code/misc.h index 809fd7e954a..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 { @@ -178,7 +176,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/mpm.h b/mps/code/mpm.h index f912718cc53..c243a4386c4 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -923,8 +923,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/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/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; diff --git a/mps/code/mpsi.c b/mps/code/mpsi.c index 3df0913df83..0573a6d4256 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)); @@ -1380,7 +1381,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); } @@ -1928,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 . diff --git a/mps/code/poolamc.c b/mps/code/poolamc.c index 05dea8bc83c..b19fcde45ae 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); @@ -476,6 +477,7 @@ typedef struct AMCStruct { /* */ /* amcGenCheck -- check consistency of a generation structure */ +ATTRIBUTE_UNUSED static Bool amcGenCheck(amcGen gen) { Arena arena; @@ -525,6 +527,7 @@ typedef struct amcBufStruct { /* amcBufCheck -- check consistency of an amcBuf */ +ATTRIBUTE_UNUSED static Bool amcBufCheck(amcBuf amcbuf) { CHECKS(amcBuf, amcbuf); @@ -2442,6 +2445,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/poolams.c b/mps/code/poolams.c index e85f06991ed..d74a06caca8 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. 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/poolmfs.c b/mps/code/poolmfs.c index baf7c2f5ee4..c7ed27f3f38 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/poolmrg.c b/mps/code/poolmrg.c index bc7762e9091..b0be22c66ef 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 6af3ae68724..1a854f79f61 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 6dd86183205..0012c5683bc 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 b5f6e942ba4..d986003b051 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: @@ -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/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/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/seg.c b/mps/code/seg.c index f55a07334af..bfeaf84a8af 100644 --- a/mps/code/seg.c +++ b/mps/code/seg.c @@ -595,7 +595,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); @@ -680,10 +680,8 @@ failControl: Bool SegCheck(Seg seg) { - Tract tract; Arena arena; Pool pool; - Addr addr; Size align; CHECKS(Seg, seg); @@ -702,16 +700,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 */ - 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); } - 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 */ 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/trace.c b/mps/code/trace.c index 8ea1b1bf0fd..1312fa04b29 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); @@ -415,7 +416,8 @@ Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet) { res = TraceAddWhite(trace, seg); if(res != ResOK) - return res; + goto failBegin; + haveWhiteSegs = TRUE; } } while (SegNext(&seg, arena, seg)); } @@ -426,6 +428,10 @@ Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet) AVER(ZoneSetSuper(condemnedSet, trace->white)); return ResOK; + +failBegin: + AVER(!haveWhiteSegs); /* See .whiten.fail. */ + return res; } @@ -1503,21 +1509,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); @@ -1527,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; } @@ -1570,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); 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); 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 ---------------- 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``. diff --git a/mps/design/type.txt b/mps/design/type.txt index 6ce0da3c035..baee04ef3d2 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 ``BOOLOF`` 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 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 ''' 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/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 diff --git a/mps/manual/source/release.rst b/mps/manual/source/release.rst index 18cc8ed72e9..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 ................. @@ -35,6 +49,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 ............. @@ -64,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/arena.rst b/mps/manual/source/topic/arena.rst index 1925117cc84..86e0a39550f 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 @@ -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) 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/error.rst b/mps/manual/source/topic/error.rst index 6b2e9452fc2..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,25 @@ 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 + 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 diff --git a/mps/manual/source/topic/finalization.rst b/mps/manual/source/topic/finalization.rst index 32f618f19e7..745feefed16 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). It might + make sense to replace it with a :term:`padding object`. + See :ref:`topic-message` for details of the message mechanism. @@ -123,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 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 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`. 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 ------------------- diff --git a/mps/tool/branch b/mps/tool/branch index 790dceb0eba..bb54f0d4527 100755 --- a/mps/tool/branch +++ b/mps/tool/branch @@ -46,10 +46,10 @@ CHILD_RE = r'(?:{}|{})$'.format(TASK_BRANCH_RE, VERSION_BRANCH_RE) TASK_BRANCH_ENTRY = ''' - {date}/{task} + {date}/{task} Changes {desc_html} - Active (diffs). + Diffs ''' @@ -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() 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 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" ;; *) 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" &&