diff --git a/mps/.p4ignore b/mps/.p4ignore index ba720759d8c..fb2e5c024e5 100644 --- a/mps/.p4ignore +++ b/mps/.p4ignore @@ -16,3 +16,5 @@ TAGS *.dSYM code/*/*/*.d *.pyc +test/test/log +test/test/obj diff --git a/mps/code/.p4ignore b/mps/code/.p4ignore index 7a9dfb599a8..dcda2b9ad09 100644 --- a/mps/code/.p4ignore +++ b/mps/code/.p4ignore @@ -9,6 +9,7 @@ lii6ll w3i3mv w3i6mv xci3gc +xci6ll # Visual Studio junk Debug Release diff --git a/mps/code/abq.c b/mps/code/abq.c index 596921dd09a..b915bb42c9b 100644 --- a/mps/code/abq.c +++ b/mps/code/abq.c @@ -107,7 +107,7 @@ Bool ABQPush(ABQ abq, void *element) if (ABQIsFull(abq)) return FALSE; - mps_lib_memcpy(ABQElement(abq, abq->in), element, abq->elementSize); + (void)mps_lib_memcpy(ABQElement(abq, abq->in), element, abq->elementSize); abq->in = ABQNextIndex(abq, abq->in); AVERT(ABQ, abq); @@ -126,7 +126,7 @@ Bool ABQPop(ABQ abq, void *elementReturn) if (ABQIsEmpty(abq)) return FALSE; - mps_lib_memcpy(elementReturn, ABQElement(abq, abq->out), abq->elementSize); + (void)mps_lib_memcpy(elementReturn, ABQElement(abq, abq->out), abq->elementSize); abq->out = ABQNextIndex(abq, abq->out); @@ -146,7 +146,7 @@ Bool ABQPeek(ABQ abq, void *elementReturn) if (ABQIsEmpty(abq)) return FALSE; - mps_lib_memcpy(elementReturn, ABQElement(abq, abq->out), abq->elementSize); + (void)mps_lib_memcpy(elementReturn, ABQElement(abq, abq->out), abq->elementSize); /* Identical to pop, but don't increment out */ @@ -261,7 +261,7 @@ void ABQIterate(ABQ abq, ABQIterateMethod iterate, void *closureP, Size closureS AVERT(Bool, delete); if (!delete) { if (copy != index) - mps_lib_memcpy(ABQElement(abq, copy), element, abq->elementSize); + (void)mps_lib_memcpy(ABQElement(abq, copy), element, abq->elementSize); copy = ABQNextIndex(abq, copy); } index = ABQNextIndex(abq, index); @@ -272,8 +272,8 @@ void ABQIterate(ABQ abq, ABQIterateMethod iterate, void *closureP, Size closureS /* If any elements were deleted, need to copy remainder of queue. */ if (copy != index) { while (index != in) { - mps_lib_memcpy(ABQElement(abq, copy), ABQElement(abq, index), - abq->elementSize); + (void)mps_lib_memcpy(ABQElement(abq, copy), ABQElement(abq, index), + abq->elementSize); copy = ABQNextIndex(abq, copy); index = ABQNextIndex(abq, index); } diff --git a/mps/code/abqtest.c b/mps/code/abqtest.c index 350f0e89f86..4cff09f1745 100644 --- a/mps/code/abqtest.c +++ b/mps/code/abqtest.c @@ -130,7 +130,7 @@ static void step(void) DestroyTestBlock(a); break; default: - if (!deleted & (pushee > popee)) { + if (!deleted && (pushee > popee)) { TestBlock b; TestClosureStruct cl; deleted = (unsigned)abqRnd (pushee - popee) + popee; diff --git a/mps/code/airtest.c b/mps/code/airtest.c index 4d4219f7f5c..367a4464390 100644 --- a/mps/code/airtest.c +++ b/mps/code/airtest.c @@ -3,26 +3,51 @@ * $Id: //info.ravenbrook.com/project/mps/branch/2014-01-15/nailboard/code/fotest.c#1 $ * Copyright (c) 2014 Ravenbrook Limited. See end of file for license. * - * This test case creates a bunch of vectors, registers them for - * finalization, and then discards the base pointers to those objects, - * keeping only ambiguous interior references to the vector entries in - * the stack-allocated table s. + * .overview: This test case creates a bunch of vectors, registers + * them for finalization, and then discards the base pointers to those + * objects, keeping only ambiguous interior references to the vector + * entries in the stack-allocated table s. * - * If any of these objects are finalized, then this means that the - * ambiguous interior references has failed to keep the object alive. + * .options: The test has two options: + * + * 'interior' is the value passed as MPS_KEY_INTERIOR when creating + * the AMC pool. If TRUE, interior pointers must keep objects alive, + * and so if any of these objects are finalized, the test fails. If + * FALSE, interior pointers do not keep objects alive, so it is likely + * that all the objects will be finalized. + * + * 'stack' is TRUE if the C stack is registered as a root. (If FALSE, + * we register the table of interior pointers as an ambiguous root.) + * + * .fail.lii6ll: The test case passes on most platforms with + * interior=FALSE and stack=TRUE (that is, all vectors get finalized), + * but fails on lii6ll in variety HOT. Rather than struggle to defeat + * the Clang optimizer, we choose not to test in this configuration. + * In any case, the MPS does not guarantee anything about timely + * finalization (see ). */ #include "mps.h" -#include "fmtscheme.h" +#include "mpsavm.h" +#include "mpscamc.h" +#include "mpslib.h" #include "testlib.h" +#include "fmtscheme.h" #define OBJ_LEN (1u << 4) -#define OBJ_COUNT 10 +#define OBJ_COUNT 1 -void test_main(void) +static void test_air(int interior, int stack) { + size_t n_finalized = 0; size_t i, j; - obj_t *s[OBJ_COUNT]; + obj_t *s[OBJ_COUNT] = {0}; + mps_root_t root; + if (!stack) { + mps_addr_t *p = (void *)s; + die(mps_root_create_table(&root, scheme_arena, mps_rank_ambig(), 0, p, + OBJ_COUNT), "mps_root_create_table"); + } 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); @@ -41,12 +66,98 @@ void test_main(void) mps_arena_release(scheme_arena); if (mps_message_get(&msg, scheme_arena, mps_message_type_finalization())) { mps_addr_t ref; - obj_t o; mps_message_finalization_ref(&ref, scheme_arena, msg); - o = ref; - error("wrongly finalized vector %ld at %p", o->vector.vector[0]->integer.integer, o); + ++ n_finalized; + if (interior) { + obj_t o; + o = ref; + error("wrongly finalized vector %ld at %p", + o->vector.vector[0]->integer.integer, (void *)o); + } } } + if (!interior && n_finalized < OBJ_COUNT) { + error("only finalized %"PRIuLONGEST" out of %"PRIuLONGEST" vectors.", + (ulongest_t)n_finalized, (ulongest_t)OBJ_COUNT); + } + if (!stack) { + mps_root_destroy(root); + } +} + +static mps_gen_param_s obj_gen_params[] = { + { 150, 0.85 }, + { 170, 0.45 } +}; + +static void test_main(int interior, int stack) +{ + mps_res_t res; + mps_chain_t obj_chain; + mps_fmt_t obj_fmt; + mps_thr_t thread; + mps_root_t reg_root; + void *marker = ▮ + + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, 1 << 20); + MPS_ARGS_DONE(args); + res = mps_arena_create_k(&scheme_arena, mps_arena_class_vm(), args); + } MPS_ARGS_END(args); + if (res != MPS_RES_OK) error("Couldn't create arena"); + + res = mps_chain_create(&obj_chain, scheme_arena, + sizeof(obj_gen_params) / sizeof(*obj_gen_params), + obj_gen_params); + if (res != MPS_RES_OK) error("Couldn't create obj chain"); + + scheme_fmt(&obj_fmt); + + MPS_ARGS_BEGIN(args) { + 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); + + res = mps_ap_create_k(&obj_ap, obj_pool, mps_args_none); + if (res != MPS_RES_OK) error("Couldn't create obj allocation point"); + + res = mps_thread_reg(&thread, scheme_arena); + if (res != MPS_RES_OK) error("Couldn't register thread"); + + if (stack) { + res = mps_root_create_reg(®_root, scheme_arena, mps_rank_ambig(), 0, + thread, mps_stack_scan_ambig, marker, 0); + if (res != MPS_RES_OK) error("Couldn't create root"); + } + + test_air(interior, stack); + + mps_arena_park(scheme_arena); + if (stack) + mps_root_destroy(reg_root); + mps_thread_dereg(thread); + mps_ap_destroy(obj_ap); + mps_pool_destroy(obj_pool); + mps_chain_destroy(obj_chain); + mps_fmt_destroy(obj_fmt); + mps_arena_destroy(scheme_arena); +} + +int main(int argc, char *argv[]) +{ + testlib_init(argc, argv); + + test_main(TRUE, TRUE); + test_main(TRUE, FALSE); + /* not test_main(FALSE, TRUE) -- see .fail.lii6ll. */ + test_main(FALSE, FALSE); + + printf("%s: Conclusion: Failed to find any defects.\n", argv[0]); + return 0; } @@ -90,4 +201,3 @@ void test_main(void) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - diff --git a/mps/code/amcss.c b/mps/code/amcss.c index bf0c6611174..3f9afba4e82 100644 --- a/mps/code/amcss.c +++ b/mps/code/amcss.c @@ -196,7 +196,8 @@ static void test(mps_arena_t arena) collections = c; report(arena); - printf("%lu objects (mps_collections says: %lu)\n", objs, c); + printf("%lu objects (mps_collections says: %"PRIuLONGEST")\n", objs, + (ulongest_t)c); /* test mps_arena_has_addr */ { @@ -285,7 +286,7 @@ static void test(mps_arena_t arena) if (objs % 1024 == 0) { report(arena); putchar('.'); - fflush(stdout); + (void)fflush(stdout); } ++objs; diff --git a/mps/code/amcsshe.c b/mps/code/amcsshe.c index 5ad7c064f5d..15dd342336c 100644 --- a/mps/code/amcsshe.c +++ b/mps/code/amcsshe.c @@ -173,7 +173,8 @@ static void *test(void *arg, size_t s) if (collections != c) { collections = c; - printf("\nCollection %lu, %lu objects.\n", c, objs); + printf("\nCollection %"PRIuLONGEST", %lu objects.\n", + (ulongest_t)c, objs); report(arena); for (r = 0; r < exactRootsCOUNT; ++r) { if (exactRoots[r] != objNULL) @@ -236,7 +237,7 @@ static void *test(void *arg, size_t s) if (objs % 1024 == 0) { report(arena); putchar('.'); - fflush(stdout); + (void)fflush(stdout); } ++objs; diff --git a/mps/code/amsss.c b/mps/code/amsss.c index a0a1fe666e6..c678f26ff45 100644 --- a/mps/code/amsss.c +++ b/mps/code/amsss.c @@ -152,7 +152,7 @@ static void *test(void *arg, size_t haveAmbigous) lastStep = totalSize; printf("\nSize %"PRIuLONGEST" bytes, %lu objects.\n", (ulongest_t)totalSize, objs); - fflush(stdout); + (void)fflush(stdout); for(i = 0; i < exactRootsCOUNT; ++i) cdie(exactRoots[i] == objNULL || dylan_check(exactRoots[i]), "all roots check"); @@ -184,7 +184,7 @@ static void *test(void *arg, size_t haveAmbigous) if (objs % 256 == 0) { printf("."); report(); - fflush(stdout); + (void)fflush(stdout); } } diff --git a/mps/code/amssshe.c b/mps/code/amssshe.c index 4787ef80e6f..37408340a00 100644 --- a/mps/code/amssshe.c +++ b/mps/code/amssshe.c @@ -111,7 +111,7 @@ static void *test(void *arg, size_t s) lastStep = totalSize; printf("\nSize %"PRIuLONGEST" bytes, %lu objects.\n", (ulongest_t)totalSize, objs); - fflush(stdout); + (void)fflush(stdout); for(i = 0; i < exactRootsCOUNT; ++i) cdie(exactRoots[i] == objNULL || dylan_check(exactRoots[i]), "all roots check"); @@ -139,7 +139,7 @@ static void *test(void *arg, size_t s) ++objs; if (objs % 256 == 0) { printf("."); - fflush(stdout); + (void)fflush(stdout); } } diff --git a/mps/code/apss.c b/mps/code/apss.c index aaa5da0957b..3a60587d412 100644 --- a/mps/code/apss.c +++ b/mps/code/apss.c @@ -43,14 +43,14 @@ static mps_res_t make(mps_addr_t *p, mps_ap_t ap, size_t size) /* stress -- create a pool of the requested type and allocate in it */ -static mps_res_t stress(mps_class_t class, size_t (*size)(unsigned long i), +static mps_res_t stress(mps_class_t class, size_t (*size)(size_t i), mps_arena_t arena, ...) { mps_res_t res = MPS_RES_OK; mps_pool_t pool; mps_ap_t ap; va_list arg; - unsigned long i, k; + size_t i, k; int *ps[testSetSIZE]; size_t ss[testSetSIZE]; @@ -78,7 +78,7 @@ static mps_res_t stress(mps_class_t class, size_t (*size)(unsigned long i), for (k=0; k (b)) ? (a) : (b)) - -#define alignUp(w, a) (((w) + (a) - 1) & ~((size_t)(a) - 1)) - - /* randomSizeAligned -- produce sizes both large and small, * aligned by platform alignment */ -static size_t randomSizeAligned(unsigned long i) +static size_t randomSizeAligned(size_t i) { size_t maxSize = 2 * 160 * 0x2000; /* Reduce by a factor of 2 every 10 cycles. Total allocation about 40 MB. */ @@ -127,16 +122,9 @@ static size_t randomSizeAligned(unsigned long i) } -static mps_pool_debug_option_s bothOptions8 = { - /* .fence_template = */ (const void *)"postpost", - /* .fence_size = */ 8, - /* .free_template = */ (const void *)"DEAD", - /* .free_size = */ 4 -}; - -static mps_pool_debug_option_s bothOptions16 = { +static mps_pool_debug_option_s bothOptions = { /* .fence_template = */ (const void *)"postpostpostpost", - /* .fence_size = */ 16, + /* .fence_size = */ MPS_PF_ALIGN, /* .free_template = */ (const void *)"DEAD", /* .free_size = */ 4 }; @@ -186,9 +174,6 @@ static void testInArena(mps_arena_t arena, mps_pool_debug_option_s *options) int main(int argc, char *argv[]) { mps_arena_t arena; - mps_pool_debug_option_s *bothOptions; - - bothOptions = MPS_PF_ALIGN == 8 ? &bothOptions8 : &bothOptions16; testlib_init(argc, argv); @@ -201,11 +186,10 @@ int main(int argc, char *argv[]) MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, 2 * testArenaSIZE); MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, FALSE); - MPS_ARGS_DONE(args); die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "mps_arena_create"); } MPS_ARGS_END(args); - testInArena(arena, bothOptions); + testInArena(arena, &bothOptions); mps_arena_destroy(arena); MPS_ARGS_BEGIN(args) { @@ -215,7 +199,7 @@ int main(int argc, char *argv[]) die(mps_arena_create_k(&arena, mps_arena_class_cl(), args), "mps_arena_create"); } MPS_ARGS_END(args); - testInArena(arena, bothOptions); + testInArena(arena, &bothOptions); mps_arena_destroy(arena); printf("%s: Conclusion: Failed to find any defects.\n", argv[0]); diff --git a/mps/code/arena.c b/mps/code/arena.c index 21ceea8c1e3..30f7687ce81 100644 --- a/mps/code/arena.c +++ b/mps/code/arena.c @@ -1,7 +1,7 @@ /* arena.c: ARENA ALLOCATION FEATURES * * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * .sources: is the main design document. */ @@ -86,7 +86,7 @@ DEFINE_CLASS(AbstractArenaClass, class) Bool ArenaClassCheck(ArenaClass class) { - CHECKL(ProtocolClassCheck(&class->protocol)); + CHECKD(ProtocolClass, &class->protocol); CHECKL(class->name != NULL); /* Should be <=6 char C identifier */ CHECKL(class->size >= sizeof(ArenaStruct)); /* Offset of generic Pool within class-specific instance cannot be */ @@ -147,7 +147,7 @@ Bool ArenaCheck(Arena arena) if (arena->primary != NULL) { CHECKD(Chunk, arena->primary); } - CHECKL(RingCheck(&arena->chunkRing)); + CHECKD_NOSIG(Ring, &arena->chunkRing); /* nothing to check for chunkSerial */ CHECKD(ChunkCacheEntry, &arena->chunkCache); @@ -155,7 +155,9 @@ Bool ArenaCheck(Arena arena) CHECKL(BoolCheck(arena->hasFreeCBS)); if (arena->hasFreeCBS) - CBSCheck(ArenaFreeCBS(arena)); + CHECKD(CBS, ArenaFreeCBS(arena)); + + CHECKL(BoolCheck(arena->zoned)); return TRUE; } @@ -179,7 +181,7 @@ Res ArenaInit(Arena arena, ArenaClass class, Align alignment, ArgList args) AVER(arena != NULL); AVERT(ArenaClass, class); - AVER(AlignCheck(alignment)); + AVERT(Align, alignment); if (ArgPick(&arg, args, MPS_KEY_ARENA_ZONED)) zoned = arg.val.b; @@ -224,7 +226,6 @@ Res ArenaInit(Arena arena, ArenaClass class, Align alignment, ArgList args) MPS_ARGS_ADD(piArgs, MPS_KEY_MFS_UNIT_SIZE, sizeof(CBSBlockStruct)); MPS_ARGS_ADD(piArgs, MPS_KEY_EXTEND_BY, arena->alignment); MPS_ARGS_ADD(piArgs, MFSExtendSelf, FALSE); - MPS_ARGS_DONE(piArgs); res = PoolInit(ArenaCBSBlockPool(arena), arena, PoolClassMFS(), piArgs); } MPS_ARGS_END(piArgs); AVER(res == ResOK); /* no allocation, no failure expected */ @@ -234,7 +235,6 @@ Res ArenaInit(Arena arena, ArenaClass class, Align alignment, ArgList args) /* Initialise the freeCBS. */ MPS_ARGS_BEGIN(cbsiArgs) { MPS_ARGS_ADD(cbsiArgs, CBSBlockPool, ArenaCBSBlockPool(arena)); - MPS_ARGS_DONE(cbsiArgs); res = CBSInit(ArenaFreeCBS(arena), arena, arena, alignment, /* fastFind */ TRUE, arena->zoned, cbsiArgs); } MPS_ARGS_END(cbsiArgs); @@ -286,7 +286,7 @@ Res ArenaCreate(Arena *arenaReturn, ArenaClass class, ArgList args) AVER(arenaReturn != NULL); AVERT(ArenaClass, class); - AVER(ArgListCheck(args)); + AVERT(ArgList, args); /* We must initialise the event subsystem very early, because event logging will start as soon as anything interesting happens and expect to write @@ -558,7 +558,7 @@ Res ControlAlloc(void **baseReturn, Arena arena, size_t size, AVERT(Arena, arena); AVER(baseReturn != NULL); AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); AVER(arena->poolReady); res = PoolAlloc(&base, ArenaControlPool(arena), (Size)size, @@ -1023,7 +1023,7 @@ Res ArenaAlloc(Addr *baseReturn, SegPref pref, Size size, Pool pool, AVERT(SegPref, pref); AVER(size > (Size)0); AVERT(Pool, pool); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); arena = PoolArena(pool); AVERT(Arena, arena); @@ -1321,7 +1321,7 @@ Res ArenaAddrObject(Addr *pReturn, Arena arena, Addr addr) /* 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/arenacl.c b/mps/code/arenacl.c index e900a3b4dbf..3d07f529779 100644 --- a/mps/code/arenacl.c +++ b/mps/code/arenacl.c @@ -1,7 +1,7 @@ /* arenacl.c: ARENA CLASS USING CLIENT MEMORY * * $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. * * .design: See . * @@ -67,7 +67,7 @@ static Bool ClientChunkCheck(ClientChunk clChunk) CHECKS(ClientChunk, clChunk); chunk = ClientChunk2Chunk(clChunk); - CHECKL(ChunkCheck(chunk)); + CHECKD(Chunk, chunk); CHECKL(clChunk->freePages <= chunk->pages); /* check they don't overlap (knowing the order) */ CHECKL((Addr)(chunk + 1) < (Addr)chunk->allocTable); @@ -201,7 +201,7 @@ static void ClientArenaVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs) args[1].key = MPS_KEY_ARENA_CL_BASE; args[1].val.addr = va_arg(varargs, Addr); args[2].key = MPS_KEY_ARGS_END; - AVER(ArgListCheck(args)); + AVERT(ArgList, args); } @@ -228,7 +228,7 @@ static Res ClientArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args) AVER(arenaReturn != NULL); AVER((ArenaClass)mps_arena_class_cl() == class); - AVER(ArgListCheck(args)); + AVERT(ArgList, args); ArgRequire(&arg, args, MPS_KEY_ARENA_SIZE); size = arg.val.size; @@ -434,6 +434,7 @@ DEFINE_ARENA_CLASS(ClientArenaClass, this) this->free = ClientFree; this->chunkInit = ClientChunkInit; this->chunkFinish = ClientChunkFinish; + AVERT(ArenaClass, this); } @@ -447,7 +448,7 @@ mps_arena_class_t mps_arena_class_cl(void) /* 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/arenavm.c b/mps/code/arenavm.c index 68753cd6e87..1bcc6272f35 100644 --- a/mps/code/arenavm.c +++ b/mps/code/arenavm.c @@ -99,8 +99,8 @@ static Bool VMChunkCheck(VMChunk vmchunk) CHECKS(VMChunk, vmchunk); chunk = VMChunk2Chunk(vmchunk); - CHECKL(ChunkCheck(chunk)); - CHECKL(VMCheck(vmchunk->vm)); + CHECKD(Chunk, chunk); + CHECKD_NOSIG(VM, vmchunk->vm); /* */ CHECKL(VMAlign(vmchunk->vm) == ChunkPageSize(chunk)); CHECKL(vmchunk->overheadMappedLimit <= (Addr)chunk->pageTable); CHECKD(SparseArray, &vmchunk->pages); @@ -174,7 +174,7 @@ static Bool VMArenaCheck(VMArena vmArena) CHECKL(VMMapped(primary->vm) <= arena->committed); } - CHECKL(RingCheck(&vmArena->spareRing)); + CHECKD_NOSIG(Ring, &vmArena->spareRing); /* FIXME: Can't check VMParams */ @@ -438,7 +438,7 @@ static void VMArenaVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs) args[0].key = MPS_KEY_ARENA_SIZE; args[0].val.size = va_arg(varargs, Size); args[1].key = MPS_KEY_ARGS_END; - AVER(ArgListCheck(args)); + AVERT(ArgList, args); } @@ -493,7 +493,7 @@ static Res VMArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args) AVER(arenaReturn != NULL); AVER(class == VMArenaClassGet()); - AVER(ArgListCheck(args)); + AVERT(ArgList, args); ArgRequire(&arg, args, MPS_KEY_ARENA_SIZE); userSize = arg.val.size; @@ -530,7 +530,7 @@ static Res VMArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args) /* Copy the stack-allocated VM parameters into their home in the VMArena. */ AVER(sizeof(vmArena->vmParams) == sizeof(vmParams)); - mps_lib_memcpy(vmArena->vmParams, vmParams, sizeof(vmArena->vmParams)); + (void)mps_lib_memcpy(vmArena->vmParams, vmParams, sizeof(vmArena->vmParams)); /* */ vmArena->extendBy = userSize; @@ -1159,6 +1159,7 @@ DEFINE_ARENA_CLASS(VMArenaClass, this) this->compact = VMCompact; this->describe = VMArenaDescribe; this->pagesMarkAllocated = VMPagesMarkAllocated; + AVERT(ArenaClass, this); } diff --git a/mps/code/arg.c b/mps/code/arg.c index 442066824ad..e3fea68754d 100644 --- a/mps/code/arg.c +++ b/mps/code/arg.c @@ -1,7 +1,7 @@ /* arg.c: ARGUMENT LISTS * * $Id$ - * Copyright (c) 2013 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2013-2014 Ravenbrook Limited. See end of file for license. * * .source: See . */ @@ -52,7 +52,7 @@ Bool ArgCheckAddr(Arg arg) { } Bool ArgCheckPoolDebugOptions(Arg arg) { - CHECKL(PoolDebugOptionsCheck((PoolDebugOptions)arg->val.pool_debug_options)); + CHECKD_NOSIG(PoolDebugOptions, (PoolDebugOptions)arg->val.pool_debug_options); return TRUE; } @@ -138,7 +138,7 @@ Bool ArgListCheck(ArgList args) CHECKL(args != NULL); for (i = 0; args[i].key != MPS_KEY_ARGS_END; ++i) { CHECKL(i < MPS_ARGS_MAX); - CHECKL(ArgCheck(&args[i])); + CHECKD_NOSIG(Arg, &args[i]); } return TRUE; } @@ -150,7 +150,7 @@ Bool ArgPick(ArgStruct *argOut, ArgList args, Key key) { Index i; AVER(argOut != NULL); - AVER(ArgListCheck(args)); + AVERT(ArgList, args); AVERT(Key, key); for (i = 0; args[i].key != MPS_KEY_ARGS_END; ++i) @@ -185,14 +185,14 @@ void ArgTrivVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs) { UNUSED(varargs); args[0].key = MPS_KEY_ARGS_END; - AVER(ArgListCheck(args)); + AVERT(ArgList, args); } /* 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/awlut.c b/mps/code/awlut.c index 8af4bcd4bbc..b8e14a0db7d 100644 --- a/mps/code/awlut.c +++ b/mps/code/awlut.c @@ -118,7 +118,7 @@ static mps_word_t *alloc_string(const char *s, mps_ap_t ap) * .assume.dylan-obj */ -static mps_word_t *alloc_table(unsigned long n, mps_ap_t ap) +static mps_word_t *alloc_table(size_t n, mps_ap_t ap) { size_t objsize; void *p; @@ -127,7 +127,7 @@ static mps_word_t *alloc_table(unsigned long n, mps_ap_t ap) objsize = (3 + n) * sizeof(mps_word_t); objsize = size_tAlignUp(objsize, MPS_PF_ALIGN); do { - unsigned long i; + size_t i; die(mps_reserve(&p, ap, objsize), "Reserve Table\n"); object = p; @@ -145,7 +145,7 @@ static mps_word_t *alloc_table(unsigned long n, mps_ap_t ap) /* gets the nth slot from a table * .assume.dylan-obj */ -static mps_word_t *table_slot(mps_word_t *table, unsigned long n) +static mps_word_t *table_slot(mps_word_t *table, size_t n) { return (mps_word_t *)table[3+n]; } @@ -154,8 +154,7 @@ static mps_word_t *table_slot(mps_word_t *table, unsigned long n) /* sets the nth slot in a table * .assume.dylan-obj */ -static void set_table_slot(mps_word_t *table, - unsigned long n, mps_word_t *p) +static void set_table_slot(mps_word_t *table, size_t n, mps_word_t *p) { cdie(table[0] == (mps_word_t)table_wrapper, "set_table_slot"); table[3+n] = (mps_word_t)p; @@ -182,7 +181,7 @@ static void test(mps_arena_t arena, mps_word_t *exacttable; mps_word_t *preserve[TABLE_SLOTS]; /* preserves objects in the weak */ /* table by referring to them */ - unsigned long i, j; + size_t i, j; void *p; exacttable = alloc_table(TABLE_SLOTS, exactap); @@ -194,11 +193,12 @@ static void test(mps_arena_t arena, for(i = 0; i < TABLE_SLOTS; ++i) { mps_word_t *string; - /* Ensure that the last entry in the table is preserved, so that - * we don't get a false positive due to the local variable - * 'string' keeping this entry alive (see job003436). + /* Ensure that the first and last entries in the table are + * preserved, so that we don't get false positives due to the + * local variables 'weak_table' and 'string' keeping these entries + * alive (see job003436). */ - if (rnd() % 2 == 0 || i + 1 == TABLE_SLOTS) { + if (rnd() % 2 == 0 || i == 0 || i + 1 == TABLE_SLOTS) { string = alloc_string("iamalive", leafap); preserve[i] = string; } else { @@ -216,17 +216,19 @@ static void test(mps_arena_t arena, } } - mps_arena_collect(arena); + die(mps_arena_collect(arena), "mps_arena_collect"); mps_arena_release(arena); for(i = 0; i < TABLE_SLOTS; ++i) { if (preserve[i] == 0) { if (table_slot(weaktable, i)) { - error("Strongly unreachable weak table entry found, slot %lu.\n", i); + error("Strongly unreachable weak table entry found, " + "slot %"PRIuLONGEST".\n", (ulongest_t)i); } else { if (table_slot(exacttable, i) != 0) { error("Weak table entry deleted, but corresponding " - "exact table entry not deleted, slot %lu.\n", i); + "exact table entry not deleted, slot %"PRIuLONGEST".\n", + (ulongest_t)i); } } } diff --git a/mps/code/awluthe.c b/mps/code/awluthe.c index 9fb1281dcc1..257b4142723 100644 --- a/mps/code/awluthe.c +++ b/mps/code/awluthe.c @@ -121,7 +121,7 @@ static mps_word_t *alloc_string(const char *s, mps_ap_t ap) * .assume.dylan-obj */ -static mps_word_t *alloc_table(unsigned long n, mps_ap_t ap) +static mps_word_t *alloc_table(size_t n, mps_ap_t ap) { size_t objsize; void *p; @@ -130,7 +130,7 @@ static mps_word_t *alloc_table(unsigned long n, mps_ap_t ap) objsize = (3 + n) * sizeof(mps_word_t); objsize = size_tAlignUp(objsize, MPS_PF_ALIGN); do { - unsigned long i; + size_t i; die(mps_reserve(&p, ap, objsize + headerSIZE), "Reserve Table\n"); object = (mps_word_t *)((char *)p + headerSIZE); @@ -150,7 +150,7 @@ static mps_word_t *alloc_table(unsigned long n, mps_ap_t ap) /* gets the nth slot from a table * .assume.dylan-obj */ -static mps_word_t *table_slot(mps_word_t *table, unsigned long n) +static mps_word_t *table_slot(mps_word_t *table, size_t n) { return (mps_word_t *)table[3+n]; } @@ -159,8 +159,7 @@ static mps_word_t *table_slot(mps_word_t *table, unsigned long n) /* sets the nth slot in a table * .assume.dylan-obj */ -static void set_table_slot(mps_word_t *table, - unsigned long n, mps_word_t *p) +static void set_table_slot(mps_word_t *table, size_t n, mps_word_t *p) { cdie(table[0] == (mps_word_t)table_wrapper, "set_table_slot"); table[3+n] = (mps_word_t)p; @@ -187,7 +186,7 @@ static void test(mps_arena_t arena, mps_word_t *exacttable; mps_word_t *preserve[TABLE_SLOTS]; /* preserves objects in the weak */ /* table by referring to them */ - unsigned long i, j; + size_t i, j; void *p; exacttable = alloc_table(TABLE_SLOTS, exactap); @@ -221,17 +220,19 @@ static void test(mps_arena_t arena, } } - mps_arena_collect(arena); + die(mps_arena_collect(arena), "mps_arena_collect"); mps_arena_release(arena); for(i = 0; i < TABLE_SLOTS; ++i) { if (preserve[i] == 0) { if (table_slot(weaktable, i)) { - error("Strongly unreachable weak table entry found, slot %lu.\n", i); + error("Strongly unreachable weak table entry found, " + "slot %"PRIuLONGEST".\n", (ulongest_t)i); } else { if (table_slot(exacttable, i) != 0) { error("Weak table entry deleted, but corresponding " - "exact table entry not deleted, slot %lu.\n", i); + "exact table entry not deleted, slot %"PRIuLONGEST".\n", + (ulongest_t)i); } } } @@ -274,8 +275,8 @@ static void *setup(void *v, size_t s) die(mps_root_create_reg(&stack, arena, mps_rank_ambig(), 0, thr, mps_stack_scan_ambig, v, 0), "Root Create\n"); - EnsureHeaderFormat(&dylanfmt, arena); - EnsureHeaderWeakFormat(&dylanweakfmt, arena); + 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. */ diff --git a/mps/code/boot.c b/mps/code/boot.c index f42d5ded7cc..eff8409fc1e 100644 --- a/mps/code/boot.c +++ b/mps/code/boot.c @@ -1,7 +1,7 @@ /* boot.c: BOOTSTRAP ALLOCATOR * * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * .overview: A structure and protocols for allocating memory from a * given block. Very simple, it basically just increments a pointer. @@ -101,7 +101,7 @@ Res BootAlloc(void **pReturn, BootBlock boot, size_t size, size_t align) AVER(pReturn != NULL); AVERT(BootBlock, boot); AVER(size > 0); - AVER(AlignCheck((Align)align)); + AVERT(Align, (Align)align); /* Align alloc pointer up and bounds check. */ blockBase = PointerAlignUp(boot->alloc, align); @@ -127,7 +127,7 @@ Res BootAlloc(void **pReturn, BootBlock boot, size_t size, size_t align) /* 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/bt.c b/mps/code/bt.c index a58e501ee52..04093bde0ae 100644 --- a/mps/code/bt.c +++ b/mps/code/bt.c @@ -1,7 +1,7 @@ /* bt.c: BIT TABLES * * $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. * * READERSHIP * @@ -10,6 +10,12 @@ * DESIGN * * .design: see + * + * .aver.critical: The function BTIsResRange (and anything it calls) + * is on the critical path because it is + * called by NailboardIsResRange, which is called for every object in + * a nailboarded segment when the segment is scanned or reclaimed; see + * . */ #include "bt.h" @@ -90,7 +96,9 @@ SRCID(bt, "$Id$"); } else { \ Index actInnerBase = BTIndexAlignUp((base)); \ if (actInnerBase > (limit)) { /* no inner range */ \ - AVER((base) < (limit)); /* caught by small range case */ \ + /* Must have base < limit otherwise caught by small range case */ \ + /* And see .aver.critical. */ \ + AVER_CRITICAL((base) < (limit)); \ bits_action(BTWordIndex((base)), \ BTBitIndex((base)), \ BTBitIndex((limit))); \ @@ -215,7 +223,7 @@ void BTDestroy(BT bt, Arena arena, Count length) * discussed in review.impl.c.bt.4. */ -static Bool BTCheck(BT bt) +Bool BTCheck(BT bt) { AVER(bt != NULL); AVER(AddrIsAligned((Addr)bt, sizeof(Word))); @@ -244,7 +252,7 @@ Size (BTSize)(Count n) Bool (BTGet)(BT t, Index i) { - AVER(BTCheck(t)); + AVERT(BT, t); /* Can't check i */ /* see macro in */ @@ -259,7 +267,7 @@ Bool (BTGet)(BT t, Index i) void (BTSet)(BT t, Index i) { - AVER(BTCheck(t)); + AVERT(BT, t); /* Can't check i */ /* see macro in */ @@ -274,7 +282,7 @@ void (BTSet)(BT t, Index i) void (BTRes)(BT t, Index i) { - AVER(BTCheck(t)); + AVERT(BT, t); /* Can't check i */ /* see macro in */ @@ -289,7 +297,7 @@ void (BTRes)(BT t, Index i) void BTSetRange(BT t, Index base, Index limit) { - AVER(BTCheck(t)); + AVERT(BT, t); AVER(base < limit); #define SINGLE_SET_RANGE(i) \ @@ -311,8 +319,8 @@ void BTSetRange(BT t, Index base, Index limit) Bool BTIsResRange(BT bt, Index base, Index limit) { - AVER(BTCheck(bt)); - AVER(base < limit); + AVERT_CRITICAL(BT, bt); /* See .aver.critical */ + AVER_CRITICAL(base < limit); /* Can't check range of base or limit */ #define SINGLE_IS_RES_RANGE(i) \ @@ -335,7 +343,7 @@ Bool BTIsResRange(BT bt, Index base, Index limit) Bool BTIsSetRange(BT bt, Index base, Index limit) { - AVER(BTCheck(bt)); + AVERT(BT, bt); AVER(base < limit); /* Can't check range of base or limit */ @@ -363,7 +371,7 @@ Bool BTIsSetRange(BT bt, Index base, Index limit) void BTResRange(BT t, Index base, Index limit) { - AVER(BTCheck(t)); + AVERT(BT, t); AVER(base < limit); #define SINGLE_RES_RANGE(i) \ @@ -876,8 +884,8 @@ Bool BTFindShortResRangeHigh(Index *baseReturn, Index *limitReturn, Bool BTRangesSame(BT comparand, BT comparator, Index base, Index limit) { - AVER(BTCheck(comparand)); - AVER(BTCheck(comparator)); + AVERT(BT, comparand); + AVERT(BT, comparator); AVER(base < limit); #define SINGLE_RANGES_SAME(i) \ @@ -912,8 +920,8 @@ Bool BTRangesSame(BT comparand, BT comparator, Index base, Index limit) void BTCopyInvertRange(BT fromBT, BT toBT, Index base, Index limit) { - AVER(BTCheck(fromBT)); - AVER(BTCheck(toBT)); + AVERT(BT, fromBT); + AVERT(BT, toBT); AVER(fromBT != toBT); AVER(base < limit); @@ -947,8 +955,8 @@ void BTCopyInvertRange(BT fromBT, BT toBT, Index base, Index limit) void BTCopyRange(BT fromBT, BT toBT, Index base, Index limit) { - AVER(BTCheck(fromBT)); - AVER(BTCheck(toBT)); + AVERT(BT, fromBT); + AVERT(BT, toBT); AVER(fromBT != toBT); AVER(base < limit); @@ -991,8 +999,8 @@ void BTCopyOffsetRange(BT fromBT, BT toBT, { Index fromBit, toBit; - AVER(BTCheck(fromBT)); - AVER(BTCheck(toBT)); + AVERT(BT, fromBT); + AVERT(BT, toBT); AVER(fromBT != toBT); AVER(fromBase < fromLimit); AVER(toBase < toLimit); @@ -1016,7 +1024,7 @@ Count BTCountResRange(BT bt, Index base, Index limit) Count c = 0; Index bit; - AVER(BTCheck(bt)); + AVERT(BT, bt); AVER(base < limit); for (bit = base; bit < limit; ++bit) @@ -1027,7 +1035,7 @@ Count BTCountResRange(BT bt, Index base, Index limit) /* 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/bt.h b/mps/code/bt.h index 29000b957b8..4876f66715a 100644 --- a/mps/code/bt.h +++ b/mps/code/bt.h @@ -1,7 +1,7 @@ /* bt.h: Bit Table Interface * * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * .source: */ @@ -39,6 +39,7 @@ extern void (BTRes)(BT bt, Index index); END +extern Bool BTCheck(BT bt); extern Res BTCreate(BT *btReturn, Arena arena, Count length); extern void BTDestroy(BT bt, Arena arena, Count length); @@ -76,7 +77,7 @@ extern Count BTCountResRange(BT bt, Index base, Index limit); /* 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/bttest.c b/mps/code/bttest.c index 12a6bd8503f..918463ef4b9 100644 --- a/mps/code/bttest.c +++ b/mps/code/bttest.c @@ -125,7 +125,7 @@ static void get(void) { if (argInRange(0)) { Bool b = (BTGet)(bt, args[0]); - printf(b ? "TRUE\n" : "FALSE\n"); + puts(b ? "TRUE" : "FALSE"); } } @@ -148,7 +148,7 @@ static void isSetRange(void) { if (checkDefaultRange(0)) { Bool b = BTIsSetRange(bt, args[0], args[1]); - printf(b ? "TRUE\n" : "FALSE\n"); + puts(b ? "TRUE" : "FALSE"); } } @@ -157,7 +157,7 @@ static void isResRange(void) { if (checkDefaultRange(0)) { Bool b = BTIsResRange(bt, args[0], args[1]); - printf(b ? "TRUE\n" : "FALSE\n"); + puts(b ? "TRUE" : "FALSE"); } } @@ -312,11 +312,6 @@ static void obeyCommand(const char *command) } -#ifdef MPS_BUILD_MV -/* disable "conversion from int to char" */ -#pragma warning(disable: 4244) -#endif - static void showBT(void) { Index i; char c; @@ -325,7 +320,7 @@ static void showBT(void) { i = 0; while((i < btSize) && (i < 50)) { if (i % 10 == 0) - c = (char)((i / 10) % 10) + '0'; + c = (char)(((i / 10) % 10) + '0'); else c = ' '; putchar(c); @@ -334,7 +329,7 @@ static void showBT(void) { putchar('\n'); i = 0; while((i < btSize) && (i < 50)) { - c = (char)(i % 10) +'0'; + c = (char)((i % 10) +'0'); putchar(c); ++ i; } @@ -353,11 +348,6 @@ static void showBT(void) { putchar('\n'); } -#ifdef MPS_BUILD_MV -/* disable "conversion from int to char" */ -#pragma warning(default: 4244) -#endif - #define testArenaSIZE (((size_t)64)<<20) @@ -374,7 +364,7 @@ extern int main(int argc, char *argv[]) while(1) { char input[100]; printf("bt test> "); - fflush(stdout); + (void)fflush(stdout); if (fgets(input, 100, stdin)) { obeyCommand(input); showBT(); diff --git a/mps/code/buffer.c b/mps/code/buffer.c index c63310980ee..baa553a19a2 100644 --- a/mps/code/buffer.c +++ b/mps/code/buffer.c @@ -1,7 +1,7 @@ /* buffer.c: ALLOCATION BUFFER IMPLEMENTATION * * $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. * * .purpose: This is (part of) the implementation of allocation buffers. * Several macros which also form part of the implementation are in @@ -45,7 +45,7 @@ Bool BufferCheck(Buffer buffer) CHECKU(Arena, buffer->arena); CHECKU(Pool, buffer->pool); CHECKL(buffer->arena == buffer->pool->arena); - CHECKL(RingCheck(&buffer->poolRing)); /* */ + CHECKD_NOSIG(Ring, &buffer->poolRing); CHECKL(BoolCheck(buffer->isMutator)); CHECKL(buffer->fillSize >= 0.0); CHECKL(buffer->emptySize >= 0.0); @@ -205,7 +205,7 @@ static Res BufferInit(Buffer buffer, BufferClass class, AVERT(BufferClass, class); AVERT(Pool, pool); /* The PoolClass should support buffer protocols */ - AVER((pool->class->attr & AttrBUF)); /* .trans.mod */ + AVER(PoolHasAttr(pool, AttrBUF)); arena = PoolArena(pool); /* Initialize the buffer. See for a definition of */ @@ -383,7 +383,7 @@ void BufferFinish(Buffer buffer) pool = BufferPool(buffer); /* The PoolClass should support buffer protocols */ - AVER((pool->class->attr & AttrBUF)); /* .trans.mod */ + AVER(PoolHasAttr(pool, AttrBUF)); AVER(BufferIsReady(buffer)); /* */ @@ -605,7 +605,7 @@ Res BufferReserve(Addr *pReturn, Buffer buffer, Size size, AVER(size > 0); AVER(SizeIsAligned(size, BufferPool(buffer)->alignment)); AVER(BufferIsReady(buffer)); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); /* Is there enough room in the unallocated portion of the buffer to */ /* satisfy the request? If so, just increase the alloc marker and */ @@ -1182,7 +1182,7 @@ static Res bufferTrivDescribe(Buffer buffer, mps_lib_FILE *stream) Bool BufferClassCheck(BufferClass class) { - CHECKL(ProtocolClassCheck(&class->protocol)); + CHECKD(ProtocolClass, &class->protocol); CHECKL(class->name != NULL); /* Should be <=6 char C identifier */ CHECKL(class->size >= sizeof(BufferStruct)); CHECKL(FUNCHECK(class->varargs)); @@ -1220,6 +1220,7 @@ DEFINE_CLASS(BufferClass, class) class->setRankSet = bufferNoSetRankSet; class->reassignSeg = bufferNoReassignSeg; class->sig = BufferClassSig; + AVERT(BufferClass, class); } @@ -1240,7 +1241,7 @@ Bool SegBufCheck(SegBuf segbuf) CHECKS(SegBuf, segbuf); buffer = &segbuf->bufferStruct; - CHECKL(BufferCheck(buffer)); + CHECKD(Buffer, buffer); CHECKL(RankSetCheck(segbuf->rankSet)); if (buffer->mode & BufferModeTRANSITION) { @@ -1250,7 +1251,7 @@ Bool SegBufCheck(SegBuf segbuf) } else { /* The buffer is attached to a segment. */ CHECKL(segbuf->seg != NULL); - CHECKL(SegCheck(segbuf->seg)); + CHECKD(Seg, segbuf->seg); /* To avoid recursive checking, leave it to SegCheck to make */ /* sure the buffer and segment fields tally. */ @@ -1472,6 +1473,7 @@ DEFINE_CLASS(SegBufClass, class) class->rankSet = segBufRankSet; class->setRankSet = segBufSetRankSet; class->reassignSeg = segBufReassignSeg; + AVERT(BufferClass, class); } @@ -1485,7 +1487,7 @@ static void rankBufVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs) args[0].key = MPS_KEY_RANK; args[0].val.rank = va_arg(varargs, Rank); args[1].key = MPS_KEY_ARGS_END; - AVER(ArgListCheck(args)); + AVERT(ArgList, args); } /* rankBufInit -- RankBufClass init method */ @@ -1499,10 +1501,10 @@ static Res rankBufInit(Buffer buffer, Pool pool, ArgList args) AVERT(Buffer, buffer); AVERT(Pool, pool); - AVER(ArgListCheck(args)); + AVERT(ArgList, args); if (ArgPick(&arg, args, MPS_KEY_RANK)) rank = arg.val.rank; - AVER(RankCheck(rank)); + AVERT(Rank, rank); /* Initialize the superclass fields first via next-method call */ super = BUFFER_SUPERCLASS(RankBufClass); @@ -1532,12 +1534,13 @@ DEFINE_CLASS(RankBufClass, class) class->name = "RANKBUF"; class->varargs = rankBufVarargs; class->init = rankBufInit; + AVERT(BufferClass, class); } /* 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/cbs.c b/mps/code/cbs.c index c57c322d267..176a15fef16 100644 --- a/mps/code/cbs.c +++ b/mps/code/cbs.c @@ -1,7 +1,7 @@ /* cbs.c: COALESCING BLOCK STRUCTURE IMPLEMENTATION * * $Id$ - * Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * .intro: This is a portable implementation of coalescing block * structures. @@ -85,6 +85,7 @@ static Bool CBSBlockCheck(CBSBlock block) /* See .enter-leave.simple. */ UNUSED(block); /* Required because there is no signature */ CHECKL(block != NULL); + /* Can't use CHECKD_NOSIG because TreeEMPTY is NULL. */ CHECKL(TreeCheck(cbsBlockTree(block))); /* If the block is in the middle of being deleted, */ @@ -245,9 +246,9 @@ Res CBSInit(CBS cbs, Arena arena, void *owner, Align alignment, AVERT(Arena, arena); AVER(cbs != NULL); - AVER(AlignCheck(alignment)); - AVER(BoolCheck(fastFind)); - AVER(BoolCheck(zoned)); + AVERT(Align, alignment); + AVERT(Bool, fastFind); + AVERT(Bool, zoned); if (ArgPick(&arg, args, CBSBlockPool)) blockPool = arg.val.pool; @@ -915,8 +916,8 @@ Res CBSFindInZones(Range rangeReturn, Range oldRangeReturn, AVER(rangeReturn != NULL); AVER(oldRangeReturn != NULL); AVERT(CBS, cbs); - /* AVER(ZoneSetCheck(zoneSet)); */ - AVER(BoolCheck(high)); + /* AVERT(ZoneSet, zoneSet); */ + AVERT(Bool, high); cbsFind = high ? CBSFindLast : CBSFindFirst; splayFind = high ? SplayFindLast : SplayFindFirst; @@ -1086,7 +1087,7 @@ Res CBSDescribe(CBS cbs, mps_lib_FILE *stream) /* 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/check.h b/mps/code/check.h index d4abc0fd80a..825e15c7e48 100644 --- a/mps/code/check.h +++ b/mps/code/check.h @@ -1,7 +1,7 @@ /* check.h: ASSERTION 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. * * .aver: This header defines a family of AVER and NOTREACHED macros. @@ -52,7 +52,7 @@ #define ASSERT(cond, condstring) \ BEGIN \ if (cond) NOOP; else \ - mps_lib_assert_fail(__FILE__ , __LINE__, (condstring)); \ + mps_lib_assert_fail(MPS_FILE, __LINE__, (condstring)); \ END #define ASSERT_TYPECHECK(type, val) \ @@ -85,9 +85,6 @@ * * TODO: Should also allow the check level variable to come from an * environment variable. - * - * TODO: CheckLevelDEEP asserts on arena creation with bootstrapping - * problems. It clearly hasn't been tried for a while. RB 2012-09-01 */ enum { @@ -327,7 +324,7 @@ extern unsigned CheckLevel; /* 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/clock.h b/mps/code/clock.h index 5e103ff4393..253f7a5e0e4 100644 --- a/mps/code/clock.h +++ b/mps/code/clock.h @@ -1,6 +1,6 @@ /* clock.h -- Fast clocks and timers * - * Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * $Id$ */ @@ -15,10 +15,6 @@ * * On platforms that support it, we want to stamp events with a very cheap * and fast high-resolution timer. - * - * TODO: This is a sufficiently complicated nest of ifdefs that it should - * be quarantined in its own header with KEEP OUT signs attached. - * RB 2012-09-11 */ /* Microsoft C provides an intrinsic for the Intel rdtsc instruction. @@ -49,7 +45,7 @@ typedef union EventClockUnion { using Microsoft Visual Studio 6 because of support for CodeView debugging information. */ -#include /* KILL IT WITH FIRE! */ +#include "mpswin.h" /* KILL IT WITH FIRE! */ #define EVENT_CLOCK(lvalue) \ BEGIN \ @@ -169,7 +165,7 @@ typedef mps_clock_t EventClock; /* 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/comm.gmk b/mps/code/comm.gmk index 64ce520b560..38ae5e64a7c 100644 --- a/mps/code/comm.gmk +++ b/mps/code/comm.gmk @@ -204,9 +204,11 @@ TESTLIBDEP = $(TESTLIB:%.c=$(PFM)/$(VARIETY)/%.d) FMTDYOBJ = $(FMTDY:%.c=$(PFM)/$(VARIETY)/%.o) FMTDYDEP = $(FMTDY:%.c=$(PFM)/$(VARIETY)/%.d) FMTDYTSTOBJ = $(FMTDYTST:%.c=$(PFM)/$(VARIETY)/%.o) +FMTDYTSTDEP = $(FMTDYTST:%.c=$(PFM)/$(VARIETY)/%.d) FMTHETSTOBJ = $(FMTHETST:%.c=$(PFM)/$(VARIETY)/%.o) FMTHETSTDEP = $(FMTHETST:%.c=$(PFM)/$(VARIETY)/%.d) -FMTSCMTSTOBJ = $(FMTSCM:%.c=$(PFM)/$(VARIETY)/%.o) +FMTSCMOBJ = $(FMTSCM:%.c=$(PFM)/$(VARIETY)/%.o) +FMTSCMDEP = $(FMTSCM:%.c=$(PFM)/$(VARIETY)/%.d) PLINTHOBJ = $(PLINTH:%.c=$(PFM)/$(VARIETY)/%.o) PLINTHDEP = $(PLINTH:%.c=$(PFM)/$(VARIETY)/%.d) EVENTPROCOBJ = $(EVENTPROC:%.c=$(PFM)/$(VARIETY)/%.o) @@ -377,7 +379,7 @@ $(PFM)/$(VARIETY)/abqtest: $(PFM)/$(VARIETY)/abqtest.o \ $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a $(PFM)/$(VARIETY)/airtest: $(PFM)/$(VARIETY)/airtest.o \ - $(FMTSCMTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a + $(FMTSCMOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a $(PFM)/$(VARIETY)/amcss: $(PFM)/$(VARIETY)/amcss.o \ $(FMTDYTSTOBJ) $(TESTLIBOBJ) $(PFM)/$(VARIETY)/mps.a @@ -572,9 +574,20 @@ include $(PFM)/$(VARIETY)/mps.d else # %%PART: When adding a new part, add the dependency file macro for the new # part here. -include $(MPMDEP) $(AMSDEP) $(AMCDEP) $(LODEP) \ - $(AWLDEP) $(POOLNDEP) $(TESTLIBDEP) $(FMTDYDEP) $(FMTHETSTDEP) \ - $(PLINTHDEP) $(EVENTPROCDEP) +include \ + $(MPMDEP) \ + $(AMCDEP) \ + $(AMSDEP) \ + $(AWLDEP) \ + $(EVENTPROCDEP) \ + $(FMTDYDEP) \ + $(FMTDYTSTDEP) \ + $(FMTHETSTDEP) \ + $(FMTSCMDEP) \ + $(LODEP) \ + $(PLINTHDEP) \ + $(POOLNDEP) \ + $(TESTLIBDEP) endif endif diff --git a/mps/code/commpost.nmk b/mps/code/commpost.nmk index 6c9966efe03..d6492fe3d67 100644 --- a/mps/code/commpost.nmk +++ b/mps/code/commpost.nmk @@ -27,7 +27,7 @@ $(ALL_TARGETS) $(OPTIONAL_TARGETS): clean: $(ECHO) $(PFM): $@ - -echo y | rmdir/s $(PFM) + if exist $(PFM) rmdir /q /s $(PFM) # target target # %%VARIETY: When adding a new variety, optionally, add a recursive make @@ -96,8 +96,8 @@ $(PFM)\cool\mps.lib: \ $(MPMOBJ) $(AMCOBJ) $(AMSOBJ) $(AWLOBJ) $(LOOBJ) $(SNCOBJ) \ $(MVFFOBJ) $(PLINTHOBJ) $(POOLNOBJ) $(ECHO) $@ - cl /c $(CFLAGS) /Fd$(PFM)\$(VARIETY)\ /Fo$(PFM)\$(VARIETY)\version.o version.c - $(LIBMAN) $(LIBFLAGS) /OUT:$@ $** $(PFM)\$(VARIETY)\version.o + $(CC) /c $(CFLAGS) /Fo$(PFM)\$(VARIETY)\version.obj version.c + $(LIBMAN) $(LIBFLAGS) /OUT:$@ $** $(PFM)\$(VARIETY)\version.obj # OTHER GENUINE TARGETS @@ -273,13 +273,13 @@ $(PFM)\$(VARIETY)\mpseventsql.obj: $(PFM)\$(VARIETY)\eventsql.obj $(ECHO) $@ @if not exist $(PFM) mkdir $(PFM) @if not exist $(PFM)\$(VARIETY) mkdir $(PFM)\$(VARIETY) - cl /c $(CFLAGS) /Fd$(PFM)\$(VARIETY)\ /Fo$@ $< + $(CC) /c $(CFLAGS) /Fo$@ $< $(PFM)\$(VARIETY)\sqlite3.obj: $(ECHO) $@ @if not exist $(PFM) mkdir $(PFM) @if not exist $(PFM)\$(VARIETY) mkdir $(PFM)\$(VARIETY) - cl /c $(CFLAGSSQL) /Fd$(PFM)\$(VARIETY)\ /Fo$@ sqlite3.c + $(CC) /c $(CFLAGSSQL) /Fo$@ sqlite3.c {}.asm{$(PFM)\$(VARIETY)}.obj: $(ECHO) $@ @@ -301,7 +301,7 @@ $(PFM)\$(VARIETY)\sqlite3.obj: {$(PFM)\$(VARIETY)}.obj{$(PFM)\$(VARIETY)}.exe: $(ECHO) $@ - $(LINKER) $(LINKFLAGS) /PDB:$*.pdb /OUT:$@ $(**) + $(LINKER) $(LINKFLAGS) /OUT:$@ $(**) # C. COPYRIGHT AND LICENSE diff --git a/mps/code/commpre.nmk b/mps/code/commpre.nmk index e86cab1441d..75cead3ef26 100644 --- a/mps/code/commpre.nmk +++ b/mps/code/commpre.nmk @@ -1,7 +1,7 @@ # commpre.nmk: FIRST COMMON FRAGMENT FOR PLATFORMS USING NMAKE -*- makefile -*-1 # # $Id$ -# Copyright (c) 2001 Ravenbrook Limited. See end of file for license. +# Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. # # DESCRIPTION # @@ -242,20 +242,15 @@ ECHO = echo # C FLAGS -# /MD means compile for multi-threaded environment with separate C library DLL. -# /MT means compile for multi-threaded environment. -# /ML means compile for single-threaded environment. -# A 'd' at the end means compile for debugging. - CFLAGSTARGETPRE = CFLAGSTARGETPOST = -CRTFLAGSHOT = /MT -CRTFLAGSCOOL = /MTd -LINKFLAGSHOT = libcmt.lib -LINKFLAGSCOOL = libcmtd.lib +CRTFLAGSHOT = +CRTFLAGSCOOL = +LINKFLAGSHOT = +LINKFLAGSCOOL = CFLAGSSQLPRE = /nologo $(PFMDEFS) -CFLAGSCOMMONPRE = /nologo /W4 /WX $(PFMDEFS) $(CFLAGSTARGETPRE) +CFLAGSCOMMONPRE = /nologo $(PFMDEFS) $(CFLAGSTARGETPRE) CFLAGSSQLPOST = CFLAGSCOMMONPOST = $(CFLAGSTARGETPOST) @@ -270,7 +265,7 @@ CFLAGSHOT = /O2 /DNDEBUG # building a DLL, mpsdy.dll, the linker step will fail (error LNK2001: # unresolved external symbol __chkesp). See # http://support.microsoft.com/kb/q191669/ -CFLAGSCOOL = /Od +CFLAGSCOOL = CFLAGSINTERNAL = /Zi CFLAGSEXTERNAL = @@ -303,7 +298,7 @@ LFCOOL = $(LINKFLAGSCOOL) $(LINKFLAGSINTERNAL) # %%VARIETY: When adding a new variety, define a macro containing the flags # for the new variety LIBMAN = lib # can't call this LIB - it screws the environment -LIBFLAGSCOMMON = /nologo +LIBFLAGSCOMMON = LIBFLAGSRASH = LIBFLAGSHOT = @@ -322,7 +317,7 @@ LIBFLAGSCOOL = # 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/config.h b/mps/code/config.h index 702ed5a6723..3e6158c1c7c 100644 --- a/mps/code/config.h +++ b/mps/code/config.h @@ -1,7 +1,7 @@ /* config.h: MPS CONFIGURATION * * $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. * * PURPOSE @@ -204,56 +204,77 @@ #include "mpstd.h" /* Suppress Visual C warnings at warning level 4, */ -/* see mail.richard.1997-09-25.13-26. */ +/* see mail.richard.1997-09-25.13-26 and job003715. */ /* Essentially the same settings are done in testlib.h. */ #ifdef MPS_BUILD_MV -/* "unreferenced inline function has been removed" (windows.h) */ -#pragma warning(disable: 4514) - /* "constant conditional" (MPS_END) */ #pragma warning(disable: 4127) -/* "unreachable code" (ASSERT, if cond is constantly true). */ -#pragma warning(disable: 4702) - -/* "expression evaluates to a function which is missing an argument list" */ -#pragma warning(disable: 4550) - -/* "local variable is initialized but not referenced" */ -#pragma warning(disable: 4189) - -/* "not all control paths return a value" */ -#pragma warning(disable: 4715) - -/* MSVC 2.0 generates a warning when using NOCHECK or UNUSED */ -#ifdef _MSC_VER -#if _MSC_VER < 1000 -#pragma warning(disable: 4705) -#endif -#else /* _MSC_VER */ -#error "Expected _MSC_VER to be defined for builder.mv" -#endif /* _MSC_VER */ - - -/* Non-checking varieties give many spurious warnings because parameters - * are suddenly unused, etc. We aren't interested in these - */ - -#if defined(AVER_AND_CHECK_NONE) - -/* "unreferenced formal parameter" */ -#pragma warning(disable: 4100) - -/* "unreferenced local function has been removed" */ -#pragma warning(disable: 4505) - -#endif /* AVER_AND_CHECK_NONE */ - #endif /* MPS_BUILD_MV */ +/* Suppress Pelles C warnings at warning level 2 */ +/* Some of the same settings are done in testlib.h. */ + +#ifdef MPS_BUILD_PC + +/* "Unreachable code" (AVER, if condition is constantly true). */ +#pragma warn(disable: 2154) + +/* "Consider changing type to 'size_t' for loop variable" */ +#pragma warn(disable: 2804) + +#endif /* MPS_BUILD_PC */ + + +/* MPS_FILE -- expands to __FILE__ in nested macros */ + +#ifdef MPS_BUILD_PC + +/* Pelles C loses definition of __FILE__ in deeply nested macro + * expansions. See + */ +#define MPS_FILE "<__FILE__ unavailable in " MPS_PF_STRING ">" + +#else + +#define MPS_FILE __FILE__ + +#endif + + +/* Function attributes */ +/* Some of these are also defined in testlib.h */ + +/* Attribute for functions that take a printf-like format argument, so + * that the compiler can check the format specifiers against the types + * of the arguments. + * GCC: + * Clang: + */ +#if defined(MPS_BUILD_GC) || defined(MPS_BUILD_LL) +#define ATTRIBUTE_FORMAT(ARGLIST) __attribute__((__format__ ARGLIST)) +#else +#define ATTRIBUTE_FORMAT(ARGLIST) +#endif + +/* Attribute for functions that should not be instrumented by Clang's + * address sanitizer. + * + */ +#if defined(MPS_BUILD_LL) +#if __has_feature(address_sanitizer) +#define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((__no_sanitize_address__)) +#else +#define ATTRIBUTE_NO_SANITIZE_ADDRESS +#endif +#else +#define ATTRIBUTE_NO_SANITIZE_ADDRESS +#endif + + /* EPVMDefaultSubsequentSegSIZE is a default for the alignment of * subsequent segments (non-initial at each save level) in EPVM. See * design.mps.poolepvm.arch.segment.size. @@ -284,6 +305,13 @@ #define FMT_CLASS_DEFAULT (&FormatDefaultClass) +/* Pool AMC Configuration -- see */ + +#define AMC_INTERIOR_DEFAULT TRUE +/* AMC treats segments of this many pages (or more) as "Large" */ +#define AMCLargeSegPAGES ((Count)8) + + /* Pool AMS Configuration -- see */ #define AMS_SUPPORT_AMBIGUOUS_DEFAULT FALSE @@ -293,6 +321,10 @@ /* Pool AWL Configuration -- see */ #define AWL_GEN_DEFAULT 0 +#define AWL_HAVE_SEG_SA_LIMIT TRUE +#define AWL_SEG_SA_LIMIT 200 /* TODO: Improve guesswork with measurements */ +#define AWL_HAVE_TOTAL_SA_LIMIT FALSE +#define AWL_TOTAL_SA_LIMIT 0 /* Pool LO Configuration -- see */ @@ -370,12 +402,10 @@ /* Stack configuration */ -/* Currently StackProbe has a useful implementation only on - * Intel platforms and only when using Microsoft build tools (builder.mv) - */ -#if defined(MPS_ARCH_I3) && defined(MPS_BUILD_MV) +/* Currently StackProbe has a useful implementation only on Windows. */ +#if defined(MPS_OS_W3) && defined(MPS_ARCH_I3) #define StackProbeDEPTH ((Size)500) -#elif defined(MPS_PF_W3I6MV) +#elif defined(MPS_OS_W3) && defined(MPS_ARCH_I6) #define StackProbeDEPTH ((Size)500) #else #define StackProbeDEPTH ((Size)0) @@ -556,20 +586,6 @@ #define ARENA_INIT_SPARE_COMMIT_LIMIT ((Size)10uL*1024uL*1024uL) -/* Pool Class AMC configuration */ - -/* AMC treats segments of this many pages (or more) as "Large" */ -#define AMCLargeSegPAGES ((Count)8) - - -/* Pool Class AWL configuration -- see poolawl.c for usage */ - -#define AWL_HAVE_SEG_SA_LIMIT TRUE -#define AWL_SEG_SA_LIMIT 200 /* TODO: Improve guesswork with measurements */ -#define AWL_HAVE_TOTAL_SA_LIMIT FALSE -#define AWL_TOTAL_SA_LIMIT 0 - - /* Default chain for GC pools * * TODO: The default should be to measure liveness and make sensible @@ -588,7 +604,7 @@ /* 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/dbgpool.c b/mps/code/dbgpool.c index ab0bc7d3cfd..77c1d6eaf40 100644 --- a/mps/code/dbgpool.c +++ b/mps/code/dbgpool.c @@ -1,7 +1,7 @@ /* dbgpool.c: POOL DEBUG MIXIN * * $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. * * .source: design.mps.object-debug @@ -34,8 +34,6 @@ typedef tagStruct *Tag; /* tag init methods: copying the user-supplied data into the tag */ -#define TagInitMethodCheck(f) FUNCHECK(f) - static void TagTrivInit(void* tag, va_list args) { UNUSED(tag); UNUSED(args); @@ -75,7 +73,7 @@ Bool PoolDebugMixinCheck(PoolDebugMixin debug) /* Nothing to check about freeTemplate */ /* Nothing to check about freeSize */ if (debug->tagInit != NULL) { - CHECKL(TagInitMethodCheck(debug->tagInit)); + CHECKL(FUNCHECK(debug->tagInit)); /* Nothing to check about tagSize */ CHECKD(Pool, debug->tagPool); CHECKL(COMPATTYPE(Addr, void*)); /* tagPool relies on this */ @@ -573,7 +571,7 @@ static void TagWalk(Pool pool, ObjectsStepMethod step, void *p) AVERT(PoolDebugMixin, debug); node = SplayTreeFirst(&debug->index); - while (node != NULL) { + while (node != TreeEMPTY) { Tag tag = TagOfTree(node); step(tag->addr, tag->size, NULL, pool, &tag->userdata, p); @@ -691,7 +689,7 @@ void PoolClassMixInDebug(PoolClass class) /* 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/event.c b/mps/code/event.c index 05e307cfc12..2e7468c3752 100644 --- a/mps/code/event.c +++ b/mps/code/event.c @@ -200,7 +200,7 @@ void EventInit(void) AVER((EventKind)Event##name##Kind < EventKindLIMIT); \ EVENT_##name##_PARAMS(EVENT_PARAM_CHECK, name) - EVENT_LIST(EVENT_CHECK, X) + EVENT_LIST(EVENT_CHECK, X); /* Ensure that no event can be larger than the maximum event size. */ AVER(EventBufferSIZE <= EventSizeMAX); @@ -416,7 +416,7 @@ void EventDump(mps_lib_FILE *stream) /* This can happen if there's a backtrace very early in the life of the MPS, and will cause an access violation if we continue. */ if (!eventInited) { - WriteF(stream, "No events\n", NULL); + (void)WriteF(stream, "No events\n", NULL); return; } diff --git a/mps/code/event.h b/mps/code/event.h index 3e1463527ba..11884d30d6c 100644 --- a/mps/code/event.h +++ b/mps/code/event.h @@ -87,7 +87,7 @@ extern Word EventKindControl; size = offsetof(Event##name##Struct, f1) + _string_len + sizeof('\0'); \ EVENT_BEGIN(name, size) \ _event->f0 = (p0); \ - mps_lib_memcpy(_event->f1, (string), _string_len); \ + (void)mps_lib_memcpy(_event->f1, (string), _string_len); \ _event->f1[_string_len] = '\0'; \ EVENT_END(name, size); \ END diff --git a/mps/code/eventcnv.c b/mps/code/eventcnv.c index 7cca6846a49..355b6efa2a2 100644 --- a/mps/code/eventcnv.c +++ b/mps/code/eventcnv.c @@ -1,5 +1,5 @@ /* eventcnv.c: Simple event log converter - * Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * This is a command-line tool that converts a binary format telemetry output * stream from the MPS into a more-portable textual format. @@ -46,12 +46,6 @@ #include /* for strcmp */ #include "mpstd.h" -#ifdef MPS_BUILD_MV -/* MSVC warning 4996 = stdio / C runtime 'unsafe' */ -/* Objects to: strncpy, sscanf, fopen. See job001934. */ -#pragma warning( disable : 4996 ) -#endif - #define DEFAULT_TELEMETRY_FILENAME "mpsio.log" #define TELEMETRY_FILENAME_ENVAR "MPS_TELEMETRY_FILENAME" @@ -62,18 +56,20 @@ static const char *prog; /* program name */ /* fevwarn -- flush stdout, write message to stderr */ +ATTRIBUTE_FORMAT((printf, 2, 0)) static void fevwarn(const char *prefix, const char *format, va_list args) { - fflush(stdout); /* sync */ - fprintf(stderr, "%s: %s @", prog, prefix); - EVENT_CLOCK_PRINT(stderr, eventTime); - fprintf(stderr, " "); - vfprintf(stderr, format, args); - fprintf(stderr, "\n"); + (void)fflush(stdout); /* sync */ + (void)fprintf(stderr, "%s: %s @", prog, prefix); + (void)EVENT_CLOCK_PRINT(stderr, eventTime); + (void)fprintf(stderr, " "); + (void)vfprintf(stderr, format, args); + (void)fprintf(stderr, "\n"); } /* evwarn -- flush stdout, warn to stderr */ +ATTRIBUTE_FORMAT((printf, 1, 2)) static void evwarn(const char *format, ...) { va_list args; @@ -85,6 +81,7 @@ static void evwarn(const char *format, ...) /* everror -- flush stdout, message to stderr, exit */ +ATTRIBUTE_FORMAT((printf, 1, 2)) static void everror(const char *format, ...) { va_list args; @@ -100,10 +97,9 @@ static void everror(const char *format, ...) static void usage(void) { - fprintf(stderr, - "Usage: %s [-f logfile] [-h]\n" - "See \"Telemetry\" in the reference manual for instructions.\n", - prog); + (void)fprintf(stderr, "Usage: %s [-f logfile] [-h]\n" + "See \"Telemetry\" in the reference manual for instructions.\n", + prog); } @@ -268,9 +264,12 @@ static void readLog(FILE *stream) event->EventInit.f5, MPS_WORD_WIDTH); break; + default: + /* No special treatment needed. */ + break; } - EVENT_CLOCK_PRINT(stdout, eventTime); + (void)EVENT_CLOCK_PRINT(stdout, eventTime); printf(" %4X", (unsigned)code); switch (code) { @@ -286,7 +285,7 @@ static void readLog(FILE *stream) } putchar('\n'); - fflush(stdout); + (void)fflush(stdout); } /* while(!feof(input)) */ } @@ -332,7 +331,7 @@ int main(int argc, char *argv[]) /* 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/eventdef.h b/mps/code/eventdef.h index cc3b3d61c21..4ce313dcfc8 100644 --- a/mps/code/eventdef.h +++ b/mps/code/eventdef.h @@ -1,7 +1,7 @@ /* -- Event Logging Definitions * * $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. * * .source: * @@ -31,14 +31,13 @@ * the median version when changing an existing event, * and the major version when changing the format of the event file. * - * TODO: These should go into a header that appears at the start of a - * telemetry stream, but they aren't currently used. Keep updating them - * anyway. RB 2012-09-07 + * These are passed as parameters to the EventInit event at the start + * of a telemetry stream, allowing that stream to be identified. */ #define EVENT_VERSION_MAJOR ((unsigned)1) #define EVENT_VERSION_MEDIAN ((unsigned)1) -#define EVENT_VERSION_MINOR ((unsigned)6) +#define EVENT_VERSION_MINOR ((unsigned)7) /* EVENT_LIST -- list of event types and general properties @@ -192,7 +191,8 @@ /* new events for performance analysis of large heaps. */ \ EVENT(X, TraceCondemnZones , 0x0083, TRUE, Trace) \ EVENT(X, ArenaGenZoneAdd , 0x0084, TRUE, Arena) \ - EVENT(X, ArenaUseFreeZone , 0x0085, TRUE, Arena) + EVENT(X, ArenaUseFreeZone , 0x0085, TRUE, Arena) \ + /* EVENT(X, ArenaBlacklistZone , 0x0086, TRUE, Arena) */ /* Remember to update EventNameMAX and EventCodeMAX above! @@ -745,7 +745,7 @@ /* 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/eventrep.c b/mps/code/eventrep.c index f216e51c70a..969d8adcb67 100644 --- a/mps/code/eventrep.c +++ b/mps/code/eventrep.c @@ -31,7 +31,7 @@ #include "mpstd.h" -#ifdef MPS_PF_W3I6MV +#if defined(MPS_OS_W3) && defined(MPS_ARCH_I6) #define PRIuLONGEST "llu" #define PRIXPTR "016llX" typedef unsigned long long ulongest_t; @@ -116,6 +116,7 @@ typedef struct apRepStruct *apRep; /* error -- error signalling */ +ATTRIBUTE_FORMAT((printf, 1, 2)) static void error(const char *format, ...) { va_list args; diff --git a/mps/code/eventsql.c b/mps/code/eventsql.c index 0fa36dea739..46bfa688a9b 100644 --- a/mps/code/eventsql.c +++ b/mps/code/eventsql.c @@ -2,7 +2,7 @@ * * $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. * * This is a command-line tool that imports events from a text-format * MPS telemetry file into a SQLite database file. @@ -86,9 +86,6 @@ #define DEFAULT_DATABASE_NAME "mpsevent.db" #ifdef MPS_BUILD_MV -/* MSVC warning 4996 = stdio / C runtime 'unsafe' */ -/* Objects to: getenv, sprintf. See job001934. */ -#pragma warning( disable : 4996 ) #define strtoll _strtoi64 #endif @@ -113,6 +110,7 @@ unsigned int verbosity = 0; #define LOG_SELDOM 3 #define LOG_RARELY 4 +ATTRIBUTE_FORMAT((printf, 2, 0)) static void vlog(unsigned int level, const char *format, va_list args) { if (level <= verbosity) { @@ -123,6 +121,7 @@ static void vlog(unsigned int level, const char *format, va_list args) } } +ATTRIBUTE_FORMAT((printf, 2, 3)) static void evlog(unsigned int level, const char *format, ...) { va_list args; @@ -131,6 +130,7 @@ static void evlog(unsigned int level, const char *format, ...) va_end(args); } +ATTRIBUTE_FORMAT((printf, 1, 2)) static void error(const char *format, ...) { va_list args; @@ -452,7 +452,7 @@ static void registerLogFile(sqlite3 *db, name = sqlite3_column_text(statement, 0); logSerial = sqlite3_column_int64(statement, 1); completed = sqlite3_column_int64(statement, 2); - evlog(force ? LOG_OFTEN : LOG_ALWAYS, "Log file matching '%s' already in event_log, named \"%s\" (serial %lu, completed %lu).", + evlog(force ? LOG_OFTEN : LOG_ALWAYS, "Log file matching '%s' already in event_log, named \"%s\" (serial %llu, completed %llu).", filename, name, logSerial, completed); if (force) { evlog(LOG_OFTEN, "Continuing anyway because -f specified."); @@ -486,7 +486,7 @@ static void registerLogFile(sqlite3 *db, if (res != SQLITE_DONE) sqlite_error(res, db, "insert into event_log failed."); logSerial = sqlite3_last_insert_rowid(db); - evlog(LOG_SOMETIMES, "Log file %s added to event_log with serial %lu", + evlog(LOG_SOMETIMES, "Log file %s added to event_log with serial %llu", filename, logSerial); finalizeStatement(db, statement); } @@ -508,7 +508,7 @@ static void logFileCompleted(sqlite3 *db, res = sqlite3_step(statement); if (res != SQLITE_DONE) sqlite_error(res, db, "insert into event_log failed."); - evlog(LOG_SOMETIMES, "Marked in event_log: %lu events", completed); + evlog(LOG_SOMETIMES, "Marked in event_log: %llu events", completed); finalizeStatement(db, statement); } @@ -864,7 +864,7 @@ static int64 readLog(FILE *input, /* this macro sets statement and last_index */ EVENT_LIST(EVENT_TYPE_WRITE_SQL, X); default: - error("Event %llu has Unknown event code %d", eventCount, code); + error("Event %llu has Unknown event code %ld", eventCount, code); } /* bind the fields we store for every event */ \ res = sqlite3_bind_int64(statement, last_index+1, logSerial); @@ -951,7 +951,7 @@ int main(int argc, char *argv[]) makeTables(db); fillGlueTables(db); count = writeEventsToSQL(db); - evlog(LOG_ALWAYS, "Imported %llu events from %s to %s, serial %lu.", + evlog(LOG_ALWAYS, "Imported %llu events from %s to %s, serial %llu.", count, logFileName, databaseName, logSerial); if (runTests) { @@ -965,7 +965,7 @@ int main(int argc, char *argv[]) /* COPYRIGHT AND LICENSE * - * Copyright (c) 2012-2013 Ravenbrook Limited . + * Copyright (c) 2012-2014 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/eventtxt.c b/mps/code/eventtxt.c index 3971d0e84da..5b7f7ab1312 100644 --- a/mps/code/eventtxt.c +++ b/mps/code/eventtxt.c @@ -2,7 +2,7 @@ * * $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. * * This is a command-line tool that converts events from a text-format * MPS telemetry file into a more human-readable format. @@ -39,41 +39,34 @@ #include #include -#ifdef MPS_BUILD_MV -/* MSVC warning 4996 = stdio / C runtime 'unsafe' */ -/* Objects to: strncpy, sscanf, fopen. See job001934. */ -#pragma warning( disable : 4996 ) -#endif - static const char *prog; /* program name */ static const char *logFileName = NULL; /* everror -- error signalling */ +ATTRIBUTE_FORMAT((printf, 1, 2)) static void everror(const char *format, ...) { va_list args; - fflush(stdout); /* sync */ - fprintf(stderr, "%s: ", prog); + (void)fflush(stdout); /* sync */ + (void)fprintf(stderr, "%s: ", prog); va_start(args, format); - vfprintf(stderr, format, args); - fprintf(stderr, "\n"); + (void)vfprintf(stderr, format, args); + (void)fprintf(stderr, "\n"); va_end(args); exit(EXIT_FAILURE); } static void usage(void) { - fprintf(stderr, - "Usage: %s [-l ]\n", - prog); + (void)fprintf(stderr, "Usage: %s [-l ]\n", prog); } static void usageError(void) { - usage(); - everror("Bad usage"); + usage(); + everror("Bad usage"); } /* parseArgs -- parse command line arguments */ @@ -289,7 +282,7 @@ static void recordLabel(char *p) address = parseHex(&p); if (address > (Word)-1) { - printf("label address too large!"); + (void)printf("label address too large!"); return; } @@ -440,24 +433,27 @@ static void readLog(FILE *input) if ((major != EVENT_VERSION_MAJOR) || (median != EVENT_VERSION_MEDIAN) || (minor != EVENT_VERSION_MINOR)) { - fprintf(stderr, "Event log version does not match: %d.%d.%d vs %d.%d.%d\n", - (int)major, (int)median, (int)minor, - EVENT_VERSION_MAJOR, - EVENT_VERSION_MEDIAN, - EVENT_VERSION_MINOR); + (void)fprintf(stderr, "Event log version does not match: " + "%d.%d.%d vs %d.%d.%d\n", + (int)major, (int)median, (int)minor, + EVENT_VERSION_MAJOR, + EVENT_VERSION_MEDIAN, + EVENT_VERSION_MINOR); } if (maxCode > EventCodeMAX) { - fprintf(stderr, "Event log may contain unknown events with codes from %d to %d\n", - EventCodeMAX+1, (int)maxCode); + (void)fprintf(stderr, "Event log may contain unknown events " + "with codes from %d to %d\n", + EventCodeMAX+1, (int)maxCode); } if (wordWidth > MPS_WORD_WIDTH) { int newHexWordWidth = (int)((wordWidth + 3) / 4); if (newHexWordWidth > hexWordWidth) { - fprintf(stderr, - "Event log word width is greater than on current platform;" - "previous values may be printed too narrowly.\n"); + (void)fprintf(stderr, + "Event log word width is greater than on current " + "platform; previous values may be printed too " + "narrowly.\n"); } hexWordWidth = newHexWordWidth; } @@ -500,7 +496,7 @@ int main(int argc, char *argv[]) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2012-2013 Ravenbrook Limited . + * Copyright (C) 2012-2014 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/exposet0.c b/mps/code/exposet0.c index 739ccac1e6a..11e78ad29cb 100644 --- a/mps/code/exposet0.c +++ b/mps/code/exposet0.c @@ -185,7 +185,8 @@ static void *test(void *arg, size_t s) if (collections != c) { collections = c; - printf("\nCollection %lu started, %lu objects.\n", c, objs); + printf("\nCollection %"PRIuLONGEST" started, %lu objects.\n", + (ulongest_t)c, objs); report(arena); for (i = 0; i < exactRootsCOUNT; ++i) { @@ -231,7 +232,7 @@ static void *test(void *arg, size_t s) if (objs % 1024 == 0) { report(arena); putchar('.'); - fflush(stdout); + (void)fflush(stdout); } ++objs; diff --git a/mps/code/expt825.c b/mps/code/expt825.c index e18905061cf..5947a0cff68 100644 --- a/mps/code/expt825.c +++ b/mps/code/expt825.c @@ -86,7 +86,8 @@ static void register_numbered_tree(mps_word_t tree, mps_arena_t arena) { /* don't finalize ints */ if ((tree & 1) == 0) { - mps_finalize(arena, (mps_addr_t *)&tree); + mps_addr_t addr = (void *)tree; + die(mps_finalize(arena, &addr), "mps_finalize"); register_numbered_tree(DYLAN_VECTOR_SLOT(tree, 0), arena); register_numbered_tree(DYLAN_VECTOR_SLOT(tree, 1), arena); } @@ -124,8 +125,8 @@ static void register_indirect_tree(mps_word_t tree, mps_arena_t arena) { /* don't finalize ints */ if ((tree & 1) == 0) { - mps_word_t indirect = DYLAN_VECTOR_SLOT(tree,2); - mps_finalize(arena, (mps_addr_t *)&indirect); + mps_addr_t indirect = (void *)DYLAN_VECTOR_SLOT(tree,2); + die(mps_finalize(arena, &indirect), "mps_finalize"); register_indirect_tree(DYLAN_VECTOR_SLOT(tree, 0), arena); register_indirect_tree(DYLAN_VECTOR_SLOT(tree, 1), arena); } @@ -186,7 +187,7 @@ static void *test(void *arg, size_t s) (mps_collections(arena) < collectionCOUNT)) { mps_word_t final_this_time = 0; printf("Collecting..."); - fflush(stdout); + (void)fflush(stdout); die(mps_arena_collect(arena), "collect"); printf(" Done.\n"); while (mps_message_poll(arena)) { @@ -202,8 +203,10 @@ static void *test(void *arg, size_t s) testlib_unused(obj); } finals += final_this_time; - printf("%lu objects finalized: total %lu of %lu\n", - final_this_time, finals, object_count); + printf("%"PRIuLONGEST" objects finalized: total %"PRIuLONGEST + " of %"PRIuLONGEST"\n", + (ulongest_t)final_this_time, (ulongest_t)finals, + (ulongest_t)object_count); } object_count = 0; @@ -227,7 +230,7 @@ static void *test(void *arg, size_t s) (mps_collections(arena) < collectionCOUNT)) { mps_word_t final_this_time = 0; printf("Collecting..."); - fflush(stdout); + (void)fflush(stdout); die(mps_arena_collect(arena), "collect"); printf(" Done.\n"); while (mps_message_poll(arena)) { @@ -243,8 +246,10 @@ static void *test(void *arg, size_t s) testlib_unused(obj); } finals += final_this_time; - printf("%lu objects finalized: total %lu of %lu\n", - final_this_time, finals, object_count); + printf("%"PRIuLONGEST" objects finalized: total %"PRIuLONGEST + " of %"PRIuLONGEST"\n", + (ulongest_t)final_this_time, (ulongest_t)finals, + (ulongest_t)object_count); } mps_ap_destroy(ap); diff --git a/mps/code/fbmtest.c b/mps/code/fbmtest.c index 905e90d0a93..2b6437c216d 100644 --- a/mps/code/fbmtest.c +++ b/mps/code/fbmtest.c @@ -83,13 +83,13 @@ static Index (indexOfAddr)(FBMState state, Addr a) static void describe(FBMState state) { switch (state->type) { case FBMTypeCBS: - CBSDescribe(state->the.cbs, mps_lib_get_stdout()); + die(CBSDescribe(state->the.cbs, mps_lib_get_stdout()), "CBSDescribe"); break; case FBMTypeFreelist: - FreelistDescribe(state->the.fl, mps_lib_get_stdout()); + die(FreelistDescribe(state->the.fl, mps_lib_get_stdout()), "FreelistDescribe"); break; default: - fail(); + cdie(0, "invalid state->type"); break; } } @@ -157,7 +157,7 @@ static void check(FBMState state) FreelistIterate(state->the.fl, checkFLCallback, (void *)&closure, 0); break; default: - fail(); + cdie(0, "invalid state->type"); return; } @@ -311,7 +311,7 @@ static void allocate(FBMState state, Addr base, Addr limit) res = FreelistDelete(&oldRange, state->the.fl, &range); break; default: - fail(); + cdie(0, "invalid state->type"); return; } @@ -387,7 +387,7 @@ static void deallocate(FBMState state, Addr base, Addr limit) res = FreelistInsert(&freeRange, state->the.fl, &range); break; default: - fail(); + cdie(0, "invalid state->type"); return; } @@ -432,20 +432,23 @@ static void find(FBMState state, Size size, Bool high, FindDelete findDelete) remainderLimit = origLimit = addrOfIndex(state, expectedLimit); switch(findDelete) { - case FindDeleteNONE: { + case FindDeleteNONE: /* do nothing */ - } break; - case FindDeleteENTIRE: { + break; + case FindDeleteENTIRE: remainderBase = remainderLimit; - } break; - case FindDeleteLOW: { + break; + case FindDeleteLOW: expectedLimit = expectedBase + size; remainderBase = addrOfIndex(state, expectedLimit); - } break; - case FindDeleteHIGH: { + break; + case FindDeleteHIGH: expectedBase = expectedLimit - size; remainderLimit = addrOfIndex(state, expectedBase); - } break; + break; + default: + cdie(0, "invalid findDelete"); + break; } if (findDelete != FindDeleteNONE) { @@ -467,7 +470,7 @@ static void find(FBMState state, Size size, Bool high, FindDelete findDelete) (&foundRange, &oldRange, state->the.fl, size * state->align, findDelete); break; default: - fail(); + cdie(0, "invalid state->type"); return; } @@ -528,9 +531,7 @@ static void test(FBMState state, unsigned n) { size = fbmRnd(ArraySize / 10) + 1; high = fbmRnd(2) ? TRUE : FALSE; switch(fbmRnd(6)) { - case 0: - case 1: - case 2: findDelete = FindDeleteNONE; break; + default: findDelete = FindDeleteNONE; break; case 3: findDelete = FindDeleteLOW; break; case 4: findDelete = FindDeleteHIGH; break; case 5: findDelete = FindDeleteENTIRE; break; @@ -538,7 +539,7 @@ static void test(FBMState state, unsigned n) { find(state, size, high, findDelete); break; default: - fail(); + cdie(0, "invalid state->type"); return; } if ((i + 1) % 1000 == 0) @@ -605,10 +606,14 @@ extern int main(int argc, char *argv[]) mps_arena_destroy(arena); - printf("\nNumber of allocations attempted: %ld\n", NAllocateTried); - printf("Number of allocations succeeded: %ld\n", NAllocateSucceeded); - printf("Number of deallocations attempted: %ld\n", NDeallocateTried); - printf("Number of deallocations succeeded: %ld\n", NDeallocateSucceeded); + printf("\nNumber of allocations attempted: %"PRIuLONGEST"\n", + (ulongest_t)NAllocateTried); + printf("Number of allocations succeeded: %"PRIuLONGEST"\n", + (ulongest_t)NAllocateSucceeded); + printf("Number of deallocations attempted: %"PRIuLONGEST"\n", + (ulongest_t)NDeallocateTried); + printf("Number of deallocations succeeded: %"PRIuLONGEST"\n", + (ulongest_t)NDeallocateSucceeded); printf("%s: Conclusion: Failed to find any defects.\n", argv[0]); return 0; } diff --git a/mps/code/finalcv.c b/mps/code/finalcv.c index daed57c7311..e8f7e251a6e 100644 --- a/mps/code/finalcv.c +++ b/mps/code/finalcv.c @@ -186,7 +186,8 @@ static void *test(void *arg, size_t s) mps_message_finalization_ref(&objaddr, arena, message); obj = objaddr; objind = dylan_int_int(obj[vectorSLOT]); - printf("Finalizing: object %lu at %p\n", objind, objaddr); + printf("Finalizing: object %"PRIuLONGEST" at %p\n", + (ulongest_t)objind, objaddr); /* */ cdie(root[objind] == NULL, "finalized live"); cdie(state[objind] == finalizableSTATE, "finalized dead"); diff --git a/mps/code/finaltest.c b/mps/code/finaltest.c index 205cfefd5ad..dd6146851df 100644 --- a/mps/code/finaltest.c +++ b/mps/code/finaltest.c @@ -20,6 +20,8 @@ #include "mpslib.h" #include "mps.h" #include "mpscamc.h" +#include "mpscams.h" +#include "mpscawl.h" #include "mpsavm.h" #include "fmtdy.h" #include "fmtdytst.h" @@ -32,14 +34,8 @@ #define testArenaSIZE ((size_t)16<<20) #define rootCOUNT 20 -#define maxtreeDEPTH 12 +#define maxtreeDEPTH 10 #define collectionCOUNT 10 -#define genCOUNT 2 - -/* testChain -- generation parameters for the test */ - -static mps_gen_param_s testChain[genCOUNT] = { - { 150, 0.85 }, { 170, 0.45 } }; /* global object counter */ @@ -77,7 +73,7 @@ static void register_numbered_tree(mps_word_t tree, mps_arena_t arena) /* don't finalize ints */ if ((tree & 1) == 0) { mps_addr_t tree_ref = (mps_addr_t)tree; - mps_finalize(arena, &tree_ref); + die(mps_finalize(arena, &tree_ref), "mps_finalize"); register_numbered_tree(DYLAN_VECTOR_SLOT(tree, 0), arena); register_numbered_tree(DYLAN_VECTOR_SLOT(tree, 1), arena); } @@ -117,123 +113,96 @@ static void register_indirect_tree(mps_word_t tree, mps_arena_t arena) if ((tree & 1) == 0) { mps_word_t indirect = DYLAN_VECTOR_SLOT(tree,2); mps_addr_t indirect_ref = (mps_addr_t)indirect; - mps_finalize(arena, &indirect_ref); + die(mps_finalize(arena, &indirect_ref), "mps_finalize"); register_indirect_tree(DYLAN_VECTOR_SLOT(tree, 0), arena); register_indirect_tree(DYLAN_VECTOR_SLOT(tree, 1), arena); } } +static mps_addr_t test_awl_find_dependent(mps_addr_t addr) +{ + testlib_unused(addr); + return NULL; +} static void *root[rootCOUNT]; -static void *test(void *arg, size_t s) +static void test_trees(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; + + object_count = 0; + + printf("Making some %s finalized trees of objects.\n", name); + /* make some trees */ + for(i = 0; i < rootCOUNT; ++i) { + root[i] = (void *)(*make)(maxtreeDEPTH, ap); + (*reg)((mps_word_t)root[i], arena); + } + + printf("Losing all pointers to the trees.\n"); + /* clean out the roots */ + for(i = 0; i < rootCOUNT; ++i) { + root[i] = 0; + } + + 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"); + ++ collections; + while (mps_message_poll(arena)) { + mps_message_t message; + mps_addr_t objaddr; + cdie(mps_message_get(&message, arena, + mps_message_type_finalization()), + "get"); + mps_message_finalization_ref(&objaddr, arena, message); + mps_message_discard(arena, message); + ++ final_this_time; + } + finals += final_this_time; + printf("%"PRIuLONGEST" objects finalized: total %"PRIuLONGEST + " of %"PRIuLONGEST"\n", final_this_time, finals, object_count); + } + cdie(finals == object_count, "Not all objects were finalized."); +} + +static void *test(mps_arena_t arena, mps_class_t pool_class) { mps_ap_t ap; mps_fmt_t fmt; - mps_chain_t chain; - mps_word_t finals; - mps_pool_t amc; + mps_pool_t pool; mps_root_t mps_root; - mps_arena_t arena; - mps_message_t message; - size_t i; - - arena = (mps_arena_t)arg; - (void)s; die(mps_fmt_create_A(&fmt, arena, dylan_fmt_A()), "fmt_create\n"); - die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); - die(mps_pool_create(&amc, arena, mps_class_amc(), fmt, chain), - "pool_create amc\n"); + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_FORMAT, fmt); + 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); die(mps_root_create_table(&mps_root, arena, mps_rank_exact(), (mps_rm_t)0, root, (size_t)rootCOUNT), "root_create\n"); - die(mps_ap_create(&ap, amc, mps_rank_exact()), "ap_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); - object_count = 0; - - printf("Making some finalized trees of objects.\n"); - /* make some trees */ - for(i = 0; i < rootCOUNT; ++i) { - root[i] = (void *)make_numbered_tree(maxtreeDEPTH, ap); - register_numbered_tree((mps_word_t)root[i], arena); - } - - printf("Losing all pointers to the trees.\n"); - /* clean out the roots */ - for(i = 0; i < rootCOUNT; ++i) { - root[i] = 0; - } - - finals = 0; - - while ((finals < object_count) && - (mps_collections(arena) < collectionCOUNT)) { - mps_word_t final_this_time = 0; - printf("Collecting..."); - fflush(stdout); - die(mps_arena_collect(arena), "collect"); - printf(" Done.\n"); - while (mps_message_poll(arena)) { - mps_addr_t objaddr; - cdie(mps_message_get(&message, arena, - mps_message_type_finalization()), - "get"); - mps_message_finalization_ref(&objaddr, arena, message); - mps_message_discard(arena, message); - ++ final_this_time; - } - finals += final_this_time; - printf("%lu objects finalized: total %lu of %lu\n", - final_this_time, finals, object_count); - } - - object_count = 0; - - printf("Making some indirectly finalized trees of objects.\n"); - /* make some trees */ - for(i = 0; i < rootCOUNT; ++i) { - root[i] = (void *)make_indirect_tree(maxtreeDEPTH, ap); - register_indirect_tree((mps_word_t)root[i], arena); - } - - printf("Losing all pointers to the trees.\n"); - /* clean out the roots */ - for(i = 0; i < rootCOUNT; ++i) { - root[i] = 0; - } - - finals = 0; - - while ((finals < object_count) && - (mps_collections(arena) < collectionCOUNT)) { - mps_word_t final_this_time = 0; - printf("Collecting..."); - fflush(stdout); - die(mps_arena_collect(arena), "collect"); - printf(" Done.\n"); - while (mps_message_poll(arena)) { - mps_addr_t objaddr; - cdie(mps_message_get(&message, arena, - mps_message_type_finalization()), - "get"); - mps_message_finalization_ref(&objaddr, arena, message); - mps_message_discard(arena, message); - ++ final_this_time; - } - finals += final_this_time; - printf("%lu objects finalized: total %lu of %lu\n", - final_this_time, finals, object_count); - } + test_trees("numbered", arena, ap, make_numbered_tree, register_numbered_tree); + test_trees("indirect", arena, ap, make_indirect_tree, register_indirect_tree); mps_ap_destroy(ap); mps_root_destroy(mps_root); - mps_pool_destroy(amc); - mps_chain_destroy(chain); + mps_pool_destroy(pool); mps_fmt_destroy(fmt); return NULL; @@ -244,14 +213,17 @@ int main(int argc, char *argv[]) { mps_arena_t arena; mps_thr_t thread; - void *r; testlib_init(argc, argv); die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), "arena_create\n"); die(mps_thread_reg(&thread, arena), "thread_reg\n"); - mps_tramp(&r, test, arena, 0); + + test(arena, mps_class_amc()); + /* TODO: test(arena, mps_class_ams()); */ + /* TODO: test(arena, mps_class_awl()); */ + mps_thread_dereg(thread); mps_arena_destroy(arena); diff --git a/mps/code/fmtdy.c b/mps/code/fmtdy.c index f622bfe128c..5ec72159590 100644 --- a/mps/code/fmtdy.c +++ b/mps/code/fmtdy.c @@ -1,7 +1,7 @@ /* fmtdy.c: DYLAN OBJECT FORMAT IMPLEMENTATION * * $Id$ - * Copyright (c) 2001 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. * * .readership: MPS developers, Dylan developers @@ -69,10 +69,6 @@ /* MPS_END causes "constant conditional" warnings. */ #pragma warning(disable: 4127) -/* windows.h causes warnings about "unreferenced inline function */ -/* has been removed". */ -#pragma warning(disable: 4514) - #endif /* _MSC_VER */ @@ -470,8 +466,8 @@ extern mps_res_t dylan_scan1(mps_ss_t mps_ss, mps_addr_t *object_io) break; case 1: /* stretchy non-traceable */ - notreached(); /* Not used by DylanWorks yet */ p += vt + 1; + notreached(); /* Not used by DylanWorks yet */ break; case 2: /* non-stretchy traceable */ @@ -482,7 +478,6 @@ extern mps_res_t dylan_scan1(mps_ss_t mps_ss, mps_addr_t *object_io) break; case 3: /* stretchy traceable */ - notreached(); /* DW doesn't create them yet */ vl = *(mps_word_t *)p; /* vector length */ assert((vl & 3) == 1); /* check Dylan integer tag */ vl >>= 2; /* untag it */ @@ -490,21 +485,22 @@ extern mps_res_t dylan_scan1(mps_ss_t mps_ss, mps_addr_t *object_io) res = dylan_scan_contig(mps_ss, p, p + vl); if(res) return res; p += vt; /* skip to end of whole vector */ + notreached(); /* DW doesn't create them yet */ break; case 4: /* non-word */ - es = (vh & 0xff) >> 3; - vb = (vh >> 16) & 0xff; + es = (unsigned)(vh & 0xff) >> 3; + vb = (unsigned)((vh >> 16) & 0xff); vt += vb; p += NONWORD_LENGTH(vt, es); break; case 5: /* stretchy non-word */ - notreached(); /* DW doesn't create them yet */ - es = (vh & 0xff) >> 3; - vb = (vh >> 16) & 0xff; + es = (unsigned)(vh & 0xff) >> 3; + vb = (unsigned)((vh >> 16) & 0xff); vt += vb; p += NONWORD_LENGTH(vt, es) + 1; + notreached(); /* DW doesn't create them yet */ break; default: @@ -678,8 +674,8 @@ static mps_addr_t dylan_skip(mps_addr_t object) if((vf & 6) == 4) /* non-word */ { - es = (vh & 0xff) >> 3; - vb = (vh >> 16) & 0xff; + es = (unsigned)(vh & 0xff) >> 3; + vb = (unsigned)((vh >> 16) & 0xff); vt += vb; p += NONWORD_LENGTH(vt, es); } @@ -844,7 +840,7 @@ mps_res_t dylan_fmt_weak(mps_fmt_t *mps_fmt_o, mps_arena_t arena) /* 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/fmtdytst.c b/mps/code/fmtdytst.c index 790840f5491..376c43aa7df 100644 --- a/mps/code/fmtdytst.c +++ b/mps/code/fmtdytst.c @@ -1,7 +1,7 @@ /* fmtdytst.c: DYLAN FORMAT TEST CODE * * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * .readership: MPS developers, Dylan developers. */ @@ -17,12 +17,6 @@ #define unused(param) ((void)param) -#ifdef MPS_BUILD_MV -/* windows.h causes warnings about "unreferenced inline function */ -/* has been removed". */ -#pragma warning(disable: 4514) -#endif /* MPS_BUILD_MV */ - static mps_word_t *ww = NULL; static mps_word_t *tvw; @@ -222,7 +216,7 @@ mps_bool_t dylan_check(mps_addr_t addr) /* 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/fmtno.c b/mps/code/fmtno.c index 6c632fef06b..05f84651bdf 100644 --- a/mps/code/fmtno.c +++ b/mps/code/fmtno.c @@ -1,7 +1,7 @@ /* fmtno.c: NULL OBJECT FORMAT IMPLEMENTATION * * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * .readership: MPS developers */ @@ -17,22 +17,6 @@ #define notreached() assert(0) #define unused(param) ((void)param) -#ifdef MPS_BUILD_MV - -/* MSVC 2.0 generates a warning for unused(). */ -#ifdef _MSC_VER -#if _MSC_VER < 1000 -#pragma warning(disable: 4705) -#endif -#else /* _MSC_VER */ -#error "Expected _MSC_VER to be defined for builder.mv" -#endif /* _MSC_VER */ - -/* windows.h causes warnings about "unreferenced inline function */ -/* has been removed". */ -#pragma warning(disable: 4514) - -#endif /* MPS_BUILD_MV */ #define ALIGN sizeof(mps_word_t) @@ -137,7 +121,7 @@ mps_res_t no_fmt(mps_fmt_t *mps_fmt_o, mps_arena_t arena) /* 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/fmtscheme.c b/mps/code/fmtscheme.c index 97c76483402..5299c8f3525 100644 --- a/mps/code/fmtscheme.c +++ b/mps/code/fmtscheme.c @@ -6,10 +6,6 @@ #include -#include "mpsavm.h" -#include "mpscamc.h" -#include "mpslib.h" - #include "fmtscheme.h" #include "testlib.h" @@ -419,8 +415,9 @@ static mps_addr_t obj_isfwd(mps_addr_t addr) return obj->fwd2.fwd; case TYPE_FWD: return obj->fwd.fwd; + default: + return NULL; } - return NULL; } static void obj_fwd(mps_addr_t old, mps_addr_t new) @@ -467,70 +464,6 @@ void scheme_fmt(mps_fmt_t *fmt) if (res != MPS_RES_OK) error("Couldn't create obj format"); } -static mps_gen_param_s obj_gen_params[] = { - { 150, 0.85 }, - { 170, 0.45 } -}; - -int main(int argc, char *argv[]) -{ - mps_res_t res; - mps_chain_t obj_chain; - mps_fmt_t obj_fmt; - mps_thr_t thread; - mps_root_t reg_root; - void *marker = ▮ - - randomize(argc, argv); - mps_lib_assert_fail_install(assert_die); - - MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, 1 << 20); - MPS_ARGS_DONE(args); - res = mps_arena_create_k(&scheme_arena, mps_arena_class_vm(), args); - } MPS_ARGS_END(args); - if (res != MPS_RES_OK) error("Couldn't create arena"); - - res = mps_chain_create(&obj_chain, scheme_arena, - sizeof(obj_gen_params) / sizeof(*obj_gen_params), - obj_gen_params); - if (res != MPS_RES_OK) error("Couldn't create obj chain"); - - scheme_fmt(&obj_fmt); - - MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_CHAIN, obj_chain); - MPS_ARGS_ADD(args, MPS_KEY_FORMAT, obj_fmt); - 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); - - res = mps_ap_create_k(&obj_ap, obj_pool, mps_args_none); - if (res != MPS_RES_OK) error("Couldn't create obj allocation point"); - - res = mps_thread_reg(&thread, scheme_arena); - if (res != MPS_RES_OK) error("Couldn't register thread"); - - res = mps_root_create_reg(®_root, scheme_arena, mps_rank_ambig(), 0, - thread, mps_stack_scan_ambig, marker, 0); - if (res != MPS_RES_OK) error("Couldn't create root"); - - test_main(); - - mps_arena_park(scheme_arena); - mps_root_destroy(reg_root); - mps_thread_dereg(thread); - mps_ap_destroy(obj_ap); - mps_pool_destroy(obj_pool); - mps_chain_destroy(obj_chain); - mps_fmt_destroy(obj_fmt); - mps_arena_destroy(scheme_arena); - - printf("%s: Conclusion: Failed to find any defects.\n", argv[0]); - return 0; -} - /* C. COPYRIGHT AND LICENSE * diff --git a/mps/code/fmtscheme.h b/mps/code/fmtscheme.h index 6b2f10f202d..fbbbddf8ccd 100644 --- a/mps/code/fmtscheme.h +++ b/mps/code/fmtscheme.h @@ -183,7 +183,8 @@ extern obj_t scheme_make_table(size_t length, hash_t hashf, cmp_t cmpf); extern void scheme_fmt(mps_fmt_t *fmt); extern mps_arena_t scheme_arena; -extern void test_main(void); +extern mps_pool_t obj_pool; +extern mps_ap_t obj_ap; #endif /* fmtscheme_h */ diff --git a/mps/code/format.c b/mps/code/format.c index fb72680535b..88a86283ef8 100644 --- a/mps/code/format.c +++ b/mps/code/format.c @@ -1,7 +1,7 @@ /* format.c: OBJECT FORMATS * * $Id$ - * Copyright (c) 2001 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. * * DESIGN @@ -21,7 +21,7 @@ Bool FormatCheck(Format format) CHECKS(Format, format); CHECKU(Arena, format->arena); CHECKL(format->serial < format->arena->formatSerial); - CHECKL(RingCheck(&format->arenaRing)); + CHECKD_NOSIG(Ring, &format->arenaRing); CHECKL(AlignCheck(format->alignment)); /* TODO: Define the concept of the maximum alignment it is possible to request from the MPS, document and provide an interface to it, and then @@ -114,7 +114,7 @@ Res FormatCreate(Format *formatReturn, Arena arena, ArgList args) AVER(formatReturn != NULL); AVERT(Arena, arena); - AVER(ArgListCheck(args)); + AVERT(ArgList, args); if (ArgPick(&arg, args, MPS_KEY_FMT_ALIGN)) fmtAlign = arg.val.align; @@ -217,7 +217,7 @@ Res FormatDescribe(Format format, mps_lib_FILE *stream) /* 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/fotest.c b/mps/code/fotest.c index ada5f6dec67..58b25d6b65c 100644 --- a/mps/code/fotest.c +++ b/mps/code/fotest.c @@ -60,6 +60,8 @@ DEFINE_POOL_CLASS(OOMPoolClass, this) { INHERIT_CLASS(this, AbstractAllocFreePoolClass); this->alloc = OOMAlloc; + this->size = sizeof(PoolStruct); + AVERT(PoolClass, this); } @@ -149,11 +151,6 @@ allocFail: } -#define max(a, b) (((a) > (b)) ? (a) : (b)) - -#define alignUp(w, a) (((w) + (a) - 1) & ~((size_t)(a) - 1)) - - /* randomSizeAligned -- produce sizes both large and small, * aligned by platform alignment */ diff --git a/mps/code/gc.gmk b/mps/code/gc.gmk index 8ff258c9cf3..826cb0ef659 100644 --- a/mps/code/gc.gmk +++ b/mps/code/gc.gmk @@ -3,7 +3,7 @@ # gc.gmk: GNUMAKEFILE FRAGMENT FOR GNU CC # # $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. # # This file is included by platform makefiles that use the GNU CC # compiler. It defines the compiler-specific variables that the @@ -12,11 +12,22 @@ CC = gcc CFLAGSDEBUG = -O -g3 CFLAGSOPT = -O2 -g3 -CFLAGSCOMPILER := -Wall -Wextra -Werror -Wpointer-arith \ - -Wstrict-prototypes -Wmissing-prototypes \ - -Winline -Waggregate-return -Wnested-externs \ - -Wcast-qual -Wshadow -Wwrite-strings # -Wstrict-aliasing=2 -CFLAGSCOMPILERSTRICT := -ansi -pedantic -Wshadow +CFLAGSCOMPILER := \ + -Waggregate-return \ + -Wall \ + -Wcast-qual \ + -Werror \ + -Wextra \ + -Winline \ + -Wmissing-prototypes \ + -Wnested-externs \ + -Wpointer-arith \ + -Wshadow \ + -Wstrict-aliasing=2 \ + -Wstrict-prototypes \ + -Wswitch-default \ + -Wwrite-strings +CFLAGSCOMPILERSTRICT := -ansi -pedantic # A different set of compiler flags for less strict compilation, for # instance when we need to #include a third-party header file that @@ -38,7 +49,7 @@ endef # 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/gcbench.c b/mps/code/gcbench.c index 214636649f1..61b6e925e94 100644 --- a/mps/code/gcbench.c +++ b/mps/code/gcbench.c @@ -331,8 +331,8 @@ int main(int argc, char *argv[]) { double mort = 0.0; cap = (size_t)strtoul(optarg, &p, 10); switch(toupper(*p)) { - case 'G': cap *= 1024; - case 'M': cap *= 1024; + case 'G': cap *= 1024; /* fall through */ + case 'M': cap *= 1024; /* fall through */ case 'K': p++; break; default: cap = 0; break; } @@ -356,6 +356,10 @@ int main(int argc, char *argv[]) { case 'G': arenasize *= 1024; case 'M': arenasize *= 1024; case 'K': arenasize *= 1024; break; + case '\0': break; + default: + fprintf(stderr, "Bad arena size %s\n", optarg); + return EXIT_FAILURE; } } break; diff --git a/mps/code/global.c b/mps/code/global.c index bfc2777d888..24cd0a81013 100644 --- a/mps/code/global.c +++ b/mps/code/global.c @@ -115,7 +115,7 @@ Bool GlobalsCheck(Globals arenaGlobals) CHECKS(Globals, arenaGlobals); arena = GlobalsArena(arenaGlobals); CHECKL(arena->serial < arenaSerial); - CHECKL(RingCheck(&arenaGlobals->globalRing)); + CHECKD_NOSIG(Ring, &arenaGlobals->globalRing); CHECKL(MPSVersion() == arenaGlobals->mpsVersionString); @@ -134,16 +134,17 @@ Bool GlobalsCheck(Globals arenaGlobals) CHECKL(arenaGlobals->emptyInternalSize >= 0.0); CHECKL(BoolCheck(arenaGlobals->bufferLogging)); - CHECKL(RingCheck(&arenaGlobals->poolRing)); - CHECKL(RingCheck(&arenaGlobals->rootRing)); - CHECKL(RingCheck(&arenaGlobals->rememberedSummaryRing)); + CHECKD_NOSIG(Ring, &arenaGlobals->poolRing); + CHECKD_NOSIG(Ring, &arenaGlobals->rootRing); + CHECKD_NOSIG(Ring, &arenaGlobals->rememberedSummaryRing); CHECKL(arenaGlobals->rememberedSummaryIndex < RememberedSummaryBLOCK); /* RingIsSingle imples index == 0 */ CHECKL(!RingIsSingle(&arenaGlobals->rememberedSummaryRing) || arenaGlobals->rememberedSummaryIndex == 0); - CHECKL(RingCheck(&arena->formatRing)); - CHECKL(RingCheck(&arena->messageRing)); - /* Don't check enabledMessageTypes */ + CHECKD_NOSIG(Ring, &arena->formatRing); + CHECKD_NOSIG(Ring, &arena->messageRing); + if (arena->enabledMessageTypes != NULL) + CHECKD_NOSIG(BT, arena->enabledMessageTypes); CHECKL(BoolCheck(arena->isFinalPool)); if (arena->isFinalPool) { CHECKD(Pool, arena->finalPool); @@ -151,7 +152,7 @@ Bool GlobalsCheck(Globals arenaGlobals) CHECKL(arena->finalPool == NULL); } - CHECKL(RingCheck(&arena->threadRing)); + CHECKD_NOSIG(Ring, &arena->threadRing); CHECKL(BoolCheck(arena->insideShield)); CHECKL(arena->shCacheLimit <= ShieldCacheSIZE); @@ -185,8 +186,8 @@ Bool GlobalsCheck(Globals arenaGlobals) TRACE_SET_ITER_END(ti, trace, TraceSetUNIV, arena); for(rank = 0; rank < RankLIMIT; ++rank) - CHECKL(RingCheck(&arena->greyRing[rank])); - CHECKL(RingCheck(&arena->chainRing)); + CHECKD_NOSIG(Ring, &arena->greyRing[rank]); + CHECKD_NOSIG(Ring, &arena->chainRing); CHECKL(arena->tracedSize >= 0.0); CHECKL(arena->tracedTime >= 0.0); @@ -208,6 +209,8 @@ Bool GlobalsCheck(Globals arenaGlobals) /* we also check the statics now. */ CHECKL(BoolCheck(arenaRingInit)); + /* Can't CHECKD_NOSIG here because &arenaRing is never NULL and GCC + * will warn about a constant comparison. */ CHECKL(RingCheck(&arenaRing)); CHECKL(BoolCheck(arena->emergency)); @@ -610,7 +613,7 @@ Bool ArenaAccess(Addr addr, AccessSet mode, MutatorFaultContext context) arenaClaimRingLock(); /* */ mps_exception_info = context; - AVER(RingCheck(&arenaRing)); + AVERT(Ring, &arenaRing); RING_FOR(node, &arenaRing, nextNode) { Globals arenaGlobals = RING_ELT(Globals, globalRing, node); diff --git a/mps/code/ll.gmk b/mps/code/ll.gmk index fd91e62fe42..dc2595c511f 100644 --- a/mps/code/ll.gmk +++ b/mps/code/ll.gmk @@ -3,7 +3,7 @@ # ll.gmk: GNUMAKEFILE FRAGMENT FOR CLANG/LLVM # # $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. # # This file is included by platform makefiles that use the Clang/LLVM # compiler. It defines the compiler-specific variables that the @@ -12,11 +12,24 @@ CC = clang CFLAGSDEBUG = -O -g3 CFLAGSOPT = -O2 -g3 -CFLAGSCOMPILER := -Wall -Werror -Wpointer-arith \ - -Wstrict-prototypes -Wmissing-prototypes \ - -Winline -Waggregate-return -Wnested-externs \ - -Wcast-qual -Wshadow # -Wstrict-aliasing=2 -CFLAGSCOMPILERSTRICT := -pedantic -Wno-extended-offsetof +CFLAGSCOMPILER := \ + -pedantic \ + -Waggregate-return \ + -Wall \ + -Wcast-qual \ + -Werror \ + -Wextra \ + -Winline \ + -Wmissing-prototypes \ + -Wnested-externs \ + -Wno-extended-offsetof \ + -Wpointer-arith \ + -Wshadow \ + -Wstrict-aliasing=2 \ + -Wstrict-prototypes \ + -Wunreachable-code \ + -Wwrite-strings +CFLAGSCOMPILERSTRICT := # A different set of compiler flags for less strict compilation, for # instance when we need to #include a third-party header file that @@ -38,7 +51,7 @@ endef # 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/locbwcss.c b/mps/code/locbwcss.c index 5807d9c1f7b..0e40c254635 100644 --- a/mps/code/locbwcss.c +++ b/mps/code/locbwcss.c @@ -110,7 +110,7 @@ static void poolStatInit(PoolStat stat, mps_pool_t pool, size_t objSize) static void allocMultiple(PoolStat stat) { mps_addr_t objects[allocsPerIteration]; - int i; + size_t i; /* allocate a few objects, and record stats for them */ for (i = 0; i < allocsPerIteration; i++) { @@ -131,8 +131,7 @@ static void allocMultiple(PoolStat stat) static void reportResults(PoolStat stat, const char *name) { - printf("\nResults for "); - fputs(name, stdout); + printf("\nResults for %s\n", name); printf("\n"); printf(" Allocated %"PRIuLONGEST" objects\n", (ulongest_t)stat->aCount); printf(" Freed %"PRIuLONGEST" objects\n", (ulongest_t)stat->fCount); @@ -198,7 +197,6 @@ int main(int argc, char *argv[]) MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE); MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, FALSE); - MPS_ARGS_DONE(args); die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "mps_arena_create"); } MPS_ARGS_END(args); diff --git a/mps/code/lockutw3.c b/mps/code/lockutw3.c index da5070ecab7..43f486799df 100644 --- a/mps/code/lockutw3.c +++ b/mps/code/lockutw3.c @@ -4,6 +4,8 @@ * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. */ +#include /* malloc */ + #include "mpm.h" #include "testlib.h" #include "mpslib.h" @@ -84,8 +86,10 @@ int main(int argc, char *argv[]) for(i = 0; i < nTHREADS; i++) t[i] = CreateThread(NULL, 0, thread0, NULL, 0, &id); - for(i = 0; i < nTHREADS; i++) - WaitForSingleObject(t[i], INFINITE); + for(i = 0; i < nTHREADS; i++) { + cdie(WaitForSingleObject(t[i], INFINITE) == WAIT_OBJECT_0, + "WaitForSingleObject"); + } Insist(shared == nTHREADS*COUNT); diff --git a/mps/code/locus.c b/mps/code/locus.c index 11220210f52..a704c8b820b 100644 --- a/mps/code/locus.c +++ b/mps/code/locus.c @@ -1,7 +1,7 @@ /* locus.c: LOCUS MANAGER * * $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. * * DESIGN * @@ -43,7 +43,7 @@ SegPref SegPrefDefault(void) void SegPrefInit(SegPref pref) { - mps_lib_memcpy(pref, &segPrefDefault, sizeof(SegPrefStruct)); + (void)mps_lib_memcpy(pref, &segPrefDefault, sizeof(SegPrefStruct)); } @@ -89,7 +89,7 @@ static Bool GenDescCheck(GenDesc gen) CHECKL(gen->mortality <= 1.0); CHECKL(gen->proflow >= 0.0); CHECKL(gen->proflow <= 1.0); - CHECKL(RingCheck(&gen->locusRing)); + CHECKD_NOSIG(Ring, &gen->locusRing); return TRUE; } @@ -192,7 +192,7 @@ Bool ChainCheck(Chain chain) CHECKS(Chain, chain); CHECKU(Arena, chain->arena); - CHECKL(RingCheck(&chain->chainRing)); + CHECKD_NOSIG(Ring, &chain->chainRing); CHECKL(TraceSetCheck(chain->activeTraces)); CHECKL(chain->genCount > 0); for (i = 0; i < chain->genCount; ++i) { @@ -370,7 +370,7 @@ Res ChainCondemnAll(Chain chain, Trace trace) Ring segNode, nextSegNode; AVERT(Pool, pool); - AVER((pool->class->attr & AttrGC) != 0); + AVER(PoolHasAttr(pool, AttrGC)); RING_FOR(segNode, PoolSegRing(pool), nextSegNode) { Seg seg = SegOfPoolRing(segNode); @@ -458,7 +458,7 @@ Bool PoolGenCheck(PoolGen gen) /* nothing to check about serial */ CHECKU(Pool, gen->pool); CHECKU(Chain, gen->chain); - CHECKL(RingCheck(&gen->genRing)); + CHECKD_NOSIG(Ring, &gen->genRing); CHECKL(gen->newSize <= gen->totalSize); return TRUE; } @@ -501,14 +501,14 @@ void LocusFinish(Arena arena) Bool LocusCheck(Arena arena) { /* Can't check arena, because this is part of ArenaCheck. */ - CHECKL(GenDescCheck(&arena->topGen)); + CHECKD(GenDesc, &arena->topGen); return TRUE; } /* 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/locusss.c b/mps/code/locusss.c index b399e58e8da..3dfbc78afe1 100644 --- a/mps/code/locusss.c +++ b/mps/code/locusss.c @@ -110,7 +110,7 @@ static void poolStatInit(PoolStat stat, mps_pool_t pool, size_t objSize) static mps_res_t allocMultiple(PoolStat stat) { mps_addr_t objects[contigAllocs]; - int i; + size_t i; /* allocate a few objects, and record stats for them */ for (i = 0; i < contigAllocs; i++) { @@ -220,7 +220,6 @@ static void runArenaTest(size_t size, MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, size); MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, FALSE); - MPS_ARGS_DONE(args); die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "mps_arena_create"); } MPS_ARGS_END(args); diff --git a/mps/code/message.c b/mps/code/message.c index 75b01d328d8..eba94182837 100644 --- a/mps/code/message.c +++ b/mps/code/message.c @@ -1,7 +1,7 @@ /* message.c: MPS/CLIENT MESSAGES * * $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 * @@ -53,7 +53,7 @@ Bool MessageCheck(Message message) CHECKS(Message, message); CHECKU(Arena, message->arena); CHECKD(MessageClass, message->class); - CHECKL(RingCheck(&message->queueRing)); + CHECKD_NOSIG(Ring, &message->queueRing); /* postedClock is uncheckable for clocked message types, */ /* but must be 0 for unclocked message types: */ CHECKL(MessageIsClocked(message) || (message->postedClock == 0)); @@ -186,7 +186,7 @@ void MessageEmpty(Arena arena) static Bool MessageTypeEnabled(Arena arena, MessageType type) { AVERT(Arena, arena); - AVER(MessageTypeCheck(type)); + AVERT(MessageType, type); return BTGet(arena->enabledMessageTypes, type); } @@ -194,7 +194,7 @@ static Bool MessageTypeEnabled(Arena arena, MessageType type) void MessageTypeEnable(Arena arena, MessageType type) { AVERT(Arena, arena); - AVER(MessageTypeCheck(type)); + AVERT(MessageType, type); BTSet(arena->enabledMessageTypes, type); } @@ -204,7 +204,7 @@ void MessageTypeDisable(Arena arena, MessageType type) Message message; AVERT(Arena, arena); - AVER(MessageTypeCheck(type)); + AVERT(MessageType, type); /* Flush existing messages of this type */ while(MessageGet(&message, arena, type)) { @@ -252,7 +252,7 @@ Bool MessageGet(Message *messageReturn, Arena arena, MessageType type) AVER(messageReturn != NULL); AVERT(Arena, arena); - AVER(MessageTypeCheck(type)); + AVERT(MessageType, type); RING_FOR(node, &arena->messageRing, next) { Message message = RING_ELT(Message, queueRing, node); @@ -427,7 +427,7 @@ const char *MessageNoGCStartWhy(Message message) /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2002, 2008 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/mpm.c b/mps/code/mpm.c index 5436327c7ef..f544acca401 100644 --- a/mps/code/mpm.c +++ b/mps/code/mpm.c @@ -1,7 +1,7 @@ /* mpm.c: GENERAL MPM SUPPORT * * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * .purpose: Miscellaneous support for the implementation of the MPM * and pool classes. @@ -132,7 +132,7 @@ Bool AlignCheck(Align align) Bool (WordIsAligned)(Word word, Align align) { - AVER(AlignCheck(align)); + AVERT(Align, align); return WordIsAligned(word, align); } @@ -141,7 +141,7 @@ Bool (WordIsAligned)(Word word, Align align) Word (WordAlignUp)(Word word, Align align) { - AVER(AlignCheck(align)); + AVERT(Align, align); return WordAlignUp(word, align); } @@ -167,7 +167,7 @@ Word (WordRoundUp)(Word word, Size modulus) Word (WordAlignDown)(Word word, Align alignment) { - AVER(AlignCheck(alignment)); + AVERT(Align, alignment); return WordAlignDown(word, alignment); } @@ -212,7 +212,7 @@ Shift SizeLog2(Size size) Addr (AddrAlignDown)(Addr addr, Align alignment) { - AVER(AlignCheck(alignment)); + AVERT(Align, alignment); return AddrAlignDown(addr, alignment); } @@ -604,7 +604,7 @@ Bool StringEqual(const char *s1, const char *s2) /* 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/mpm.h b/mps/code/mpm.h index 3bbd71cbb23..7876330de65 100644 --- a/mps/code/mpm.h +++ b/mps/code/mpm.h @@ -178,11 +178,13 @@ extern Bool PoolClassCheck(PoolClass class); extern Bool PoolCheck(Pool pool); extern Res PoolDescribe(Pool pool, mps_lib_FILE *stream); +/* Must be thread-safe. See . */ #define PoolArena(pool) ((pool)->arena) #define PoolAlignment(pool) ((pool)->alignment) #define PoolSegRing(pool) (&(pool)->segRing) #define PoolArenaRing(pool) (&(pool)->arenaRing) #define PoolOfArenaRing(node) RING_ELT(Pool, arenaRing, node) +#define PoolHasAttr(pool, Attr) (((pool)->class->attr & (Attr)) != 0) extern Bool PoolFormat(Format *formatReturn, Pool pool); @@ -263,10 +265,11 @@ extern Res PoolTrivFramePush(AllocFrame *frameReturn, Pool pool, Buffer buf); extern Res PoolNoFramePop(Pool pool, Buffer buf, AllocFrame frame); extern Res PoolTrivFramePop(Pool pool, Buffer buf, AllocFrame frame); extern void PoolNoFramePopPending(Pool pool, Buffer buf, AllocFrame frame); +extern void PoolTrivFramePopPending(Pool pool, Buffer buf, AllocFrame frame); extern Res PoolNoAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr); extern void PoolNoWalk(Pool pool, Seg seg, FormattedObjectsStepMethod step, void *p, size_t s); -extern void PoolNoFreeWalk(Pool pool, FreeBlockStepMethod f, void *p); +extern void PoolTrivFreeWalk(Pool pool, FreeBlockStepMethod f, void *p); extern PoolDebugMixin PoolNoDebugMixin(Pool pool); extern BufferClass PoolNoBufferClass(void); @@ -1009,9 +1012,6 @@ extern void StackProbe(Size depth); * STATISTIC_WRITE is inserted in WriteF arguments to output the values * of statistic fields. * - * STATISTIC_BEGIN and STATISTIC_END can be used around a block of - * statements. - * * .statistic.whitehot: The implementation of STATISTIC for * non-statistical varieties passes the parameter to DISCARD to ensure * the parameter is syntactically an expression. The parameter is @@ -1023,16 +1023,12 @@ extern void StackProbe(Size depth); #define STATISTIC(gather) BEGIN (gather); END #define STATISTIC_STAT(gather) BEGIN gather; END #define STATISTIC_WRITE(format, arg) (format), (arg), -#define STATISTIC_BEGIN BEGIN -#define STATISTIC_END END #elif defined(STATISTICS_NONE) #define STATISTIC(gather) DISCARD(((gather), 0)) #define STATISTIC_STAT DISCARD_STAT #define STATISTIC_WRITE(format, arg) -#define STATISTIC_BEGIN BEGIN if (0) { -#define STATISTIC_END } END #else /* !defined(STATISTICS) && !defined(STATISTICS_NONE) */ diff --git a/mps/code/mpmss.c b/mps/code/mpmss.c index 76fbf12c3fe..9dd25574417 100644 --- a/mps/code/mpmss.c +++ b/mps/code/mpmss.c @@ -30,13 +30,13 @@ extern mps_class_t PoolClassMFS(void); /* stress -- create a pool of the requested type and allocate in it */ -static mps_res_t stress(mps_class_t class, size_t (*size)(int i), +static mps_res_t stress(mps_class_t class, size_t (*size)(size_t i), mps_arena_t arena, ...) { mps_res_t res; mps_pool_t pool; va_list arg; - int i, k; + size_t i, k; int *ps[testSetSIZE]; size_t ss[testSetSIZE]; @@ -62,7 +62,7 @@ static mps_res_t stress(mps_class_t class, size_t (*size)(int i), for (k=0; k (b)) ? (a) : (b)) - -#define alignUp(w, a) (((w) + (a) - 1) & ~((size_t)(a) - 1)) - - /* randomSize -- produce sizes both latge and small */ -static size_t randomSize(int i) +static size_t randomSize(size_t i) { /* Make the range large enough to span three pages in the segment table: */ /* 160 segments/page, page size max 0x2000. */ @@ -111,7 +106,7 @@ static size_t randomSize(int i) /* randomSize8 -- produce sizes both latge and small, 8-byte aligned */ -static size_t randomSize8(int i) +static size_t randomSize8(size_t i) { size_t maxSize = 2 * 160 * 0x2000; /* Reduce by a factor of 2 every 10 cycles. Total allocation about 40 MB. */ @@ -123,23 +118,16 @@ static size_t randomSize8(int i) static size_t fixedSizeSize = 0; -static size_t fixedSize(int i) +static size_t fixedSize(size_t i) { testlib_unused(i); return fixedSizeSize; } -static mps_pool_debug_option_s bothOptions8 = { - /* .fence_template = */ (const void *)"postpost", - /* .fence_size = */ 8, - /* .free_template = */ (const void *)"DEAD", - /* .free_size = */ 4 -}; - -static mps_pool_debug_option_s bothOptions16 = { +static mps_pool_debug_option_s bothOptions = { /* .fence_template = */ (const void *)"postpostpostpost", - /* .fence_size = */ 16, + /* .fence_size = */ MPS_PF_ALIGN, /* .free_template = */ (const void *)"DEAD", /* .free_size = */ 4 }; @@ -153,7 +141,7 @@ static mps_pool_debug_option_s fenceOptions = { /* testInArena -- test all the pool classes in the given arena */ -static int testInArena(mps_arena_t arena, mps_pool_debug_option_s *options) +static void testInArena(mps_arena_t arena, mps_pool_debug_option_s *options) { /* IWBN to test MVFFDebug, but the MPS doesn't support debugging */ /* cross-segment allocation (possibly MVFF ought not to). */ @@ -176,23 +164,18 @@ static int testInArena(mps_arena_t arena, mps_pool_debug_option_s *options) die(stress(mps_class_mv(), randomSize, arena, (size_t)65536, (size_t)32, (size_t)65536), "stress MV"); - - return 0; } int main(int argc, char *argv[]) { mps_arena_t arena; - mps_pool_debug_option_s *bothOptions; - - bothOptions = MPS_PF_ALIGN == 8 ? &bothOptions8 : &bothOptions16; testlib_init(argc, argv); die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), "mps_arena_create"); - testInArena(arena, bothOptions); + testInArena(arena, &bothOptions); mps_arena_destroy(arena); die(mps_arena_create(&arena, mps_arena_class_vm(), smallArenaSIZE), diff --git a/mps/code/mpmtypes.h b/mps/code/mpmtypes.h index 9aac8322b35..693a2262247 100644 --- a/mps/code/mpmtypes.h +++ b/mps/code/mpmtypes.h @@ -1,7 +1,7 @@ /* mpmtypes.h: MEMORY POOL MANAGER TYPES * * $Id$ - * Copyright (c) 2001-2002, 2006 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * Portions copyright (c) 2001 Global Graphics Software. * * .design: @@ -41,7 +41,7 @@ typedef unsigned Shift; /* */ typedef unsigned Serial; /* */ typedef Addr Ref; /* */ typedef void *Pointer; /* */ -typedef Word Clock; /* processor time */ +typedef Word Clock; /* */ typedef MPS_T_ULONGEST ULongest; /* */ typedef mps_arg_s ArgStruct; @@ -60,7 +60,6 @@ typedef unsigned TraceSet; /* */ typedef unsigned TraceState; /* */ typedef unsigned AccessSet; /* */ typedef unsigned Attr; /* */ -typedef unsigned FormatVariety; typedef int RootVar; /* */ typedef Word *BT; /* */ @@ -300,16 +299,6 @@ typedef struct TraceMessageStruct *TraceMessage; /* trace end */ AttrGC | AttrINCR_RB | AttrINCR_WB | AttrMOVINGGC) -/* Format varieties */ -enum { - FormatVarietyA = 1, - FormatVarietyB, - FormatVarietyAutoHeader, - FormatVarietyFixed, - FormatVarietyLIMIT -}; - - /* Segment preferences */ enum { SegPrefHigh = 1, @@ -465,7 +454,7 @@ typedef double WriteFD; /* C. COPYRIGHT AND LICENSE * - * Copyright (C) 2001-2002, 2006 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.c b/mps/code/mps.c index c8a00b7cd13..2125d2d4a3c 100644 --- a/mps/code/mps.c +++ b/mps/code/mps.c @@ -207,8 +207,8 @@ #include "protw3.c" /* Windows protection */ #include "proti3.c" /* 32-bit Intel mutator context decoding */ #include "prmci3w3.c" /* Windows on 32-bit Intel mutator context */ -#include "ssw3i3mv.c" /* Windows on 32-bit stack scan for Microsoft C */ -#include "spw3i3mv.c" /* Windows on 32-bit stack probe for Microsoft C */ +#include "ssw3i3mv.c" /* Windows on 32-bit Intel stack scan for Microsoft C */ +#include "spw3i3.c" /* Windows on 32-bit Intel stack probe */ #include "mpsiw3.c" /* Windows interface layer extras */ /* Windows on 64-bit Intel with Microsoft Visual Studio */ @@ -223,8 +223,38 @@ #include "protw3.c" /* Windows protection */ #include "proti6.c" /* 64-bit Intel mutator context decoding */ #include "prmci6w3.c" /* Windows on 64-bit Intel mutator context */ -#include "ssw3i6mv.c" /* Windows on 64-bit stack scan for Microsoft C */ -#include "spw3i6mv.c" /* Windows on 64-bit stack probe for Microsoft C */ +#include "ssw3i6mv.c" /* Windows on 64-bit Intel stack scan for Microsoft C */ +#include "spw3i6.c" /* Windows on 64-bit Intel stack probe */ +#include "mpsiw3.c" /* Windows interface layer extras */ + +/* Windows on 32-bit Intel with Pelles C */ + +#elif defined(MPS_PF_W3I3PC) + +#include "lockw3.c" /* Windows locks */ +#include "thw3.c" /* Windows threading */ +#include "thw3i3.c" /* Windows on 32-bit Intel thread stack scan */ +#include "vmw3.c" /* Windows virtual memory */ +#include "protw3.c" /* Windows protection */ +#include "proti3.c" /* 32-bit Intel mutator context decoding */ +#include "prmci3w3.c" /* Windows on 32-bit Intel mutator context */ +#include "ssw3i3pc.c" /* Windows on 32-bit stack scan for Pelles C */ +#include "spw3i3.c" /* 32-bit Intel stack probe */ +#include "mpsiw3.c" /* Windows interface layer extras */ + +/* Windows on 64-bit Intel with Pelles C */ + +#elif defined(MPS_PF_W3I6PC) + +#include "lockw3.c" /* Windows locks */ +#include "thw3.c" /* Windows threading */ +#include "thw3i6.c" /* Windows on 64-bit Intel thread stack scan */ +#include "vmw3.c" /* Windows virtual memory */ +#include "protw3.c" /* Windows protection */ +#include "proti6.c" /* 64-bit Intel mutator context decoding */ +#include "prmci6w3.c" /* Windows on 64-bit Intel mutator context */ +#include "ssw3i6pc.c" /* Windows on 64-bit stack scan for Pelles C */ +#include "spw3i6.c" /* 64-bit Intel stack probe */ #include "mpsiw3.c" /* Windows interface layer extras */ #else diff --git a/mps/code/mps.h b/mps/code/mps.h index 299684b781e..b948a5f8d7d 100644 --- a/mps/code/mps.h +++ b/mps/code/mps.h @@ -191,6 +191,9 @@ extern const struct mps_key_s _mps_key_align; extern const struct mps_key_s _mps_key_cbs_extend_by; #define MPS_KEY_CBS_EXTEND_BY (&_mps_key_cbs_extend_by) #define MPS_KEY_CBS_EXTEND_BY_FIELD size +extern const struct mps_key_s _mps_key_interior; +#define MPS_KEY_INTERIOR (&_mps_key_interior) +#define MPS_KEY_INTERIOR_FIELD b extern const struct mps_key_s _mps_key_vmw3_top_down; #define MPS_KEY_VMW3_TOP_DOWN (&_mps_key_vmw3_top_down) diff --git a/mps/code/mps.xcodeproj/project.pbxproj b/mps/code/mps.xcodeproj/project.pbxproj index cd178d5f855..1fa335aee26 100644 --- a/mps/code/mps.xcodeproj/project.pbxproj +++ b/mps/code/mps.xcodeproj/project.pbxproj @@ -5026,29 +5026,24 @@ GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.4; - OTHER_CFLAGS = ( - "-pedantic", - "-Wall", - "-Wextra", - "-Wwrite-strings", - "-Wno-extended-offsetof", - ); SDKROOT = macosx; SYMROOT = xc; WARNING_CFLAGS = ( "-pedantic", - "-Wpointer-arith", - "-Wstrict-prototypes", - "-Wmissing-prototypes", - "-Winline", "-Waggregate-return", - "-Wnested-externs", - "-Wcast-qual", - "-Wshadow", "-Wall", + "-Wcast-qual", "-Wextra", - "-Wwrite-strings", + "-Winline", + "-Wmissing-prototypes", + "-Wnested-externs", "-Wno-extended-offsetof", + "-Wpointer-arith", + "-Wshadow", + "-Wstrict-aliasing=2", + "-Wstrict-prototypes", + "-Wunreachable-code", + "-Wwrite-strings", ); }; name = RASH; @@ -5470,29 +5465,24 @@ GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.4; ONLY_ACTIVE_ARCH = YES; - OTHER_CFLAGS = ( - "-pedantic", - "-Wall", - "-Wextra", - "-Wwrite-strings", - "-Wno-extended-offsetof", - ); SDKROOT = macosx; SYMROOT = xc; WARNING_CFLAGS = ( "-pedantic", - "-Wpointer-arith", - "-Wstrict-prototypes", - "-Wmissing-prototypes", - "-Winline", "-Waggregate-return", - "-Wnested-externs", - "-Wcast-qual", - "-Wshadow", "-Wall", + "-Wcast-qual", "-Wextra", - "-Wwrite-strings", + "-Winline", + "-Wmissing-prototypes", + "-Wnested-externs", "-Wno-extended-offsetof", + "-Wpointer-arith", + "-Wshadow", + "-Wstrict-aliasing=2", + "-Wstrict-prototypes", + "-Wunreachable-code", + "-Wwrite-strings", ); }; name = Debug; @@ -5528,29 +5518,24 @@ GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.4; - OTHER_CFLAGS = ( - "-pedantic", - "-Wall", - "-Wextra", - "-Wwrite-strings", - "-Wno-extended-offsetof", - ); SDKROOT = macosx; SYMROOT = xc; WARNING_CFLAGS = ( "-pedantic", - "-Wpointer-arith", - "-Wstrict-prototypes", - "-Wmissing-prototypes", - "-Winline", "-Waggregate-return", - "-Wnested-externs", - "-Wcast-qual", - "-Wshadow", "-Wall", + "-Wcast-qual", "-Wextra", - "-Wwrite-strings", + "-Winline", + "-Wmissing-prototypes", + "-Wnested-externs", "-Wno-extended-offsetof", + "-Wpointer-arith", + "-Wshadow", + "-Wstrict-aliasing=2", + "-Wstrict-prototypes", + "-Wunreachable-code", + "-Wwrite-strings", ); }; name = Release; diff --git a/mps/code/mpsi.c b/mps/code/mpsi.c index 1d52208be9a..3df0913df83 100644 --- a/mps/code/mpsi.c +++ b/mps/code/mpsi.c @@ -1,7 +1,7 @@ /* mpsi.c: MEMORY POOL SYSTEM C INTERFACE LAYER * * $Id$ - * Copyright (c) 2001-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. * * .purpose: This code bridges between the MPS interface to C, @@ -46,11 +46,6 @@ #include "mpm.h" #include "mps.h" #include "sac.h" -#include "chain.h" - -/* TODO: Remove these includes when varargs support is removed. */ -#include "mpsacl.h" -#include "mpsavm.h" #include @@ -459,7 +454,7 @@ mps_res_t mps_fmt_create_k(mps_fmt_t *mps_fmt_o, AVER(mps_fmt_o != NULL); AVERT(Arena, arena); - AVER(ArgListCheck(args)); + AVERT(ArgList, args); res = FormatCreate(&format, arena, args); @@ -657,7 +652,7 @@ mps_res_t mps_pool_create_k(mps_pool_t *mps_pool_o, mps_arena_t arena, AVER(mps_pool_o != NULL); AVERT(Arena, arena); AVERT(PoolClass, class); - AVER(ArgListCheck(args)); + AVERT(ArgList, args); res = PoolCreate(&pool, arena, class, args); @@ -1737,12 +1732,12 @@ mps_word_t mps_telemetry_control(mps_word_t resetMask, mps_word_t flipMask) void mps_telemetry_set(mps_word_t setMask) { - EventControl((Word)setMask, (Word)setMask); + (void)EventControl((Word)setMask, (Word)setMask); } void mps_telemetry_reset(mps_word_t resetMask) { - EventControl((Word)resetMask, 0); + (void)EventControl((Word)resetMask, 0); } mps_word_t mps_telemetry_get(void) @@ -1935,7 +1930,7 @@ void mps_chain_destroy(mps_chain_t chain) /* 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/mpsicv.c b/mps/code/mpsicv.c index 3f8d05b92e0..a4d8c3750b5 100644 --- a/mps/code/mpsicv.c +++ b/mps/code/mpsicv.c @@ -94,8 +94,6 @@ struct tlonglong { /* alignmentTest -- test default alignment is acceptable */ -#define max(a, b) (((a) > (b)) ? (a) : (b)) - static void alignmentTest(mps_arena_t arena) { mps_pool_t pool; @@ -404,7 +402,7 @@ static void *test(void *arg, size_t s) if (rnd() & 1) { printf("Using auto_header format.\n"); - EnsureHeaderFormat(&format, arena); + die(EnsureHeaderFormat(&format, arena), "EnsureHeaderFormat"); ap_headerSIZE = headerSIZE; /* from fmthe.h */ } else { printf("Using normal format (no implicit object header: client pointers point at start of storage).\n"); @@ -518,7 +516,8 @@ static void *test(void *arg, size_t s) if (rnd() % patternFREQ == 0) { switch(rnd() % 4) { - case 0: case 1: + case 0: /* fall through */ + case 1: die(mps_ap_alloc_pattern_begin(ap, ramp), "alloc_pattern_begin"); ++rampCount; break; @@ -530,7 +529,7 @@ static void *test(void *arg, size_t s) --rampCount; } break; - case 3: + default: die(mps_ap_alloc_pattern_reset(ap), "alloc_pattern_reset"); rampCount = 0; break; diff --git a/mps/code/mpsliban.c b/mps/code/mpsliban.c index e84b2aed00d..75a3d48d518 100644 --- a/mps/code/mpsliban.c +++ b/mps/code/mpsliban.c @@ -65,9 +65,9 @@ static void mps_lib_assert_fail_default(const char *file, unsigned line, const char *condition) { - fflush(stdout); /* synchronize */ - fprintf(stderr, "%s:%u: MPS ASSERTION FAILED: %s\n", file, line, condition); - fflush(stderr); /* make sure the message is output */ + (void)fflush(stdout); /* synchronize */ + (void)fprintf(stderr, "%s:%u: MPS ASSERTION FAILED: %s\n", file, line, condition); + (void)fflush(stderr); /* make sure the message is output */ ASSERT_ABORT(); /* see config.h */ } diff --git a/mps/code/mpstd.h b/mps/code/mpstd.h index 88b4575155a..1306281224b 100644 --- a/mps/code/mpstd.h +++ b/mps/code/mpstd.h @@ -31,9 +31,12 @@ * Alignment of 4 would work, but the MS library uses 8 bytes for * doubles and __int64, so we choose that. The actual granularity of * VC malloc is 16! + * + * PellesC /Ze (Microsoft compatibility mode) defines _MSC_VER but + * isn't compatible enough for MPS purposes. */ -#if defined(_MSC_VER) && defined(_WIN32) && defined(_M_IX86) +#if defined(_MSC_VER) && defined(_WIN32) && defined(_M_IX86) && !defined(__POCC__) #if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_W3I3MV) #error "specified CONFIG_PF_... inconsistent with detected w3i3mv" #endif @@ -58,7 +61,7 @@ * */ -#elif defined(_MSC_VER) && defined(_WIN32) && defined(_WIN64) && defined(_M_X64) +#elif defined(_MSC_VER) && defined(_WIN32) && defined(_WIN64) && defined(_M_X64) && !defined(__POCC__) #if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_W3I6MV) #error "specified CONFIG_PF_... inconsistent with detected w3i6mv" #endif @@ -74,6 +77,47 @@ #define MPS_PF_ALIGN 16 +/* PellesC version 7.00.25 with /Ze option (Microsoft compatibility mode) + * Help node "Predefined preprocessor symbols (POCC)" + */ + +#elif defined(__POCC__) && defined(_WIN32) && defined(_M_IX86) +#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_W3I3PC) +#error "specified CONFIG_PF_... inconsistent with detected w3i3pc" +#endif +#define MPS_PF_W3I3PC +#define MPS_PF_STRING "w3i3pc" +#define MPS_OS_W3 +#define MPS_ARCH_I3 +#define MPS_BUILD_PC +#define MPS_T_WORD unsigned long +#define MPS_T_ULONGEST unsigned long +#define MPS_WORD_WIDTH 32 +#define MPS_WORD_SHIFT 5 +#define MPS_PF_ALIGN 8 + + +/* PellesC version 7.00.25 with /Ze option (Microsoft compatibility mode) + * and /Tarm64-coff (Create a COFF object file for a X64 processor). + * Help node "Predefined preprocessor symbols (POCC)" + */ + +#elif defined(__POCC__) && defined(_WIN32) && defined(_WIN64) && defined(_M_X64) +#if defined(CONFIG_PF_STRING) && ! defined(CONFIG_PF_W3I6PC) +#error "specified CONFIG_PF_... inconsistent with detected w3i6pc" +#endif +#define MPS_PF_W3I6PC +#define MPS_PF_STRING "w3i6pc" +#define MPS_OS_W3 +#define MPS_ARCH_I6 +#define MPS_BUILD_PC +#define MPS_T_WORD unsigned __int64 +#define MPS_T_ULONGEST unsigned __int64 +#define MPS_WORD_WIDTH 64 +#define MPS_WORD_SHIFT 6 +#define MPS_PF_ALIGN 16 + + /* GCC 4.0.1 (As supplied by Apple on Mac OS X 10.4.8 on an Intel Mac), * gcc -E -dM * And above for xcppgc. diff --git a/mps/code/mpsw3.h b/mps/code/mpsw3.h index 2f543ddc0f8..f32b7a09831 100644 --- a/mps/code/mpsw3.h +++ b/mps/code/mpsw3.h @@ -11,7 +11,7 @@ #define mpsw3_h #include "mps.h" /* needed for mps_tramp_t */ -#include /* needed for SEH filter */ +#include "mpswin.h" /* needed for SEH filter */ extern LONG mps_SEH_filter(LPEXCEPTION_POINTERS, void **, size_t *); diff --git a/mps/code/mpswin.h b/mps/code/mpswin.h index 99317fb790a..0840f1371a3 100644 --- a/mps/code/mpswin.h +++ b/mps/code/mpswin.h @@ -1,7 +1,7 @@ /* mpswin.h: RAVENBROOK MEMORY POOL SYSTEM WINDOWS.H INTERFACE * * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * .readership: For MPS client application developers, MPS developers. * @@ -11,29 +11,18 @@ #ifndef mpswin_h #define mpswin_h -/* Suppress Visual C warnings from windows.h at warning level 4. */ -#ifdef MPS_BUILD_MV -#pragma warning(disable: 4115 4201 4209 4214) -#endif - +/* Speed up the build process by excluding parts of windows.h that we + * don't use. See */ +#define WIN32_LEAN_AND_MEAN #include - -#ifdef MPS_BUILD_MV -#pragma warning(default: 4115 4201 4209 4214) -/* windows.h might also cause warnings about "unreferenced inline - * function has been removed". In Visual C, these can be turned off: - * #pragma warning(disable: 4514) - * But they are generated at the end of the compilation, so you have - * to turn them off permanently. - */ -#endif +#undef WIN32_LEAN_AND_MEAN #endif /* mpswin_h */ /* 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/mv.nmk b/mps/code/mv.nmk new file mode 100644 index 00000000000..d0759bad532 --- /dev/null +++ b/mps/code/mv.nmk @@ -0,0 +1,78 @@ +# -*- makefile -*- +# +# mv.nmk: NMAKE FRAGMENT FOR MICROSOFT VISUAL C/C++ +# +# $Id$ +# Copyright (c) 2014 Ravenbrook Limited. See end of file for license. +# +# This file is included by platform nmake files that use the Microsoft +# Visual C/C+ compiler. It defines the compiler-specific variables +# that the common nmake file fragment () requires. + +CC = cl +LIBMAN = lib +LINKER = link + +# /D_CRT_SECURE_NO_WARNINGS suppresses "This function or variable may +# be unsafe" warnings for standard C library functions fopen, getenv, +# snprintf, sscanf, strcpy, and so on. +# +# /Gs appears to be necessary to suppress stack checks. Stack checks +# (if not suppressed) generate a dependency on the C library, __chkesp, +# which causes the linker step to fail when building the DLL, mpsdy.dll. +CFLAGSCOMMONPRE = $(CFLAGSCOMMONPRE) /D_CRT_SECURE_NO_WARNINGS /W4 /WX /Gs /Fd$(PFM)\$(VARIETY) +LIBFLAGSCOMMON = $(LIBFLAGSCOMMON) /nologo + +# /MD means compile for multi-threaded environment with separate C library DLL. +# /MT means compile for multi-threaded environment. +# /ML means compile for single-threaded environment. +# A 'd' at the end means compile for debugging. +CRTFLAGSHOT = $(CRTFLAGSHOT) /MT +CRTFLAGSCOOL = $(CRTFLAGSCOOL) /MTd + +CFLAGSCOOL = $(CFLAGSCOOL) /Od + +LINKFLAGSCOMMON = $(LINKFLAGSCOMMON) /PDB:$*.pdb +LINKFLAGSHOT = $(LINKFLAGSHOT) libcmt.lib +LINKFLAGSCOOL = $(LINKFLAGSCOOL) libcmtd.lib + + +# C. COPYRIGHT AND LICENSE +# +# Copyright (C) 2014 Ravenbrook Limited . +# All rights reserved. This is an open source license. Contact +# Ravenbrook for commercial licensing options. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Redistributions in any form must be accompanied by information on how +# to obtain complete source code for this software and any accompanying +# software that uses this software. The source code must either be +# included in the distribution or be available for no more than the cost +# of distribution plus a nominal fee, and must be freely redistributable +# under reasonable conditions. For an executable file, complete source +# code means the source code for all modules it contains. It does not +# include source code for modules or files that typically accompany the +# major components of the operating system on which the executable file +# runs. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mps/code/mv2test.c b/mps/code/mv2test.c index bc276abfc26..40d53d0589f 100644 --- a/mps/code/mv2test.c +++ b/mps/code/mv2test.c @@ -38,11 +38,9 @@ static double expdev(void) } -#define max(a, b) (((a) > (b)) ? (a) : (b)) - -static size_t min; -static size_t mean; -static size_t max; +static size_t size_min; +static size_t size_mean; +static size_t size_max; static int verbose = 0; static mps_pool_t pool; @@ -50,8 +48,8 @@ static size_t randomSize(unsigned long i) { /* Distribution centered on mean. Verify that allocations below min and above max are handled correctly */ - size_t s = (max - mean)/4; - size_t m = mean; + size_t s = (size_max - size_mean)/4; + size_t m = size_mean; double r; double x; @@ -73,8 +71,6 @@ static size_t randomSize(unsigned long i) #define TEST_SET_SIZE 1234 #define TEST_LOOPS 27 -#define alignUp(w, a) (((w) + (a) - 1) & ~((size_t)(a) - 1)) - static mps_res_t make(mps_addr_t *p, mps_ap_t ap, size_t size) { mps_res_t res; @@ -177,19 +173,18 @@ static void stress_with_arena_class(mps_arena_class_t aclass, Bool zoned) MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE); MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, zoned); - MPS_ARGS_DONE(args); die(mps_arena_create_k(&arena, aclass, args), "mps_arena_create"); } MPS_ARGS_END(args); - min = MPS_PF_ALIGN; - mean = 42; - max = 8192; + size_min = MPS_PF_ALIGN; + size_mean = 42; + size_max = 8192; MPS_ARGS_BEGIN(args) { - MPS_ARGS_ADD(args, MPS_KEY_MIN_SIZE, min); - MPS_ARGS_ADD(args, MPS_KEY_MEAN_SIZE, mean); - MPS_ARGS_ADD(args, MPS_KEY_MAX_SIZE, max); + MPS_ARGS_ADD(args, MPS_KEY_MIN_SIZE, size_min); + MPS_ARGS_ADD(args, MPS_KEY_MEAN_SIZE, size_mean); + MPS_ARGS_ADD(args, MPS_KEY_MAX_SIZE, size_max); MPS_ARGS_ADD(args, MPS_KEY_MVT_RESERVE_DEPTH, TEST_SET_SIZE/2); MPS_ARGS_ADD(args, MPS_KEY_MVT_FRAG_LIMIT, 0.3); die(stress(mps_class_mvt(), arena, randomSize, args), "stress MVT"); diff --git a/mps/code/nailboard.c b/mps/code/nailboard.c index 69adde5a6c3..8744514662b 100644 --- a/mps/code/nailboard.c +++ b/mps/code/nailboard.c @@ -13,22 +13,31 @@ SRCID(nailboard, "$Id$"); + +/* Log2 of scale factor between levels. See . */ #define LEVEL_SHIFT MPS_WORD_SHIFT + /* nailboardLevels -- return the number of levels in a nailboard with * the given number of nails. + * + * See */ + static Count nailboardLevels(Count nails) { - return SizeRoundUp(SizeFloorLog2(nails) + 1, LEVEL_SHIFT) / LEVEL_SHIFT; + return (SizeFloorLog2((Size)nails) + LEVEL_SHIFT) / LEVEL_SHIFT; } + /* nailboardLevelBits -- return the number of bits in the bit table * for the given level. */ + static Count nailboardLevelBits(Nailboard board, Index level) { - /* Don't AVER(level < board->levels): see .check.levels */ + /* Use <= rather than < because of .check.levels. */ + AVER(level <= board->levels); return RangeSize(&board->range) >> (board->alignShift + level * LEVEL_SHIFT); } @@ -48,19 +57,23 @@ Bool NailboardCheck(Nailboard board) return TRUE; } + /* nailboardStructSize -- return the size of the nailboard structure, * plus the array of pointers to levels. */ + static Size nailboardStructSize(Count levels) { return offsetof(NailboardStruct, level) + sizeof(BT *) * levels; } + /* nailboardSize -- return the total size of the nailboard * * This is the size of the nailboard structure plus the combined sizes * of the bit tables. */ + static Size nailboardSize(Count nails, Count levels) { Index i; @@ -73,6 +86,7 @@ static Size nailboardSize(Count nails, Count levels) return size; } + /* NailboardCreate -- allocate a nailboard * * Allocate a nailboard in the control pool for arena, to cover the @@ -83,11 +97,13 @@ static Size nailboardSize(Count nails, Count levels) * alignment specifies the granularity of the nails: that is, the * number of bytes covered by each nail. */ + Res NailboardCreate(Nailboard *boardReturn, Arena arena, Align alignment, Addr base, Addr limit) { void *p; Nailboard board; + Shift alignShift; Count nails, levels; Index i; Res res; @@ -99,7 +115,8 @@ Res NailboardCreate(Nailboard *boardReturn, Arena arena, Align alignment, AVER(AddrIsAligned(base, alignment)); AVER(AddrIsAligned(limit, alignment)); - nails = AddrOffset(base, limit) / alignment; + alignShift = SizeLog2((Size)alignment); + nails = AddrOffset(base, limit) >> alignShift; levels = nailboardLevels(nails); res = ControlAlloc(&p, arena, nailboardSize(nails, levels), FALSE); if (res != ResOK) @@ -108,81 +125,94 @@ Res NailboardCreate(Nailboard *boardReturn, Arena arena, Align alignment, board = p; RangeInit(&board->range, base, limit); board->levels = levels; - board->alignShift = SizeLog2(alignment); + board->alignShift = alignShift; board->newNails = FALSE; - p = AddrAdd(p, nailboardStructSize(levels)); + p = PointerAdd(p, nailboardStructSize(levels)); for (i = 0; i < levels; ++i) { AVER(nails > 0); board->level[i] = p; BTResRange(board->level[i], 0, nails); - p = AddrAdd(p, BTSize(nails)); + p = PointerAdd(p, BTSize(nails)); nails >>= LEVEL_SHIFT; } - + board->sig = NailboardSig; AVERT(Nailboard, board); *boardReturn = board; return ResOK; } + /* NailboardDestroy -- destroy a nailboard */ void NailboardDestroy(Nailboard board, Arena arena) { + Count nails; Size size; AVERT(Nailboard, board); AVERT(Arena, arena); - size = nailboardSize(nailboardLevelBits(board, 0), board->levels); + nails = nailboardLevelBits(board, 0); + size = nailboardSize(nails, board->levels); board->sig = SigInvalid; ControlFree(arena, board, size); } + /* NailboardClearNewNails -- clear the "new nails" flag */ void (NailboardClearNewNails)(Nailboard board) { AVERT(Nailboard, board); - board->newNails = FALSE; + NailboardClearNewNails(board); } + /* NailboardNewNails -- return the "new nails" flag * * Return TRUE if any new nails have been set in the nailboard since * the last call to NailboardClearNewNails (or since the nailboard was * created, if there have never been any such calls), FALSE otherwise. */ + Bool (NailboardNewNails)(Nailboard board) { AVERT(Nailboard, board); - return board->newNails; + return NailboardNewNails(board); } + /* nailboardIndex -- return the index of the nail corresponding to * addr in the given level. */ + static Index nailboardIndex(Nailboard board, Index level, Addr addr) { return AddrOffset(RangeBase(&board->range), addr) >> (board->alignShift + level * LEVEL_SHIFT); } + /* nailboardAddr -- return the address corresponding to the index in * the given level. */ + static Addr nailboardAddr(Nailboard board, Index level, Index index) { return AddrAdd(RangeBase(&board->range), index << (board->alignShift + level * LEVEL_SHIFT)); } + /* nailboardIndexRange -- update *ibaseReturn and *ilimitReturn to be - * the indexes of the nail corresponding to base and limit - * respectively, in the given level. See .impl.isresrange.alignment. + * the interval of indexes of nails in the given level, corresponding + * to the interval of addresses base and limit. See + * . */ + static void nailboardIndexRange(Index *ibaseReturn, Index *ilimitReturn, Nailboard board, Index level, Addr base, Addr limit) @@ -191,12 +221,14 @@ static void nailboardIndexRange(Index *ibaseReturn, Index *ilimitReturn, *ilimitReturn = nailboardIndex(board, level, AddrSub(limit, 1)) + 1; } + /* NailboardGet -- return nail corresponding to address * * Return the nail in the nailboard corresponding to the address addr. * It is an error if addr does not lie in the range of addresses * covered by the nailboard. */ + Bool NailboardGet(Nailboard board, Addr addr) { AVERT(Nailboard, board); @@ -204,12 +236,17 @@ Bool NailboardGet(Nailboard board, Addr addr) return BTGet(board->level[0], nailboardIndex(board, 0, addr)); } + /* NailboardSet -- set nail corresponding to address * * Set the nail in the nailboard corresponding to the address addr. * Return the old nail at that position. It is an error if addr does * not lie in the range of addresses covered by the nailboard. + * + * This function is on the critical path because it is called for + * every fix of an ambiguous reference to an address in an AMC pool. */ + Bool NailboardSet(Nailboard board, Addr addr) { Index i, j; @@ -232,12 +269,14 @@ Bool NailboardSet(Nailboard board, Addr addr) return FALSE; } + /* NailboardSetRange -- set all nails in range * * Set all nails in the nailboard corresponding to the range between * base and limit. It is an error if any part of the range is not * covered by the nailboard, or if any nail in the range is set. */ + void NailboardSetRange(Nailboard board, Addr base, Addr limit) { Index i, ibase, ilimit; @@ -250,14 +289,18 @@ void NailboardSetRange(Nailboard board, Addr base, Addr limit) } } + /* NailboardIsSetRange -- test if all nails are set in a range * * Return TRUE if all nails are set in the range between base and * limit, or FALSE if any nail is unset. It is an error if any part of * the range is not covered by the nailboard. * - * This function is not expected to be efficient. + * This function is not expected to be efficient because it is only + * used in an AVER in AMCWhiten to check that the unused part of the + * buffer for a nailboarded segment has in fact been nailed. */ + Bool NailboardIsSetRange(Nailboard board, Addr base, Addr limit) { Index ibase, ilimit; @@ -266,6 +309,7 @@ Bool NailboardIsSetRange(Nailboard board, Addr base, Addr limit) return BTIsSetRange(board->level[0], ibase, ilimit); } + /* NailboardIsResRange -- test if all nails are reset in a range * * Return TRUE if no nails are set in the range between base and @@ -276,8 +320,9 @@ Bool NailboardIsSetRange(Nailboard board, Addr base, Addr limit) * object in every nailed segment. It must take time that is no more * than logarithmic in the size of the range. * - * See . + * See . */ + Bool NailboardIsResRange(Nailboard board, Addr base, Addr limit) { Index i, ibase, ilimit; @@ -286,19 +331,32 @@ Bool NailboardIsResRange(Nailboard board, Addr base, Addr limit) AVERT_CRITICAL(Nailboard, board); - for (i = board->levels - 1;; --i) { + /* Descend levels until ibase and ilimit are two or more bits apart: + * that is, until there is an "inner" part to the range. */ + i = board->levels; + do { + -- i; nailboardIndexRange(&ibase, &ilimit, board, i, base, limit); if (BTIsResRange(board->level[i], ibase, ilimit)) - return TRUE; /* */ + /* The entire range was clear. This is expected to be the common + * case. */ + return TRUE; if (i == 0) - return FALSE; /* */ - if (ibase + 1 < ilimit - 1) { - if (BTIsResRange(board->level[i], ibase + 1, ilimit - 1)) - break; - else - return FALSE; /* */ - } - } + /* At level 0 there is only one nail per bit so the set bit is known + * to be within the range. */ + return FALSE; + } while (ibase + 1 >= ilimit - 1); + + /* At this point we know there is an "inner" part. Are there any + * bits set in it? */ + if (!BTIsResRange(board->level[i], ibase + 1, ilimit - 1)) + return FALSE; + + /* At this point we know that in level i, there is is a bit set at + * ibase or at ilimit - 1 (or both), and everything between them is + * reset. */ + AVER_CRITICAL(BTGet(board->level[i], ibase) + || BTGet(board->level[i], ilimit - 1)); /* Left splinter */ for (j = i, jbase = ibase;;) { @@ -308,7 +366,7 @@ Bool NailboardIsResRange(Nailboard board, Addr base, Addr limit) -- j; nailboardIndexRange(&jbase, &jlimit, board, j, base, leftLimit); if (jbase + 1 < jlimit && !BTIsResRange(board->level[j], jbase + 1, jlimit)) - return FALSE; /* */ + return FALSE; /* */ if (!BTGet(board->level[j], jbase)) break; if (j == 0) @@ -323,7 +381,7 @@ Bool NailboardIsResRange(Nailboard board, Addr base, Addr limit) -- j; nailboardIndexRange(&jbase, &jlimit, board, j, rightBase, limit); if (jbase < jlimit - 1 && !BTIsResRange(board->level[j], jbase, jlimit - 1)) - return FALSE; /* */ + return FALSE; /* */ if (!BTGet(board->level[j], jlimit - 1)) break; if (j == 0) @@ -333,6 +391,7 @@ Bool NailboardIsResRange(Nailboard board, Addr base, Addr limit) return TRUE; } + Res NailboardDescribe(Nailboard board, mps_lib_FILE *stream) { Index i, j; diff --git a/mps/code/nailboard.h b/mps/code/nailboard.h index 0763ef405c0..66141067f5f 100644 --- a/mps/code/nailboard.h +++ b/mps/code/nailboard.h @@ -14,6 +14,13 @@ typedef struct NailboardStruct *Nailboard; +/* NOTE: we could reduce the size of this structure using bitfields. + * levels can be at most MPS_WORD_WIDTH / LEVEL_SHIFT + 1, which is 11 + * on 64-bit, so it would fit in 4 bits. (Or it could be recalculated + * from range each time it's needed.) alignShift is at most + * MPS_WORD_SHIFT so would fit in 3 bits. (Or it could be supplied in + * each function call by the owner.) newNails would fit in 1 bit. + */ typedef struct NailboardStruct { Sig sig; RangeStruct range; /* range of addresses covered by nailboard */ diff --git a/mps/code/nailboardtest.c b/mps/code/nailboardtest.c index c2baaad210f..a78ba4b3b9e 100644 --- a/mps/code/nailboardtest.c +++ b/mps/code/nailboardtest.c @@ -53,8 +53,8 @@ int main(int argc, char **argv) { mps_arena_t arena; - randomize(argc, argv); - mps_lib_assert_fail_install(assert_die); + testlib_init(argc, argv); + die(mps_arena_create(&arena, mps_arena_class_vm(), 1024 * 1024), "mps_arena_create"); diff --git a/mps/code/pc.nmk b/mps/code/pc.nmk new file mode 100644 index 00000000000..e52addfba4c --- /dev/null +++ b/mps/code/pc.nmk @@ -0,0 +1,59 @@ +# -*- makefile -*- +# +# pc.nmk: NMAKE FRAGMENT FOR PELLES C +# +# $Id$ +# Copyright (c) 2014 Ravenbrook Limited. See end of file for license. +# +# This file is included by platform nmake files that use the Pelles C +# compiler. It defines the compiler-specific variables that the common +# nmake file fragment () requires. + +CC = pocc +LIBMAN = polib +LINKER = polink + +CFLAGSCOMMONPRE = $(CFLAGSCOMMONPRE) /Ze /W2 +CRTFLAGSHOT = /MT +CRTFLAGSCOOL = /MT + + +# C. COPYRIGHT AND LICENSE +# +# Copyright (C) 2014 Ravenbrook Limited . +# All rights reserved. This is an open source license. Contact +# Ravenbrook for commercial licensing options. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Redistributions in any form must be accompanied by information on how +# to obtain complete source code for this software and any accompanying +# software that uses this software. The source code must either be +# included in the distribution or be available for no more than the cost +# of distribution plus a nominal fee, and must be freely redistributable +# under reasonable conditions. For an executable file, complete source +# code means the source code for all modules it contains. It does not +# include source code for modules or files that typically accompany the +# major components of the operating system on which the executable file +# runs. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mps/code/pool.c b/mps/code/pool.c index 0524d69525c..5741470457a 100644 --- a/mps/code/pool.c +++ b/mps/code/pool.c @@ -18,9 +18,6 @@ * .purpose.dispatch: Dispatch functions that implement the generic * function dispatch mechanism for Pool Classes (PoolAlloc, PoolFix, * etc.). - * .purpose.core: A selection of default, trivial, or useful methods - * that Pool Classes can use as the implementations for some of their - * methods (such as PoolTrivWhiten, PoolNoFix, etc.). * * SOURCES * @@ -40,13 +37,14 @@ SRCID(pool, "$Id$"); Bool PoolClassCheck(PoolClass class) { - CHECKL(ProtocolClassCheck(&class->protocol)); + CHECKD(ProtocolClass, &class->protocol); CHECKL(class->name != NULL); /* Should be <=6 char C identifier */ CHECKL(class->size >= sizeof(PoolStruct)); /* Offset of generic Pool within class-specific instance cannot be */ /* greater than the size of the class-specific portion of the instance */ CHECKL(class->offset <= (size_t)(class->size - sizeof(PoolStruct))); CHECKL(AttrCheck(class->attr)); + CHECKL(!(class->attr & AttrMOVINGGC) || (class->attr & AttrGC)); CHECKL(FUNCHECK(class->varargs)); CHECKL(FUNCHECK(class->init)); CHECKL(FUNCHECK(class->finish)); @@ -89,16 +87,14 @@ Bool PoolCheck(Pool pool) CHECKL(pool->serial < ArenaGlobals(pool->arena)->poolSerial); CHECKD(PoolClass, pool->class); CHECKU(Arena, pool->arena); - CHECKL(RingCheck(&pool->arenaRing)); - CHECKL(RingCheck(&pool->bufferRing)); + CHECKD_NOSIG(Ring, &pool->arenaRing); + CHECKD_NOSIG(Ring, &pool->bufferRing); /* Cannot check pool->bufferSerial */ - CHECKL(RingCheck(&pool->segRing)); + CHECKD_NOSIG(Ring, &pool->segRing); CHECKL(AlignCheck(pool->alignment)); - /* normally pool->format iff pool->class->attr&AttrFMT, but not */ - /* during pool initialization */ - if (pool->format != NULL) { - CHECKL((pool->class->attr & AttrFMT) != 0); - } + /* normally pool->format iff PoolHasAttr(pool, AttrFMT), but during + * pool initialization pool->format may not yet be set. */ + CHECKL(pool->format == NULL || PoolHasAttr(pool, AttrFMT)); CHECKL(pool->fillMutatorSize >= 0.0); CHECKL(pool->emptyMutatorSize >= 0.0); CHECKL(pool->fillInternalSize >= 0.0); @@ -118,6 +114,7 @@ ARG_DEFINE_KEY(min_size, Size); ARG_DEFINE_KEY(mean_size, Size); ARG_DEFINE_KEY(max_size, Size); ARG_DEFINE_KEY(align, Align); +ARG_DEFINE_KEY(interior, Bool); /* PoolInit -- initialize a pool @@ -288,9 +285,9 @@ Res PoolAlloc(Addr *pReturn, Pool pool, Size size, AVER(pReturn != NULL); AVERT(Pool, pool); - AVER((pool->class->attr & AttrALLOC) != 0); + AVER(PoolHasAttr(pool, AttrALLOC)); AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); res = (*pool->class->alloc)(pReturn, pool, size, withReservoirPermit); if (res != ResOK) @@ -318,7 +315,7 @@ Res PoolAlloc(Addr *pReturn, Pool pool, Size size, void PoolFree(Pool pool, Addr old, Size size) { AVERT(Pool, pool); - AVER((pool->class->attr & AttrFREE) != 0); + AVER(PoolHasAttr(pool, AttrFREE)); AVER(old != NULL); /* The pool methods should check that old is in pool. */ AVER(size > 0); @@ -383,6 +380,7 @@ Res PoolScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) AVER(totalReturn != NULL); AVERT(ScanState, ss); AVERT(Pool, pool); + AVER(PoolHasAttr(pool, AttrSCAN)); AVERT(Seg, seg); AVER(ss->arena == pool->arena); diff --git a/mps/code/poolabs.c b/mps/code/poolabs.c index af355577cc5..aa2ee5adcbd 100644 --- a/mps/code/poolabs.c +++ b/mps/code/poolabs.c @@ -1,7 +1,7 @@ /* poolabs.c: ABSTRACT POOL CLASSES * * $Id$ - * Copyright (c) 2001 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. * * PURPOSE @@ -65,12 +65,13 @@ void PoolClassMixInAllocFree(PoolClass class) void PoolClassMixInBuffer(PoolClass class) { /* Can't check class because it's not initialized yet */ - class->attr |= (AttrBUF | AttrBUF_RESERVE); + class->attr |= AttrBUF; class->bufferFill = PoolTrivBufferFill; class->bufferEmpty = PoolTrivBufferEmpty; /* By default, buffered pools treat frame operations as NOOPs */ class->framePush = PoolTrivFramePush; class->framePop = PoolTrivFramePop; + class->framePopPending = PoolTrivFramePopPending; class->bufferClass = BufferClassGet; } @@ -84,8 +85,10 @@ void PoolClassMixInScan(PoolClass class) class->access = PoolSegAccess; class->blacken = PoolTrivBlacken; class->grey = PoolTrivGrey; - /* Scan is part of the scanning protocol - but there is */ - /* no useful default method */ + /* scan is part of the scanning protocol, but there is no useful + * default method. + */ + class->scan = NULL; } @@ -95,6 +98,10 @@ void PoolClassMixInFormat(PoolClass class) { /* Can't check class because it's not initialized yet */ class->attr |= AttrFMT; + /* walk is part of the format protocol, but there is no useful + * default method. + */ + class->walk = NULL; } @@ -103,10 +110,14 @@ void PoolClassMixInFormat(PoolClass class) void PoolClassMixInCollect(PoolClass class) { /* Can't check class because it's not initialized yet */ - class->attr |= (AttrGC | AttrINCR_RB); + class->attr |= AttrGC; class->whiten = PoolTrivWhiten; - /* Fix & reclaim are part of the collection protocol - but there */ - /* are no useful default methods for them. */ + /* fix, fixEmergency and reclaim are part of the collection + * protocol, but there are no useful default methods for them. + */ + class->fix = NULL; + class->fixEmergency = NULL; + class->reclaim = NULL; class->rampBegin = PoolTrivRampBegin; class->rampEnd = PoolTrivRampEnd; } @@ -145,7 +156,7 @@ DEFINE_CLASS(AbstractPoolClass, class) class->framePopPending = PoolNoFramePopPending; class->addrObject = PoolNoAddrObject; class->walk = PoolNoWalk; - class->freewalk = PoolNoFreeWalk; + class->freewalk = PoolTrivFreeWalk; class->bufferClass = PoolNoBufferClass; class->describe = PoolTrivDescribe; class->debugMixin = PoolNoDebugMixin; @@ -199,7 +210,7 @@ void PoolTrivFinish(Pool pool) Res PoolTrivInit(Pool pool, ArgList args) { AVERT(Pool, pool); - AVER(ArgListCheck(args)); + AVERT(ArgList, args); UNUSED(args); return ResOK; } @@ -210,7 +221,7 @@ Res PoolNoAlloc(Addr *pReturn, Pool pool, Size size, AVER(pReturn != NULL); AVERT(Pool, pool); AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); NOTREACHED; return ResUNIMPL; } @@ -221,7 +232,7 @@ Res PoolTrivAlloc(Addr *pReturn, Pool pool, Size size, AVER(pReturn != NULL); AVERT(Pool, pool); AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); return ResLIMIT; } @@ -251,7 +262,7 @@ Res PoolNoBufferFill(Addr *baseReturn, Addr *limitReturn, AVERT(Pool, pool); AVERT(Buffer, buffer); AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); NOTREACHED; return ResUNIMPL; } @@ -268,7 +279,7 @@ Res PoolTrivBufferFill(Addr *baseReturn, Addr *limitReturn, AVERT(Pool, pool); AVERT(Buffer, buffer); AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); res = PoolAlloc(&p, pool, size, withReservoirPermit); if(res != ResOK) return res; @@ -596,7 +607,7 @@ Res PoolNoFramePop(Pool pool, Buffer buf, AllocFrame frame) { AVERT(Pool, pool); AVERT(Buffer, buf); - /* frame is of a abstract type & can't be checked */ + /* frame is of an abstract type & can't be checked */ UNUSED(frame); NOTREACHED; return ResUNIMPL; @@ -607,7 +618,7 @@ void PoolNoFramePopPending(Pool pool, Buffer buf, AllocFrame frame) { AVERT(Pool, pool); AVERT(Buffer, buf); - /* frame is of a abstract type & can't be checked */ + /* frame is of an abstract type & can't be checked */ UNUSED(frame); NOTREACHED; } @@ -626,12 +637,22 @@ Res PoolTrivFramePop(Pool pool, Buffer buf, AllocFrame frame) { AVERT(Pool, pool); AVERT(Buffer, buf); - /* frame is of a abstract type & can't be checked */ + /* frame is of an abstract type & can't be checked */ UNUSED(frame); return ResOK; } +void PoolTrivFramePopPending(Pool pool, Buffer buf, AllocFrame frame) +{ + AVERT(Pool, pool); + AVERT(Buffer, buf); + /* frame is of an abstract type & can't be checked */ + UNUSED(frame); + NOOP; +} + + Res PoolNoAddrObject(Addr *pReturn, Pool pool, Seg seg, Addr addr) { AVER(pReturn != NULL); @@ -656,7 +677,7 @@ void PoolNoWalk(Pool pool, Seg seg, } -void PoolNoFreeWalk(Pool pool, FreeBlockStepMethod f, void *p) +void PoolTrivFreeWalk(Pool pool, FreeBlockStepMethod f, void *p) { AVERT(Pool, pool); AVER(FUNCHECK(f)); @@ -677,7 +698,7 @@ BufferClass PoolNoBufferClass(void) /* 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/poolamc.c b/mps/code/poolamc.c index 79f043bb420..bbc582676a3 100644 --- a/mps/code/poolamc.c +++ b/mps/code/poolamc.c @@ -21,6 +21,10 @@ typedef struct AMCStruct *AMC; /* amcGen typedef */ typedef struct amcGenStruct *amcGen; +/* Function returning TRUE if block in nailboarded segment is pinned. */ +typedef Bool (*amcPinnedMethod)(AMC amc, Nailboard board, Addr base, Addr limit); + + /* forward declarations */ static Bool amcSegHasNailboard(Seg seg); @@ -337,6 +341,7 @@ DEFINE_SEG_CLASS(amcSegClass, class) class->size = sizeof(amcSegStruct); class->init = AMCSegInit; class->describe = AMCSegDescribe; + AVERT(SegClass, class); } @@ -456,6 +461,7 @@ typedef struct AMCStruct { /* */ amcGen afterRampGen; /* the generation after rampGen */ unsigned rampCount; /* */ int rampMode; /* */ + amcPinnedMethod pinned; /* function determining if block is pinned */ /* page retention in an in-progress trace */ STATISTIC_DECL(PageRetStruct pageretstruct[TraceLIMIT]); @@ -479,7 +485,7 @@ static Bool amcGenCheck(amcGen gen) amc = amcGenAMC(gen); CHECKU(AMC, amc); CHECKD(Buffer, gen->forward); - CHECKL(RingCheck(&gen->amcRing)); + CHECKD_NOSIG(Ring, &gen->amcRing); CHECKL((gen->pgen.totalSize == 0) == (gen->segs == 0)); arena = amc->poolStruct.arena; CHECKL(gen->pgen.totalSize >= gen->segs * ArenaAlign(arena)); @@ -521,7 +527,7 @@ typedef struct amcBufStruct { static Bool amcBufCheck(amcBuf amcbuf) { CHECKS(amcBuf, amcbuf); - CHECKL(SegBufCheck(&amcbuf->segbufStruct)); + CHECKD(SegBuf, &amcbuf->segbufStruct); if(amcbuf->gen != NULL) CHECKD(amcGen, amcbuf->gen); CHECKL(BoolCheck(amcbuf->forHashArrays)); @@ -627,6 +633,7 @@ DEFINE_BUFFER_CLASS(amcBufClass, class) class->size = sizeof(amcBufStruct); class->init = AMCBufInit; class->finish = AMCBufFinish; + AVERT(BufferClass, class); } @@ -742,6 +749,26 @@ static Res amcSegCreateNailboard(Seg seg, Pool pool) } +/* amcPinnedInterior -- block is pinned by any nail */ + +static Bool amcPinnedInterior(AMC amc, Nailboard board, Addr base, Addr limit) +{ + Size headerSize = AMC2Pool(amc)->format->headerSize; + return !NailboardIsResRange(board, AddrSub(base, headerSize), + AddrSub(limit, headerSize)); +} + + +/* amcPinnedBase -- block is pinned only if base is nailed */ + +static Bool amcPinnedBase(AMC amc, Nailboard board, Addr base, Addr limit) +{ + UNUSED(amc); + UNUSED(limit); + return NailboardGet(board, base); +} + + /* amcVarargs -- decode obsolete varargs */ static void AMCVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs) @@ -751,7 +778,7 @@ static void AMCVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs) args[1].key = MPS_KEY_CHAIN; args[1].val.chain = va_arg(varargs, Chain); args[2].key = MPS_KEY_ARGS_END; - AVER(ArgListCheck(args)); + AVERT(ArgList, args); } @@ -770,6 +797,7 @@ static Res amcInitComm(Pool pool, RankSet rankSet, ArgList args) Index i; size_t genArraySize; size_t genCount; + Bool interior = AMC_INTERIOR_DEFAULT; ArgStruct arg; /* Suppress a warning about this structure not being used when there @@ -793,6 +821,8 @@ static Res amcInitComm(Pool pool, RankSet rankSet, ArgList args) amc->chain = arg.val.chain; else amc->chain = ArenaGlobals(arena)->defaultChain; + if (ArgPick(&arg, args, MPS_KEY_INTERIOR)) + interior = arg.val.b; AVERT(Format, pool->format); AVERT(Chain, amc->chain); @@ -821,6 +851,12 @@ static Res amcInitComm(Pool pool, RankSet rankSet, ArgList args) pool->fix = AMCHeaderFix; } + if (interior) { + amc->pinned = amcPinnedInterior; + } else { + amc->pinned = amcPinnedBase; + } + amc->sig = AMCSig; AVERT(AMC, amc); @@ -1278,29 +1314,18 @@ static Res AMCWhiten(Pool pool, Trace trace, Seg seg) } -/* amcNailboardIsResClientRange -- wrapper for NailboardIsResRange, - * except that the addresses are client addresses for objects with the - * given header size. - */ -static Bool amcNailboardIsResClientRange(Nailboard board, Size headerSize, - Addr base, Addr limit) -{ - return NailboardIsResRange(board, AddrSub(base, headerSize), - AddrSub(limit, headerSize)); -} - - /* amcScanNailedRange -- make one scanning pass over a range of * addresses in a nailed segment. */ static Res amcScanNailedRange(Bool *totalReturn, Bool *moreReturn, Size *bytesScanned, ScanState ss, - Pool pool, Nailboard board, + AMC amc, Nailboard board, Addr base, Addr limit) { Format format; Size headerSize; Addr p, clientLimit; + Pool pool = AMC2Pool(amc); format = pool->format; headerSize = format->headerSize; p = AddrAdd(base, headerSize); @@ -1308,7 +1333,7 @@ static Res amcScanNailedRange(Bool *totalReturn, Bool *moreReturn, while (p < clientLimit) { Addr q; q = (*format->skip)(p); - if (!amcNailboardIsResClientRange(board, headerSize, p, q)) { + if ((*amc->pinned)(amc, board, p, q)) { Res res; res = (*format->scan)(&ss->ss_s, p, q); if(res != ResOK) { @@ -1338,7 +1363,7 @@ static Res amcScanNailedRange(Bool *totalReturn, Bool *moreReturn, * nailboard. */ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn, - ScanState ss, Pool pool, Seg seg, AMC amc) + ScanState ss, Seg seg, AMC amc) { Addr p, limit; Size bytesScanned = 0; @@ -1359,7 +1384,7 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn, goto returnGood; } res = amcScanNailedRange(totalReturn, moreReturn, &bytesScanned, - ss, pool, board, p, limit); + ss, amc, board, p, limit); if (res != ResOK) return res; p = limit; @@ -1368,7 +1393,7 @@ static Res amcScanNailedOnce(Bool *totalReturn, Bool *moreReturn, limit = SegLimit(seg); /* @@@@ Shouldn't p be set to BufferLimit here?! */ res = amcScanNailedRange(totalReturn, moreReturn, &bytesScanned, - ss, pool, board, p, limit); + ss, amc, board, p, limit); if (res != ResOK) return res; @@ -1392,7 +1417,7 @@ static Res amcScanNailed(Bool *totalReturn, ScanState ss, Pool pool, do { Res res; - res = amcScanNailedOnce(&total, &moreScanning, ss, pool, seg, amc); + res = amcScanNailedOnce(&total, &moreScanning, ss, seg, amc); if(res != ResOK) { *totalReturn = FALSE; return res; @@ -1653,7 +1678,7 @@ static Res AMCFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) /* If object is nailed already then we mustn't copy it: */ if (SegNailed(seg) != TraceSetEMPTY && !(amcSegHasNailboard(seg) - && NailboardIsResRange(amcSegNailboard(seg), ref, clientQ))) + && !(*amc->pinned)(amc, amcSegNailboard(seg), ref, clientQ))) { /* Segment only needs greying if there are new traces for */ /* which we are nailing. */ @@ -1800,8 +1825,7 @@ static Res AMCHeaderFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) /* If object is nailed already then we mustn't copy it: */ if (SegNailed(seg) != TraceSetEMPTY && !(amcSegHasNailboard(seg) - && amcNailboardIsResClientRange(amcSegNailboard(seg), - headerSize, ref, clientQ))) + && !(*amc->pinned)(amc, amcSegNailboard(seg), ref, clientQ))) { /* Segment only needs greying if there are new traces for */ /* which we are nailing. */ @@ -1917,8 +1941,7 @@ static void amcReclaimNailed(Pool pool, Trace trace, Seg seg) q = AddrSub(clientQ, headerSize); length = AddrOffset(p, q); if(amcSegHasNailboard(seg)) { - preserve = !amcNailboardIsResClientRange(amcSegNailboard(seg), headerSize, - clientP, clientQ); + preserve = (*amc->pinned)(amc, amcSegNailboard(seg), clientP, clientQ); } else { /* There's no nailboard, so preserve everything that hasn't been * forwarded. In this case, preservedInPlace* become somewhat @@ -2066,20 +2089,20 @@ static void AMCTraceEnd(Pool pool, Trace trace) amc = Pool2AMC(pool); AVERT(AMC, amc); ti = trace->ti; - AVER(TraceIdCheck(ti)); + AVERT(TraceId, ti); - STATISTIC_BEGIN { - Count pRetMin = 100; - PageRetStruct *pr = &amc->pageretstruct[ti]; - if(pr->pRet >= pRetMin) { - EVENT21(AMCTraceEnd, ArenaEpoch(pool->arena), (EventFU)trace->why, - ArenaAlign(pool->arena), AMCLargeSegPAGES, pRetMin, pr->pCond, - pr->pRet, pr->pCS, pr->pRS, pr->sCM, pr->pCM, pr->sRM, pr->pRM, - pr->pRM1, pr->pRMrr, pr->pRMr1, pr->sCL, pr->pCL, pr->sRL, - pr->pRL, pr->pRLr); - } - *pr = pageretstruct_Zero; - } STATISTIC_END; + STATISTIC_STAT ({ + Count pRetMin = 100; + PageRetStruct *pr = &amc->pageretstruct[ti]; + if(pr->pRet >= pRetMin) { + EVENT21(AMCTraceEnd, ArenaEpoch(pool->arena), (EventFU)trace->why, + ArenaAlign(pool->arena), AMCLargeSegPAGES, pRetMin, pr->pCond, + pr->pRet, pr->pCS, pr->pRS, pr->sCM, pr->pCM, pr->sRM, pr->pRM, + pr->pRM1, pr->pRMrr, pr->pRMr1, pr->sCL, pr->pCL, pr->sRL, + pr->pRL, pr->pRLr); + } + *pr = pageretstruct_Zero; + }); } @@ -2308,23 +2331,23 @@ static Res AMCDescribe(Pool pool, mps_lib_FILE *stream) } -/* AMCPoolClass -- the class definition */ +/* AMCZPoolClass -- the class definition */ -DEFINE_POOL_CLASS(AMCPoolClass, this) +DEFINE_POOL_CLASS(AMCZPoolClass, this) { - INHERIT_CLASS(this, AbstractCollectPoolClass); + INHERIT_CLASS(this, AbstractSegBufPoolClass); PoolClassMixInFormat(this); - this->name = "AMC"; + PoolClassMixInCollect(this); + this->name = "AMCZ"; this->size = sizeof(AMCStruct); this->offset = offsetof(AMCStruct, poolStruct); this->attr |= AttrMOVINGGC; this->varargs = AMCVarargs; - this->init = AMCInit; + this->init = AMCZInit; this->finish = AMCFinish; this->bufferFill = AMCBufferFill; this->bufferEmpty = AMCBufferEmpty; this->whiten = AMCWhiten; - this->scan = AMCScan; this->fix = AMCFix; this->fixEmergency = AMCFixEmergency; this->reclaim = AMCReclaim; @@ -2335,19 +2358,20 @@ DEFINE_POOL_CLASS(AMCPoolClass, this) this->walk = AMCWalk; this->bufferClass = amcBufClassGet; this->describe = AMCDescribe; + AVERT(PoolClass, this); } -/* AMCZPoolClass -- the class definition */ +/* AMCPoolClass -- the class definition */ -DEFINE_POOL_CLASS(AMCZPoolClass, this) +DEFINE_POOL_CLASS(AMCPoolClass, this) { - INHERIT_CLASS(this, AMCPoolClass); - this->name = "AMCZ"; - this->attr &= ~(AttrSCAN | AttrINCR_RB); - this->init = AMCZInit; - this->grey = PoolNoGrey; - this->scan = PoolNoScan; + INHERIT_CLASS(this, AMCZPoolClass); + PoolClassMixInScan(this); + this->name = "AMC"; + this->init = AMCInit; + this->scan = AMCScan; + AVERT(PoolClass, this); } @@ -2427,7 +2451,7 @@ static Bool AMCCheck(AMC amc) CHECKD(Pool, &amc->poolStruct); CHECKL(IsSubclassPoly(amc->poolStruct.class, EnsureAMCPoolClass())); CHECKL(RankSetCheck(amc->rankSet)); - CHECKL(RingCheck(&amc->genRing)); + CHECKD_NOSIG(Ring, &amc->genRing); CHECKL(BoolCheck(amc->gensBooted)); if(amc->gensBooted) { CHECKD(amcGen, amc->nursery); diff --git a/mps/code/poolams.c b/mps/code/poolams.c index 8937a09113d..c67a2efd684 100644 --- a/mps/code/poolams.c +++ b/mps/code/poolams.c @@ -1,7 +1,7 @@ /* poolams.c: AUTOMATIC MARK & SWEEP POOL CLASS * * $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. * * @@ -48,7 +48,7 @@ Bool AMSSegCheck(AMSSeg amsseg) { Seg seg = AMSSeg2Seg(amsseg); CHECKS(AMSSeg, amsseg); - CHECKL(GCSegCheck(&amsseg->gcSegStruct)); + CHECKD(GCSeg, &amsseg->gcSegStruct); CHECKU(AMS, amsseg->ams); CHECKL(AMS2Pool(amsseg->ams) == SegPool(seg)); CHECKD_NOSIG(Ring, &amsseg->segRing); @@ -60,7 +60,7 @@ Bool AMSSegCheck(AMSSeg amsseg) CHECKL(BoolCheck(amsseg->allocTableInUse)); if (!amsseg->allocTableInUse) CHECKL(amsseg->firstFree <= amsseg->grains); - CHECKL(amsseg->allocTable != NULL); + CHECKD_NOSIG(BT, amsseg->allocTable); if (SegWhite(seg) != TraceSetEMPTY) { /* */ @@ -71,8 +71,8 @@ Bool AMSSegCheck(AMSSeg amsseg) CHECKL(BoolCheck(amsseg->marksChanged)); CHECKL(BoolCheck(amsseg->ambiguousFixes)); CHECKL(BoolCheck(amsseg->colourTablesInUse)); - CHECKL(amsseg->nongreyTable != NULL); - CHECKL(amsseg->nonwhiteTable != NULL); + CHECKD_NOSIG(BT, amsseg->nongreyTable); + CHECKD_NOSIG(BT, amsseg->nonwhiteTable); return TRUE; } @@ -218,7 +218,7 @@ static Res AMSSegInit(Seg seg, Pool pool, Addr base, Size size, AVERT(AMS, ams); arena = PoolArena(pool); /* no useful checks for base and size */ - AVER(BoolCheck(reservoirPermit)); + AVERT(Bool, reservoirPermit); /* Initialize the superclass fields first via next-method call */ super = SEG_SUPERCLASS(AMSSegClass); @@ -609,6 +609,7 @@ DEFINE_CLASS(AMSSegClass, class) class->merge = AMSSegMerge; class->split = AMSSegSplit; class->describe = AMSSegDescribe; + AVERT(SegClass, class); } @@ -637,7 +638,7 @@ static Res AMSSegSizePolicy(Size *sizeReturn, AVER(sizeReturn != NULL); AVERT(Pool, pool); AVER(size > 0); - AVER(RankSetCheck(rankSet)); + AVERT(RankSet, rankSet); arena = PoolArena(pool); @@ -666,7 +667,7 @@ static Res AMSSegCreate(Seg *segReturn, Pool pool, Size size, AVERT(Pool, pool); AVER(size > 0); AVERT(RankSet, rankSet); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); ams = Pool2AMS(pool); AVERT(AMS,ams); @@ -734,7 +735,7 @@ static void AMSVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs) args[2].key = MPS_KEY_AMS_SUPPORT_AMBIGUOUS; args[2].val.b = va_arg(varargs, Bool); args[3].key = MPS_KEY_ARGS_END; - AVER(ArgListCheck(args)); + AVERT(ArgList, args); } static void AMSDebugVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs) @@ -763,7 +764,7 @@ static Res AMSInit(Pool pool, ArgList args) ArgStruct arg; AVERT(Pool, pool); - AVER(ArgListCheck(args)); + AVERT(ArgList, args); if (ArgPick(&arg, args, MPS_KEY_CHAIN)) chain = arg.val.chain; @@ -932,7 +933,7 @@ static Res AMSBufferFill(Addr *baseReturn, Addr *limitReturn, AVERT(Buffer, buffer); AVER(size > 0); AVER(SizeIsAligned(size, PoolAlignment(pool))); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); /* Check that we're not in the grey mutator phase (see */ /* ). */ @@ -996,7 +997,7 @@ static void AMSBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit) AVERT(Buffer,buffer); AVER(BufferIsReady(buffer)); seg = BufferSeg(buffer); - AVER(SegCheck(seg)); + AVERT(Seg, seg); AVER(init <= limit); AVER(AddrIsAligned(init, PoolAlignment(pool))); AVER(AddrIsAligned(limit, PoolAlignment(pool))); @@ -1074,7 +1075,7 @@ static Res AMSCondemn(Pool pool, Trace trace, Seg seg) AVERT(AMS, ams); AVERT(Trace, trace); - AVER(SegCheck(seg)); + AVERT(Seg, seg); amsseg = Seg2AMSSeg(seg); AVERT(AMSSeg, amsseg); @@ -1260,7 +1261,7 @@ static Res amsScanObject(Seg seg, Index i, Addr p, Addr next, void *clos) AVER(clos != NULL); closure = (amsScanClosure)clos; AVERT(ScanState, closure->ss); - AVER(BoolCheck(closure->scanAllObjects)); + AVERT(Bool, closure->scanAllObjects); format = AMS2Pool(amsseg->ams)->format; AVERT(Format, format); @@ -1306,7 +1307,7 @@ Res AMSScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) ams = Pool2AMS(pool); AVERT(AMS, ams); arena = PoolArena(pool); - AVER(SegCheck(seg)); + AVERT(Seg, seg); amsseg = Seg2AMSSeg(seg); AVERT(AMSSeg, amsseg); @@ -1684,8 +1685,10 @@ DEFINE_CLASS(AMSPoolClass, this) this->fix = AMSFix; this->fixEmergency = AMSFix; this->reclaim = AMSReclaim; + this->walk = PoolNoWalk; /* TODO: job003738 */ this->freewalk = AMSFreeWalk; this->describe = AMSDescribe; + AVERT(PoolClass, this); } @@ -1713,6 +1716,7 @@ DEFINE_POOL_CLASS(AMSDebugPoolClass, this) this->size = sizeof(AMSDebugStruct); this->varargs = AMSDebugVarargs; this->debugMixin = AMSDebugMixin; + AVERT(PoolClass, this); } @@ -1721,7 +1725,7 @@ DEFINE_POOL_CLASS(AMSDebugPoolClass, this) Bool AMSCheck(AMS ams) { CHECKS(AMS, ams); - CHECKL(PoolCheck(AMS2Pool(ams))); + CHECKD(Pool, AMS2Pool(ams)); CHECKL(IsSubclassPoly(AMS2Pool(ams)->class, AMSPoolClassGet())); CHECKL(PoolAlignment(AMS2Pool(ams)) == ((Size)1 << ams->grainShift)); CHECKL(PoolAlignment(AMS2Pool(ams)) == AMS2Pool(ams)->format->alignment); @@ -1729,7 +1733,7 @@ Bool AMSCheck(AMS ams) CHECKD(PoolGen, &ams->pgen); CHECKL(SizeIsAligned(ams->size, ArenaAlign(PoolArena(AMS2Pool(ams))))); CHECKL(FUNCHECK(ams->segSize)); - CHECKL(RingCheck(&ams->segRing)); + CHECKD_NOSIG(Ring, &ams->segRing); CHECKL(FUNCHECK(ams->allocRing)); CHECKL(FUNCHECK(ams->segsDestroy)); CHECKL(FUNCHECK(ams->segClass)); @@ -1740,7 +1744,7 @@ Bool AMSCheck(AMS ams) /* 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/poolawl.c b/mps/code/poolawl.c index 83890b34b6e..6332a91b7cd 100644 --- a/mps/code/poolawl.c +++ b/mps/code/poolawl.c @@ -1,7 +1,7 @@ /* poolawl.c: AUTOMATIC WEAK LINKED POOL CLASS * * $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. * * * DESIGN @@ -187,7 +187,7 @@ static Res AWLSegInit(Seg seg, Pool pool, Addr base, Size size, AVERT(Pool, pool); arena = PoolArena(pool); /* no useful checks for base and size */ - AVER(BoolCheck(reservoirPermit)); + AVERT(Bool, reservoirPermit); ArgRequire(&arg, args, awlKeySegRankSet); rankSet = arg.val.u; AVERT(RankSet, rankSet); @@ -288,6 +288,7 @@ DEFINE_SEG_CLASS(AWLSegClass, class) class->size = sizeof(AWLSegStruct); class->init = AWLSegInit; class->finish = AWLSegFinish; + AVERT(SegClass, class); } @@ -450,10 +451,10 @@ static Res AWLSegCreate(AWLSeg *awlsegReturn, Arena arena; AVER(awlsegReturn != NULL); - AVER(RankSetCheck(rankSet)); + AVERT(RankSet, rankSet); AVERT(Pool, pool); AVER(size > 0); - AVER(BoolCheck(reservoirPermit)); + AVERT(Bool, reservoirPermit); awl = Pool2AWL(pool); AVERT(AWL, awl); @@ -519,7 +520,7 @@ static void AWLVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs) args[1].key = MPS_KEY_AWL_FIND_DEPENDENT; args[1].val.addr_method = va_arg(varargs, mps_awl_find_dependent_t); args[2].key = MPS_KEY_ARGS_END; - AVER(ArgListCheck(args)); + AVERT(ArgList, args); } @@ -626,7 +627,7 @@ static Res AWLBufferFill(Addr *baseReturn, Addr *limitReturn, AVERT(Pool, pool); AVERT(Buffer, buffer); AVER(size > 0); - AVER(BoolCheck(reservoirPermit)); + AVERT(Bool, reservoirPermit); awl = Pool2AWL(pool); AVERT(AWL, awl); @@ -834,7 +835,7 @@ static void AWLBlacken(Pool pool, TraceSet traceSet, Seg seg) AWLSeg awlseg; AVERT(Pool, pool); - AVER(TraceSetCheck(traceSet)); + AVERT(TraceSet, traceSet); AVERT(Seg, seg); awl = Pool2AWL(pool); @@ -1280,6 +1281,7 @@ DEFINE_POOL_CLASS(AWLPoolClass, this) this->fixEmergency = AWLFix; this->reclaim = AWLReclaim; this->walk = AWLWalk; + AVERT(PoolClass, this); } @@ -1307,7 +1309,7 @@ static Bool AWLCheck(AWL awl) /* 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/poollo.c b/mps/code/poollo.c index f81ab6a1815..d8f23584fba 100644 --- a/mps/code/poollo.c +++ b/mps/code/poollo.c @@ -1,7 +1,7 @@ /* poollo.c: LEAF POOL CLASS * * $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 * @@ -73,6 +73,7 @@ DEFINE_SEG_CLASS(LOSegClass, class) class->size = sizeof(LOSegStruct); class->init = loSegInit; class->finish = loSegFinish; + AVERT(SegClass, class); } @@ -81,7 +82,7 @@ DEFINE_SEG_CLASS(LOSegClass, class) static Bool LOSegCheck(LOSeg loseg) { CHECKS(LOSeg, loseg); - CHECKL(GCSegCheck(&loseg->gcSegStruct)); + CHECKD(GCSeg, &loseg->gcSegStruct); CHECKU(LO, loseg->lo); CHECKL(loseg->mark != NULL); CHECKL(loseg->alloc != NULL); @@ -112,7 +113,7 @@ static Res loSegInit(Seg seg, Pool pool, Addr base, Size size, AVERT(Pool, pool); arena = PoolArena(pool); /* no useful checks for base and size */ - AVER(BoolCheck(reservoirPermit)); + AVERT(Bool, reservoirPermit); lo = PoolPoolLO(pool); AVERT(LO, lo); @@ -286,7 +287,7 @@ static Res loSegCreate(LOSeg *loSegReturn, Pool pool, Size size, AVER(loSegReturn != NULL); AVERT(Pool, pool); AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); lo = PoolPoolLO(pool); AVERT(LO, lo); @@ -460,7 +461,7 @@ static void LOVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs) args[0].key = MPS_KEY_FORMAT; args[0].val.format = va_arg(varargs, Format); args[1].key = MPS_KEY_ARGS_END; - AVER(ArgListCheck(args)); + AVERT(ArgList, args); } @@ -558,7 +559,7 @@ static Res LOBufferFill(Addr *baseReturn, Addr *limitReturn, AVER(BufferRankSet(buffer) == RankSetEMPTY); AVER(size > 0); AVER(SizeIsAligned(size, PoolAlignment(pool))); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); /* Try to find a segment with enough space already. */ RING_FOR(node, &pool->segRing, nextNode) { @@ -774,25 +775,23 @@ static void LOReclaim(Pool pool, Trace trace, Seg seg) DEFINE_POOL_CLASS(LOPoolClass, this) { - INHERIT_CLASS(this, AbstractCollectPoolClass); + INHERIT_CLASS(this, AbstractSegBufPoolClass); PoolClassMixInFormat(this); + PoolClassMixInCollect(this); this->name = "LO"; this->size = sizeof(LOStruct); this->offset = offsetof(LOStruct, poolStruct); - this->attr &= ~(AttrSCAN | AttrINCR_RB); this->varargs = LOVarargs; this->init = LOInit; this->finish = LOFinish; this->bufferFill = LOBufferFill; this->bufferEmpty = LOBufferEmpty; this->whiten = LOWhiten; - this->grey = PoolNoGrey; - this->blacken = PoolNoBlacken; - this->scan = PoolNoScan; this->fix = LOFix; this->fixEmergency = LOFix; this->reclaim = LOReclaim; this->walk = LOWalk; + AVERT(PoolClass, this); } @@ -821,7 +820,7 @@ static Bool LOCheck(LO lo) /* 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/poolmfs.c b/mps/code/poolmfs.c index 0149da55ee0..fbb125a71f2 100644 --- a/mps/code/poolmfs.c +++ b/mps/code/poolmfs.c @@ -1,7 +1,7 @@ /* poolmfs.c: MANUAL FIXED SMALL UNIT POOL * * $Id$ - * Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * This is the implementation of the MFS pool class. * @@ -86,7 +86,7 @@ static void MFSVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs) args[1].key = MPS_KEY_MFS_UNIT_SIZE; args[1].val.size = va_arg(varargs, Size); args[2].key = MPS_KEY_ARGS_END; - AVER(ArgListCheck(args)); + AVERT(ArgList, args); } ARG_DEFINE_KEY(mfs_unit_size, Size); @@ -102,7 +102,7 @@ static Res MFSInit(Pool pool, ArgList args) ArgStruct arg; AVER(pool != NULL); - AVER(ArgListCheck(args)); + AVERT(ArgList, args); ArgRequire(&arg, args, MPS_KEY_MFS_UNIT_SIZE); unitSize = arg.val.size; @@ -116,7 +116,7 @@ static Res MFSInit(Pool pool, ArgList args) extendSelf = arg.val.b; AVER(extendBy >= unitSize); - AVER(BoolCheck(extendSelf)); + AVERT(Bool, extendSelf); mfs = PoolPoolMFS(pool); arena = PoolArena(pool); @@ -250,7 +250,7 @@ static Res MFSAlloc(Addr *pReturn, Pool pool, Size size, AVER(pReturn != NULL); AVER(size == mfs->unroundedUnitSize); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); f = mfs->freeList; @@ -347,6 +347,7 @@ DEFINE_POOL_CLASS(MFSPoolClass, this) this->alloc = MFSAlloc; this->free = MFSFree; this->describe = MFSDescribe; + AVERT(PoolClass, this); } @@ -369,7 +370,7 @@ Bool MFSCheck(MFS mfs) CHECKS(MFS, mfs); CHECKD(Pool, &mfs->poolStruct); CHECKL(mfs->poolStruct.class == EnsureMFSPoolClass()); - CHECKL(mfs->unroundedUnitSize >= UNIT_MIN); + CHECKL(mfs->unitSize >= UNIT_MIN); CHECKL(mfs->extendBy >= UNIT_MIN); CHECKL(BoolCheck(mfs->extendSelf)); arena = PoolArena(&mfs->poolStruct); @@ -377,7 +378,7 @@ Bool MFSCheck(MFS mfs) CHECKL(SizeAlignUp(mfs->unroundedUnitSize, mfs->poolStruct.alignment) == mfs->unitSize); if(mfs->tractList != NULL) { - CHECKL(TractCheck(mfs->tractList)); + CHECKD_NOSIG(Tract, mfs->tractList); } return TRUE; } @@ -385,7 +386,7 @@ Bool MFSCheck(MFS mfs) /* 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/poolmrg.c b/mps/code/poolmrg.c index c945029a9db..93d9f8bd25e 100644 --- a/mps/code/poolmrg.c +++ b/mps/code/poolmrg.c @@ -1,7 +1,7 @@ /* poolmrg.c: MANUAL RANK GUARDIAN POOL * * $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. * * @@ -130,9 +130,9 @@ static Bool MRGCheck(MRG mrg) CHECKS(MRG, mrg); CHECKD(Pool, &mrg->poolStruct); CHECKL(MRG2Pool(mrg)->class == PoolClassMRG()); - CHECKL(RingCheck(&mrg->entryRing)); - CHECKL(RingCheck(&mrg->freeRing)); - CHECKL(RingCheck(&mrg->refRing)); + CHECKD_NOSIG(Ring, &mrg->entryRing); + CHECKD_NOSIG(Ring, &mrg->freeRing); + CHECKD_NOSIG(Ring, &mrg->refRing); CHECKL(mrg->extendBy == ArenaAlign(PoolArena(MRG2Pool(mrg)))); return TRUE; } @@ -183,7 +183,7 @@ static Bool MRGLinkSegCheck(MRGLinkSeg linkseg) Seg seg; CHECKS(MRGLinkSeg, linkseg); - CHECKL(SegCheck(&linkseg->segStruct)); + CHECKD(Seg, &linkseg->segStruct); seg = LinkSeg2Seg(linkseg); if (NULL != linkseg->refSeg) { /* see .link.nullref */ CHECKL(SegPool(seg) == SegPool(RefSeg2Seg(linkseg->refSeg))); @@ -198,10 +198,10 @@ static Bool MRGRefSegCheck(MRGRefSeg refseg) Seg seg; CHECKS(MRGRefSeg, refseg); - CHECKL(GCSegCheck(&refseg->gcSegStruct)); + CHECKD(GCSeg, &refseg->gcSegStruct); seg = RefSeg2Seg(refseg); CHECKL(SegPool(seg) == SegPool(LinkSeg2Seg(refseg->linkSeg))); - CHECKL(RingCheck(&refseg->mrgRing)); + CHECKD_NOSIG(Ring, &refseg->mrgRing); CHECKD(MRGLinkSeg, refseg->linkSeg); CHECKL(refseg->linkSeg->refSeg == refseg); return TRUE; @@ -224,7 +224,7 @@ static Res MRGLinkSegInit(Seg seg, Pool pool, Addr base, Size size, mrg = Pool2MRG(pool); AVERT(MRG, mrg); /* no useful checks for base and size */ - AVER(BoolCheck(reservoirPermit)); + AVERT(Bool, reservoirPermit); /* Initialize the superclass fields first via next-method call */ super = SEG_SUPERCLASS(MRGLinkSegClass); @@ -267,7 +267,7 @@ static Res MRGRefSegInit(Seg seg, Pool pool, Addr base, Size size, mrg = Pool2MRG(pool); AVERT(MRG, mrg); /* no useful checks for base and size */ - AVER(BoolCheck(reservoirPermit)); + AVERT(Bool, reservoirPermit); AVERT(MRGLinkSeg, linkseg); /* Initialize the superclass fields first via next-method call */ @@ -302,6 +302,7 @@ DEFINE_SEG_CLASS(MRGLinkSegClass, class) class->name = "MRGLSEG"; class->size = sizeof(MRGLinkSegStruct); class->init = MRGLinkSegInit; + AVERT(SegClass, class); } @@ -314,6 +315,7 @@ DEFINE_SEG_CLASS(MRGRefSegClass, class) class->name = "MRGRSEG"; class->size = sizeof(MRGRefSegStruct); class->init = MRGRefSegInit; + AVERT(SegClass, class); } @@ -629,7 +631,7 @@ static Res MRGInit(Pool pool, ArgList args) MRG mrg; AVER(pool != NULL); /* Can't check more; see pool contract @@@@ */ - AVER(ArgListCheck(args)); + AVERT(ArgList, args); UNUSED(args); mrg = Pool2MRG(pool); @@ -855,13 +857,14 @@ DEFINE_POOL_CLASS(MRGPoolClass, this) this->name = "MRG"; this->size = sizeof(MRGStruct); this->offset = offsetof(MRGStruct, poolStruct); - this->attr |= (AttrSCAN | AttrFREE | AttrINCR_RB); + this->attr |= AttrSCAN; this->init = MRGInit; this->finish = MRGFinish; this->grey = PoolTrivGrey; this->blacken = PoolTrivBlacken; this->scan = MRGScan; this->describe = MRGDescribe; + AVERT(PoolClass, this); } @@ -873,7 +876,7 @@ PoolClass PoolClassMRG(void) /* 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/poolmv.c b/mps/code/poolmv.c index 9acd64380f6..0ce4f28c95d 100644 --- a/mps/code/poolmv.c +++ b/mps/code/poolmv.c @@ -1,7 +1,7 @@ /* poolmv.c: MANUAL VARIABLE POOL * * $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. * * **** RESTRICTION: This pool may not allocate from the arena control @@ -138,11 +138,11 @@ static Bool MVSpanCheck(MVSpan span) CHECKS(MVSpan, span); - CHECKL(RingCheck(&span->spans)); + CHECKD_NOSIG(Ring, &span->spans); CHECKU(MV, span->mv); CHECKD_NOSIG(Tract, span->tract); - CHECKL(MVBlockCheck(&span->base)); - CHECKL(MVBlockCheck(&span->limit)); + CHECKD_NOSIG(MVBlock, &span->base); + CHECKD_NOSIG(MVBlock, &span->limit); /* The block chain starts with the base sentinel. */ CHECKL(span->blocks == &span->base); /* Since there is a limit sentinel, the chain can't end just after the */ @@ -193,7 +193,7 @@ static void MVVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs) args[2].key = MPS_KEY_MAX_SIZE; args[2].val.size = va_arg(varargs, Size); args[3].key = MPS_KEY_ARGS_END; - AVER(ArgListCheck(args)); + AVERT(ArgList, args); } static void MVDebugVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs) @@ -570,7 +570,7 @@ static Res MVAlloc(Addr *pReturn, Pool pool, Size size, span->mv = mv; /* Set the p field for each tract of the span */ TRACT_FOR(tract, addr, arena, base, limit) { - AVER(TractCheck(tract)); + AVERT(Tract, tract); AVER(TractP(tract) == NULL); AVER(TractPool(tract) == pool); TractSetP(tract, (void *)span); @@ -792,6 +792,7 @@ DEFINE_POOL_CLASS(MVPoolClass, this) this->alloc = MVAlloc; this->free = MVFree; this->describe = MVDescribe; + AVERT(PoolClass, this); } @@ -811,6 +812,7 @@ DEFINE_POOL_CLASS(MVDebugPoolClass, this) this->size = sizeof(MVDebugStruct); this->varargs = MVDebugVarargs; this->debugMixin = MVDebugMixin; + AVERT(PoolClass, this); } @@ -901,7 +903,7 @@ Bool MVCheck(MV mv) /* 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/poolmv2.c b/mps/code/poolmv2.c index 6910de5e065..b2903481b45 100644 --- a/mps/code/poolmv2.c +++ b/mps/code/poolmv2.c @@ -1,7 +1,7 @@ /* poolmv2.c: MANUAL VARIABLE-SIZED TEMPORAL POOL * * $Id$ - * Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * .purpose: A manual-variable pool designed to take advantage of * placement according to predicted deathtime. @@ -145,6 +145,7 @@ DEFINE_POOL_CLASS(MVTPoolClass, this) this->bufferFill = MVTBufferFill; this->bufferEmpty = MVTBufferEmpty; this->describe = MVTDescribe; + AVERT(PoolClass, this); } /* Macros */ @@ -199,7 +200,7 @@ static void MVTVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs) args[4].key = MPS_KEY_MVT_FRAG_LIMIT; args[4].val.d = (double)va_arg(varargs, Count) / 100.0; args[5].key = MPS_KEY_ARGS_END; - AVER(ArgListCheck(args)); + AVERT(ArgList, args); } @@ -278,7 +279,9 @@ static Res MVTInit(Pool pool, ArgList args) if (res != ResOK) goto failABQ; - FreelistInit(MVTFreelist(mvt), align); + res = FreelistInit(MVTFreelist(mvt), align); + if (res != ResOK) + goto failFreelist; pool->alignment = align; mvt->reuseSize = reuseSize; @@ -343,6 +346,8 @@ static Res MVTInit(Pool pool, ArgList args) reserveDepth, fragLimit); return ResOK; +failFreelist: + ABQFinish(arena, MVTABQ(mvt)); failABQ: CBSFinish(MVTCBS(mvt)); failCBS: @@ -359,9 +364,7 @@ static Bool MVTCheck(MVT mvt) CHECKD(Pool, &mvt->poolStruct); CHECKL(mvt->poolStruct.class == MVTPoolClassGet()); CHECKD(CBS, &mvt->cbsStruct); - /* CHECKL(CBSCheck(MVTCBS(mvt))); */ CHECKD(ABQ, &mvt->abqStruct); - /* CHECKL(ABQCheck(MVTABQ(mvt))); */ CHECKD(Freelist, &mvt->flStruct); CHECKL(mvt->reuseSize >= 2 * mvt->fillSize); CHECKL(mvt->fillSize >= mvt->maxSize); @@ -375,8 +378,7 @@ static Bool MVTCheck(MVT mvt) if (mvt->splinter) { CHECKL(AddrOffset(mvt->splinterBase, mvt->splinterLimit) >= mvt->minSize); - /* CHECKD(Seg, mvt->splinterSeg); */ - CHECKL(SegCheck(mvt->splinterSeg)); + CHECKD(Seg, mvt->splinterSeg); CHECKL(mvt->splinterBase >= SegBase(mvt->splinterSeg)); CHECKL(mvt->splinterLimit <= SegLimit(mvt->splinterSeg)); } @@ -683,7 +685,7 @@ static Res MVTBufferFill(Addr *baseReturn, Addr *limitReturn, AVER(BufferIsReset(buffer)); AVER(minSize > 0); AVER(SizeIsAligned(minSize, pool->alignment)); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); /* Allocate oversize blocks exactly, directly from the arena. */ @@ -757,9 +759,11 @@ static Bool MVTDeleteOverlapping(Bool *deleteReturn, void *element, /* MVTReserve -- add a range to the available range queue, and if the - * queue is full, return segments to the arena. + * queue is full, return segments to the arena. Return TRUE if it + * succeeded in adding the range to the queue, FALSE if the queue + * overflowed. */ -static Res MVTReserve(MVT mvt, Range range) +static Bool MVTReserve(MVT mvt, Range range) { AVERT(MVT, mvt); AVERT(Range, range); @@ -774,18 +778,18 @@ static Res MVTReserve(MVT mvt, Range range) SURELY(ABQPeek(MVTABQ(mvt), &oldRange)); AVERT(Range, &oldRange); if (!MVTReturnSegs(mvt, &oldRange, arena)) - goto failOverflow; + goto overflow; METER_ACC(mvt->returns, RangeSize(&oldRange)); if (!ABQPush(MVTABQ(mvt), range)) - goto failOverflow; + goto overflow; } - return ResOK; + return TRUE; -failOverflow: +overflow: mvt->abqOverflow = TRUE; METER_ACC(mvt->overflows, RangeSize(range)); - return ResFAIL; + return FALSE; } @@ -820,7 +824,7 @@ static Res MVTInsert(MVT mvt, Addr base, Addr limit) * are coalesced on the ABQ. */ ABQIterate(MVTABQ(mvt), MVTDeleteOverlapping, &newRange, 0); - MVTReserve(mvt, &newRange); + (void)MVTReserve(mvt, &newRange); } return ResOK; @@ -875,11 +879,11 @@ static Res MVTDelete(MVT mvt, Addr base, Addr limit) */ RangeInit(&rangeLeft, RangeBase(&rangeOld), base); if (RangeSize(&rangeLeft) >= mvt->reuseSize) - MVTReserve(mvt, &rangeLeft); + (void)MVTReserve(mvt, &rangeLeft); RangeInit(&rangeRight, limit, RangeLimit(&rangeOld)); if (RangeSize(&rangeRight) >= mvt->reuseSize) - MVTReserve(mvt, &rangeRight); + (void)MVTReserve(mvt, &rangeRight); return ResOK; } @@ -1269,8 +1273,6 @@ static Bool MVTReturnSegs(MVT mvt, Range range, Arena arena) */ static Bool MVTRefillCallback(MVT mvt, Range range) { - Res res; - AVERT(ABQ, MVTABQ(mvt)); AVERT(Range, range); @@ -1278,11 +1280,7 @@ static Bool MVTRefillCallback(MVT mvt, Range range) return TRUE; METER_ACC(mvt->refillPushes, ABQDepth(MVTABQ(mvt))); - res = MVTReserve(mvt, range); - if (res != ResOK) - return FALSE; - - return TRUE; + return MVTReserve(mvt, range); } static Bool MVTCBSRefillCallback(CBS cbs, Range range, @@ -1488,7 +1486,7 @@ CBS _mps_mvt_cbs(mps_pool_t mps_pool) { /* 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/poolmvff.c b/mps/code/poolmvff.c index e1d1d094d38..201d2047104 100644 --- a/mps/code/poolmvff.c +++ b/mps/code/poolmvff.c @@ -1,7 +1,7 @@ /* poolmvff.c: First Fit Manual Variable Pool * * $Id$ - * Copyright (c) 2001 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. * * .purpose: This is a pool class for manually managed objects of @@ -228,7 +228,7 @@ static Res MVFFAddSeg(Seg *segReturn, AVERT(MVFF, mvff); AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); pool = MVFF2Pool(mvff); arena = PoolArena(pool); @@ -339,7 +339,7 @@ static Res MVFFAlloc(Addr *aReturn, Pool pool, Size size, AVER(aReturn != NULL); AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); size = SizeAlignUp(size, PoolAlignment(pool)); @@ -510,7 +510,7 @@ static void MVFFVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs) args[5].key = MPS_KEY_MVFF_FIRST_FIT; args[5].val.b = va_arg(varargs, Bool); args[6].key = MPS_KEY_ARGS_END; - AVER(ArgListCheck(args)); + AVERT(ArgList, args); } static void MVFFDebugVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs) @@ -571,9 +571,9 @@ static Res MVFFInit(Pool pool, ArgList args) AVER(avgSize > 0); /* .arg.check */ AVER(avgSize <= extendBy); /* .arg.check */ AVER(SizeIsAligned(align, MPS_PF_ALIGN)); - AVER(BoolCheck(slotHigh)); - AVER(BoolCheck(arenaHigh)); - AVER(BoolCheck(firstFit)); + AVERT(Bool, slotHigh); + AVERT(Bool, arenaHigh); + AVERT(Bool, firstFit); mvff = Pool2MVFF(pool); @@ -720,6 +720,7 @@ DEFINE_POOL_CLASS(MVFFPoolClass, this) this->bufferFill = MVFFBufferFill; this->bufferEmpty = MVFFBufferEmpty; this->describe = MVFFDescribe; + AVERT(PoolClass, this); } @@ -739,6 +740,7 @@ DEFINE_POOL_CLASS(MVFFDebugPoolClass, this) this->size = sizeof(MVFFDebugStruct); this->varargs = MVFFDebugVarargs; this->debugMixin = MVFFDebugMixin; + AVERT(PoolClass, this); } @@ -828,7 +830,7 @@ CBS _mps_mvff_cbs(mps_pool_t mps_pool) { /* 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/pooln.c b/mps/code/pooln.c index f0851f56fd5..3a7e26df34c 100644 --- a/mps/code/pooln.c +++ b/mps/code/pooln.c @@ -1,7 +1,7 @@ /* pooln.c: NULL POOL CLASS * * $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 "pooln.h" @@ -71,7 +71,7 @@ static Res NAlloc(Addr *pReturn, Pool pool, Size size, AVER(pReturn != NULL); AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); return ResLIMIT; /* limit of nil blocks exceeded */ } @@ -110,7 +110,7 @@ static Res NBufferFill(Addr *baseReturn, Addr *limitReturn, AVERT(Buffer, buffer); AVER(BufferIsReset(buffer)); AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); NOTREACHED; /* can't create buffers, so shouldn't fill them */ return ResUNIMPL; @@ -270,8 +270,7 @@ DEFINE_POOL_CLASS(NPoolClass, this) this->name = "N"; this->size = sizeof(PoolNStruct); this->offset = offsetof(PoolNStruct, poolStruct); - this->attr = AttrSCAN | AttrALLOC | AttrFREE | AttrBUF | - AttrBUF_RESERVE | AttrGC; + this->attr |= (AttrALLOC | AttrBUF | AttrFREE | AttrGC | AttrSCAN); this->init = NInit; this->finish = NFinish; this->alloc = NAlloc; @@ -287,6 +286,7 @@ DEFINE_POOL_CLASS(NPoolClass, this) this->reclaim = NReclaim; this->traceEnd = NTraceEnd; this->describe = NDescribe; + AVERT(PoolClass, this); } @@ -313,7 +313,7 @@ Bool PoolNCheck(PoolN poolN) /* 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/poolsnc.c b/mps/code/poolsnc.c index 800a1482efc..e9afe98a96b 100644 --- a/mps/code/poolsnc.c +++ b/mps/code/poolsnc.c @@ -1,7 +1,7 @@ /* poolsnc.c: STACK NO CHECKING POOL CLASS * * $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. * * DESIGN * @@ -90,9 +90,9 @@ static Bool SNCBufCheck(SNCBuf sncbuf) CHECKS(SNCBuf, sncbuf); segbuf = &sncbuf->segBufStruct; - CHECKL(SegBufCheck(segbuf)); + CHECKD(SegBuf, segbuf); if (sncbuf->topseg != NULL) { - CHECKL(SegCheck(sncbuf->topseg)); + CHECKD(Seg, sncbuf->topseg); } return TRUE; } @@ -185,6 +185,7 @@ DEFINE_BUFFER_CLASS(SNCBufClass, class) class->size = sizeof(SNCBufStruct); class->init = SNCBufInit; class->finish = SNCBufFinish; + AVERT(BufferClass, class); } @@ -216,7 +217,7 @@ typedef struct SNCSegStruct { static Bool SNCSegCheck(SNCSeg sncseg) { CHECKS(SNCSeg, sncseg); - CHECKL(GCSegCheck(&sncseg->gcSegStruct)); + CHECKD(GCSeg, &sncseg->gcSegStruct); if (NULL != sncseg->next) { CHECKS(SNCSeg, sncseg->next); } @@ -237,7 +238,7 @@ static Res sncSegInit(Seg seg, Pool pool, Addr base, Size size, sncseg = SegSNCSeg(seg); AVERT(Pool, pool); /* no useful checks for base and size */ - AVER(BoolCheck(reservoirPermit)); + AVERT(Bool, reservoirPermit); /* Initialize the superclass fields first via next-method call */ super = SEG_SUPERCLASS(SNCSegClass); @@ -261,6 +262,7 @@ DEFINE_SEG_CLASS(SNCSegClass, class) class->name = "SNCSEG"; class->size = sizeof(SNCSegStruct); class->init = sncSegInit; + AVERT(SegClass, class); } @@ -365,7 +367,7 @@ static void SNCVarargs(ArgStruct args[MPS_ARGS_MAX], va_list varargs) args[0].key = MPS_KEY_FORMAT; args[0].val.format = va_arg(varargs, Format); args[1].key = MPS_KEY_ARGS_END; - AVER(ArgListCheck(args)); + AVERT(ArgList, args); } @@ -431,7 +433,7 @@ static Res SNCBufferFill(Addr *baseReturn, Addr *limitReturn, AVERT(Pool, pool); AVERT(Buffer, buffer); AVER(size > 0); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); AVER(BufferIsReset(buffer)); snc = Pool2SNC(pool); @@ -682,6 +684,7 @@ DEFINE_POOL_CLASS(SNCPoolClass, this) this->framePopPending = SNCFramePopPending; this->walk = SNCWalk; this->bufferClass = SNCBufClassGet; + AVERT(PoolClass, this); } @@ -699,7 +702,7 @@ static Bool SNCCheck(SNC snc) CHECKD(Pool, &snc->poolStruct); CHECKL(snc->poolStruct.class == SNCPoolClassGet()); if (snc->freeSegs != NULL) { - CHECKL(SegCheck(snc->freeSegs)); + CHECKD(Seg, snc->freeSegs); } return TRUE; } @@ -707,7 +710,7 @@ static Bool SNCCheck(SNC snc) /* 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/prmci3li.c b/mps/code/prmci3li.c index 8d1b409e2dc..6a36ae7db2b 100644 --- a/mps/code/prmci3li.c +++ b/mps/code/prmci3li.c @@ -1,7 +1,7 @@ /* prmci3li.c: PROTECTION MUTATOR CONTEXT INTEL 386 (LINUX) * * $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. * * .purpose: This module implements the part of the protection module * that decodes the MutatorFaultContext. @@ -57,9 +57,10 @@ MRef Prmci3AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum) case 5: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EBP]); case 6: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_ESI]); case 7: return (MRef)((char *)&mfc->ucontext->uc_mcontext.gregs[REG_EDI]); + default: + NOTREACHED; + return NULL; /* Avoids compiler warning. */ } - NOTREACHED; - return (MRef)NULL; /* Avoids compiler warning. */ } @@ -107,7 +108,7 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc) /* 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/prmci3w3.c b/mps/code/prmci3w3.c index f3d2e2386cc..4cf9584c988 100644 --- a/mps/code/prmci3w3.c +++ b/mps/code/prmci3w3.c @@ -1,7 +1,7 @@ /* prmci3w3.c: PROTECTION MUTATOR CONTEXT INTEL 386 (Win32) * * $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. * * PURPOSE * @@ -46,9 +46,10 @@ MRef Prmci3AddressHoldingReg(MutatorFaultContext context, unsigned int regnum) case 5: return (MRef)&wincont->Ebp; case 6: return (MRef)&wincont->Esi; case 7: return (MRef)&wincont->Edi; + default: + NOTREACHED; + return NULL; /* suppress warning */ } - NOTREACHED; - return NULL; /* suppress warning */ } @@ -80,7 +81,7 @@ void Prmci3StepOverIns(MutatorFaultContext context, Size inslen) /* 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/prmci3xc.c b/mps/code/prmci3xc.c index b08ee3a1c4c..786145fc084 100644 --- a/mps/code/prmci3xc.c +++ b/mps/code/prmci3xc.c @@ -1,7 +1,7 @@ /* prmci3xc.c: PROTECTION MUTATOR CONTEXT INTEL 386 (MAC OS X) * * $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. * * .purpose: This module implements the part of the protection module * that decodes the MutatorFaultContext. @@ -55,9 +55,10 @@ MRef Prmci3AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum) case 5: return (MRef)((char *)&mfc->threadState->__ebp); case 6: return (MRef)((char *)&mfc->threadState->__esi); case 7: return (MRef)((char *)&mfc->threadState->__edi); + default: + NOTREACHED; + return NULL; /* Avoids compiler warning. */ } - NOTREACHED; - return (MRef)NULL; /* Avoids compiler warning. */ } @@ -104,7 +105,7 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc) /* 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/prmci6li.c b/mps/code/prmci6li.c index 9c15fcdf6ff..2f8bf9afc62 100644 --- a/mps/code/prmci6li.c +++ b/mps/code/prmci6li.c @@ -1,7 +1,7 @@ /* prmci6li.c: PROTECTION MUTATOR CONTEXT x64 (LINUX) * * $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. * * .purpose: This module implements the part of the protection module * that decodes the MutatorFaultContext. @@ -61,9 +61,10 @@ MRef Prmci6AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum) case 13: return &gregs[REG_R13]; case 14: return &gregs[REG_R14]; case 15: return &gregs[REG_R15]; + default: + NOTREACHED; + return NULL; /* Avoids compiler warning. */ } - NOTREACHED; - return (MRef)NULL; /* Avoids compiler warning. */ } @@ -111,7 +112,7 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc) /* 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/prmci6w3.c b/mps/code/prmci6w3.c index 8faca025450..81641c00526 100644 --- a/mps/code/prmci6w3.c +++ b/mps/code/prmci6w3.c @@ -1,7 +1,7 @@ /* prmci6w3.c: PROTECTION MUTATOR CONTEXT INTEL 386 (Win32) * * $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. * * PURPOSE * @@ -52,9 +52,10 @@ MRef Prmci6AddressHoldingReg(MutatorFaultContext context, unsigned int regnum) case 13: return (MRef)&wincont->R13; case 14: return (MRef)&wincont->R14; case 15: return (MRef)&wincont->R15; + default: + NOTREACHED; + return NULL; /* suppress warning */ } - NOTREACHED; - return NULL; /* suppress warning */ } @@ -86,7 +87,7 @@ void Prmci6StepOverIns(MutatorFaultContext context, Size inslen) /* 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/prmci6xc.c b/mps/code/prmci6xc.c index f3d0413d1a6..02ccb840b6c 100644 --- a/mps/code/prmci6xc.c +++ b/mps/code/prmci6xc.c @@ -1,7 +1,7 @@ /* prmci6xc.c: PROTECTION MUTATOR CONTEXT x64 (MAC OS X) * * $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. * * .purpose: This module implements the part of the protection module * that decodes the MutatorFaultContext. @@ -58,9 +58,10 @@ MRef Prmci6AddressHoldingReg(MutatorFaultContext mfc, unsigned int regnum) case 13: return (MRef)((char *)&mfc->threadState->__r13); case 14: return (MRef)((char *)&mfc->threadState->__r14); case 15: return (MRef)((char *)&mfc->threadState->__r15); + default: + NOTREACHED; + return NULL; /* Avoids compiler warning. */ } - NOTREACHED; - return (MRef)NULL; /* Avoids compiler warning. */ } @@ -107,7 +108,7 @@ Res MutatorFaultContextScan(ScanState ss, MutatorFaultContext mfc) /* 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/protocol.c b/mps/code/protocol.c index 6a53613d54b..bcc8ae56863 100644 --- a/mps/code/protocol.c +++ b/mps/code/protocol.c @@ -1,7 +1,7 @@ /* pool.c: PROTOCOL IMPLEMENTATION * * $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 * @@ -18,7 +18,7 @@ SRCID(protocol, "$Id$"); Bool ProtocolClassCheck(ProtocolClass class) { CHECKS(ProtocolClass, class); - CHECKS(ProtocolClass, class->superclass); + CHECKU(ProtocolClass, class->superclass); CHECKL(FUNCHECK(class->coerceInst)); CHECKL(FUNCHECK(class->coerceClass)); return TRUE; @@ -30,7 +30,7 @@ Bool ProtocolClassCheck(ProtocolClass class) Bool ProtocolInstCheck(ProtocolInst inst) { CHECKS(ProtocolInst, inst); - CHECKL(ProtocolClassCheck(inst->class)); + CHECKD(ProtocolClass, inst->class); return TRUE; } @@ -118,6 +118,7 @@ DEFINE_CLASS(ProtocolClass, theClass) theClass->superclass = theClass; theClass->coerceInst = ProtocolCoerceInst; theClass->coerceClass = ProtocolCoerceClass; + AVERT(ProtocolClass, theClass); } @@ -126,7 +127,7 @@ DEFINE_CLASS(ProtocolClass, theClass) /* 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/protw3.c b/mps/code/protw3.c index 6ebd38d6e50..1f76f0a4e80 100644 --- a/mps/code/protw3.c +++ b/mps/code/protw3.c @@ -106,11 +106,13 @@ LONG WINAPI ProtSEHfilter(LPEXCEPTION_POINTERS info) void ProtSetup(void) { + void *handler; /* See "AddVectoredExceptionHandler function (Windows)" */ /* ProtSetup is called only once per process, not once per arena, so this exception handler is only installed once. */ - AddVectoredExceptionHandler(1uL, ProtSEHfilter); + handler = AddVectoredExceptionHandler(1uL, ProtSEHfilter); + AVER(handler != NULL); } diff --git a/mps/code/pthrdext.c b/mps/code/pthrdext.c index 7185a0ff441..59d5899c326 100644 --- a/mps/code/pthrdext.c +++ b/mps/code/pthrdext.c @@ -1,7 +1,7 @@ /* pthreadext.c: POSIX THREAD EXTENSIONS * * $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. * * .purpose: Provides extension to Pthreads. * @@ -178,8 +178,8 @@ extern Bool PThreadextCheck(PThreadext pthreadext) CHECKS(PThreadext, pthreadext); /* can't check ID */ - CHECKL(RingCheck(&pthreadext->threadRing)); - CHECKL(RingCheck(&pthreadext->idRing)); + CHECKD_NOSIG(Ring, &pthreadext->threadRing); + CHECKD_NOSIG(Ring, &pthreadext->idRing); if (pthreadext->suspendedMFC == NULL) { /* not suspended */ CHECKL(RingIsSingle(&pthreadext->threadRing)); @@ -366,7 +366,7 @@ unlock: /* 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/qs.c b/mps/code/qs.c index 89f93fb2833..ed54b998b87 100644 --- a/mps/code/qs.c +++ b/mps/code/qs.c @@ -186,7 +186,7 @@ static void swap(void) static void makerndlist(unsigned l) { - unsigned i; + size_t i; mps_word_t r; mps_addr_t addr; @@ -318,15 +318,14 @@ static void validate(void) for(i = 0; i < listl; ++i) { cdie(((QSCell)reg[1])->tag == QSInt, "validate int"); if((mps_word_t)((QSCell)reg[1])->value != list[i]) { - fprintf(stdout, - "mps_res_t: Element %"PRIuLONGEST" of the two lists do not match.\n", - (ulongest_t)i); + (void)fprintf(stdout, "mps_res_t: Element %"PRIuLONGEST" of the " + "two lists do not match.\n", (ulongest_t)i); return; } reg[1] = (mps_addr_t)((QSCell)reg[1])->tail; } cdie(reg[1] == (mps_word_t)0, "validate end"); - fprintf(stdout, "Note: Lists compare equal.\n"); + (void)fprintf(stdout, "Note: Lists compare equal.\n"); } @@ -335,7 +334,6 @@ static void *go(void *p, size_t s) mps_fmt_t format; mps_chain_t chain; mps_addr_t base; - mps_addr_t *addr; testlib_unused(p); testlib_unused(s); @@ -358,9 +356,7 @@ static void *go(void *p, size_t s) "RootCreateTable"); base = &activationStack; - addr = base; - die(mps_root_create_table(&actroot, arena, mps_rank_ambig(), 0, - addr, sizeof(QSCell)/sizeof(mps_addr_t)), + die(mps_root_create_table(&actroot, arena, mps_rank_ambig(), 0, base, 1), "RootCreateTable"); /* makes a random list */ diff --git a/mps/code/replay.c b/mps/code/replay.c index 974ce5dcd07..9f761119c4f 100644 --- a/mps/code/replay.c +++ b/mps/code/replay.c @@ -21,7 +21,7 @@ #include "mpstd.h" -#ifdef MPS_PF_W3I6MV +#if defined(MPS_OS_W3) && defined(MPS_ARCH_I6) #define PRIuLONGEST "llu" #define PRIXPTR "016llX" typedef unsigned long long ulongest_t; @@ -47,6 +47,7 @@ static Word eventTime = 0; /* current event time */ /* error -- error signalling */ +ATTRIBUTE_FORMAT((printf, 1, 2)) static void error(const char *format, ...) { va_list args; diff --git a/mps/code/reserv.c b/mps/code/reserv.c index 310695c97df..02b18d66d88 100644 --- a/mps/code/reserv.c +++ b/mps/code/reserv.c @@ -1,7 +1,7 @@ /* reserv.c: ARENA RESERVOIR * * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * IMPROVEMENTS * @@ -74,6 +74,7 @@ DEFINE_POOL_CLASS(ReservoirPoolClass, this) this->offset = offsetof(ReservoirStruct, poolStruct); this->init = ResPoolInit; this->finish = ResPoolFinish; + AVERT(PoolClass, this); } @@ -94,7 +95,7 @@ Bool ReservoirCheck(Reservoir reservoir) /* could call ReservoirIsConsistent, but it's costly. */ tract = reservoir->reserve; if (tract != NULL) { - CHECKL(TractCheck(tract)); + CHECKD_NOSIG(Tract, tract); CHECKL(TractPool(tract) == ReservoirPool(reservoir)); } CHECKL(SizeIsAligned(reservoir->reservoirLimit, ArenaAlign(arena))); @@ -281,7 +282,7 @@ Bool ReservoirDeposit(Reservoir reservoir, Addr *baseIO, Size *sizeIO) /* put as many pages as necessary into the reserve & free the rest */ TRACT_FOR(tract, addr, arena, base, limit) { - AVER(TractCheck(tract)); + AVERT(Tract, tract); if (reservoir->reservoirSize < reslimit) { /* Reassign the tract to the reservoir pool */ TractFinish(tract); @@ -416,7 +417,7 @@ void ReservoirFinish (Reservoir reservoir) /* 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/root.c b/mps/code/root.c index edb932f800a..4277550a7fb 100644 --- a/mps/code/root.c +++ b/mps/code/root.c @@ -1,7 +1,7 @@ /* root.c: ROOT IMPLEMENTATION * * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * .purpose: This is the implementation of the root datatype. * @@ -98,7 +98,7 @@ Bool RootCheck(Root root) CHECKS(Root, root); CHECKU(Arena, root->arena); CHECKL(root->serial < ArenaGlobals(root->arena)->rootSerial); - CHECKL(RingCheck(&root->arenaRing)); + CHECKD_NOSIG(Ring, &root->arenaRing); CHECKL(RankCheck(root->rank)); CHECKL(TraceSetCheck(root->grey)); /* Don't need to check var here, because of the switch below */ @@ -121,7 +121,7 @@ Bool RootCheck(Root root) case RootREG: CHECKL(root->the.reg.scan != NULL); - CHECKL(ThreadCheck(root->the.reg.thread)); + CHECKD_NOSIG(Thread, root->the.reg.thread); /* */ break; case RootFMT: @@ -261,7 +261,7 @@ Res RootCreateTable(Root *rootReturn, Arena arena, AVER(rootReturn != NULL); AVERT(Arena, arena); - AVER(RankCheck(rank)); + AVERT(Rank, rank); AVER(base != 0); AVER(base < limit); @@ -281,7 +281,7 @@ Res RootCreateTableMasked(Root *rootReturn, Arena arena, AVER(rootReturn != NULL); AVERT(Arena, arena); - AVER(RankCheck(rank)); + AVERT(Rank, rank); AVER(base != 0); AVER(base < limit); /* Can't check anything about mask. */ @@ -302,7 +302,7 @@ Res RootCreateReg(Root *rootReturn, Arena arena, AVER(rootReturn != NULL); AVERT(Arena, arena); - AVER(RankCheck(rank)); + AVERT(Rank, rank); AVERT(Thread, thread); AVER(scan != NULL); @@ -322,7 +322,7 @@ Res RootCreateFmt(Root *rootReturn, Arena arena, AVER(rootReturn != NULL); AVERT(Arena, arena); - AVER(RankCheck(rank)); + AVERT(Rank, rank); AVER(FUNCHECK(scan)); AVER(base != 0); AVER(base < limit); @@ -342,7 +342,7 @@ Res RootCreateFun(Root *rootReturn, Arena arena, Rank rank, AVER(rootReturn != NULL); AVERT(Arena, arena); - AVER(RankCheck(rank)); + AVERT(Rank, rank); AVER(FUNCHECK(scan)); theUnion.fun.scan = scan; @@ -671,7 +671,7 @@ Res RootsDescribe(Globals arenaGlobals, mps_lib_FILE *stream) /* 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/sa.c b/mps/code/sa.c index 59ddd4be178..e8bddfa5bbc 100644 --- a/mps/code/sa.c +++ b/mps/code/sa.c @@ -48,13 +48,11 @@ Bool SparseArrayCheck(SparseArray sa) CHECKS(SparseArray, sa); CHECKL(sa->base != NULL); CHECKL(sa->elementSize >= 1); - /* TODO: CHECKD(VM, sa->vm); once VMStruct becomes visible */ - CHECKL(VMCheck(sa->vm)); + CHECKD_NOSIG(VM, sa->vm); /* */ CHECKL(sa->elementSize <= VMAlign(sa->vm)); CHECKL(sa->length > 0); - /* TODO: Make BTCheck extern and use everywhere. */ - /* CHECKL(BTCheck(sa->mapped)); */ - /* CHECKL(BTCheck(sa->pages)); */ + CHECKD_NOSIG(BT, sa->mapped); + CHECKD_NOSIG(BT, sa->pages); CHECKL(sa->shift == SizeLog2(VMAlign(sa->vm))); return TRUE; } diff --git a/mps/code/sac.c b/mps/code/sac.c index 2a87f9a2810..435988cf867 100644 --- a/mps/code/sac.c +++ b/mps/code/sac.c @@ -1,7 +1,7 @@ /* sac.c: SEGREGATED ALLOCATION CACHES * * $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" @@ -249,7 +249,7 @@ Res SACFill(Addr *p_o, SAC sac, Size size, Bool hasReservoirPermit) AVER(p_o != NULL); AVERT(SAC, sac); AVER(size != 0); - AVER(BoolCheck(hasReservoirPermit)); + AVERT(Bool, hasReservoirPermit); esac = ExternalSACOfSAC(sac); sacFind(&i, &blockSize, sac, size); @@ -384,7 +384,7 @@ void SACFlush(SAC sac) /* 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/sacss.c b/mps/code/sacss.c index a5fc3734029..ee86c83989d 100644 --- a/mps/code/sacss.c +++ b/mps/code/sacss.c @@ -47,13 +47,13 @@ static mps_res_t make(mps_addr_t *p, mps_sac_t sac, size_t size) static mps_res_t stress(mps_class_t class, size_t classes_count, mps_sac_classes_s *classes, - size_t (*size)(int i), mps_arena_t arena, ...) + size_t (*size)(size_t i), mps_arena_t arena, ...) { mps_res_t res; mps_pool_t pool; mps_sac_t sac; va_list arg; - int i, k; + size_t i, k; int *ps[testSetSIZE]; size_t ss[testSetSIZE]; @@ -94,26 +94,26 @@ static mps_res_t stress(mps_class_t class, /* upper half, as when allocating them again we want smaller objects */ /* see randomSize() */ switch (k % 2) { - case 0: { + case 0: for (i=testSetSIZE/2; i (b)) ? (a) : (b)) - - /* randomSize8 -- produce sizes both latge and small */ -static size_t randomSize8(int i) +static size_t randomSize8(size_t i) { size_t maxSize = 2 * 160 * 0x2000; size_t size; @@ -143,47 +140,34 @@ static size_t randomSize8(int i) /* testInArena -- test all the pool classes in the given arena */ -static mps_pool_debug_option_s debugOptions8 = { - /* .fence_template = */ (const void *)"postpost", - /* .fence_size = */ 8, - /* .free_template = */ (const void *)"DEAD", - /* .free_size = */ 4 -}; - -static mps_pool_debug_option_s debugOptions16 = { +static mps_pool_debug_option_s debugOptions = { /* .fence_template = */ (const void *)"postpostpostpost", - /* .fence_size = */ 16, + /* .fence_size = */ MPS_PF_ALIGN, /* .free_template = */ (const void *)"DEAD", /* .free_size = */ 4 }; -static mps_sac_classes_s classes8[4] = { {8, 1, 1}, {16, 1, 2}, {136, 9, 5}, - {topClassSIZE, 9, 4} }; +static mps_sac_classes_s classes[4] = { + {MPS_PF_ALIGN, 1, 1}, + {MPS_PF_ALIGN * 2, 1, 2}, + {128 + MPS_PF_ALIGN, 9, 5}, + {topClassSIZE, 9, 4} +}; -static mps_sac_classes_s classes16[4] = { {16, 1, 1}, {32, 1, 2}, {144, 9, 5}, - {topClassSIZE, 9, 4} }; - -static int testInArena(mps_arena_t arena) +static void testInArena(mps_arena_t arena) { - mps_pool_debug_option_s *debugOptions; - mps_sac_classes_s *classes; - - debugOptions = MPS_PF_ALIGN == 8 ? &debugOptions8 : &debugOptions16; - classes = MPS_PF_ALIGN == 8 ? classes8 : classes16; - printf("MVFF\n\n"); die(stress(mps_class_mvff(), classCOUNT, classes, randomSize8, arena, (size_t)65536, (size_t)32, (mps_align_t)MPS_PF_ALIGN, TRUE, TRUE, TRUE), "stress MVFF"); printf("MV debug\n\n"); die(stress(mps_class_mv_debug(), classCOUNT, classes, randomSize8, arena, - debugOptions, (size_t)65536, (size_t)32, (size_t)65536), + &debugOptions, (size_t)65536, (size_t)32, (size_t)65536), "stress MV debug"); printf("MV\n\n"); die(stress(mps_class_mv(), classCOUNT, classes, randomSize8, arena, (size_t)65536, (size_t)32, (size_t)65536), "stress MV"); - return 0; } @@ -201,7 +185,6 @@ int main(int argc, char *argv[]) MPS_ARGS_BEGIN(args) { MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, testArenaSIZE); MPS_ARGS_ADD(args, MPS_KEY_ARENA_ZONED, FALSE); - MPS_ARGS_DONE(args); die(mps_arena_create_k(&arena, mps_arena_class_vm(), args), "mps_arena_create"); } MPS_ARGS_END(args); diff --git a/mps/code/seg.c b/mps/code/seg.c index 7e6ad00defa..dea2b7d7ff7 100644 --- a/mps/code/seg.c +++ b/mps/code/seg.c @@ -1,7 +1,7 @@ /* seg.c: SEGMENTS * * $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: The design for this module is . * @@ -68,7 +68,7 @@ Res SegAlloc(Seg *segReturn, SegClass class, SegPref pref, AVERT(SegPref, pref); AVER(size > (Size)0); AVERT(Pool, pool); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); arena = PoolArena(pool); AVERT(Arena, arena); @@ -152,7 +152,7 @@ static Res SegInit(Seg seg, Pool pool, Addr base, Size size, AVER(SizeIsAligned(size, align)); class = seg->class; AVERT(SegClass, class); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); limit = AddrAdd(base, size); seg->limit = limit; @@ -168,7 +168,7 @@ static Res SegInit(Seg seg, Pool pool, Addr base, Size size, seg->sig = SegSig; /* set sig now so tract checks will see it */ TRACT_FOR(tract, addr, arena, base, limit) { - AVER(TractCheck(tract)); /* */ + AVERT(Tract, tract); AVER(TractP(tract) == NULL); AVER(!TractHasSeg(tract)); AVER(TractPool(tract) == pool); @@ -196,7 +196,7 @@ static Res SegInit(Seg seg, Pool pool, Addr base, Size size, failInit: RingFinish(SegPoolRing(seg)); TRACT_FOR(tract, addr, arena, base, limit) { - AVER(TractCheck(tract)); /* */ + AVERT(Tract, tract); TRACT_UNSET_SEG(tract); } seg->sig = SigInvalid; @@ -233,7 +233,7 @@ static void SegFinish(Seg seg) limit = SegLimit(seg); TRACT_TRACT_FOR(tract, addr, arena, seg->firstTract, limit) { - AVER(TractCheck(tract)); /* */ + AVERT(Tract, tract); TractSetWhite(tract, TraceSetEMPTY); TRACT_UNSET_SEG(tract); } @@ -263,7 +263,7 @@ static void SegFinish(Seg seg) void SegSetGrey(Seg seg, TraceSet grey) { AVERT(Seg, seg); - AVER(TraceSetCheck(grey)); + AVERT(TraceSet, grey); AVER(grey == TraceSetEMPTY || SegRankSet(seg) != RankSetEMPTY); /* Don't dispatch to the class method if there's no actual change in @@ -281,7 +281,7 @@ void SegSetGrey(Seg seg, TraceSet grey) void SegSetWhite(Seg seg, TraceSet white) { AVERT(Seg, seg); - AVER(TraceSetCheck(white)); + AVERT(TraceSet, white); seg->class->setWhite(seg, white); } @@ -296,7 +296,7 @@ void SegSetWhite(Seg seg, TraceSet white) void SegSetRankSet(Seg seg, RankSet rankSet) { AVERT(Seg, seg); - AVER(RankSetCheck(rankSet)); + AVERT(RankSet, rankSet); AVER(rankSet != RankSetEMPTY || SegSummary(seg) == RefSetEMPTY); seg->class->setRankSet(seg, rankSet); } @@ -325,7 +325,7 @@ void SegSetSummary(Seg seg, RefSet summary) void SegSetRankAndSummary(Seg seg, RankSet rankSet, RefSet summary) { AVERT(Seg, seg); - AVER(RankSetCheck(rankSet)); + AVERT(RankSet, rankSet); #ifdef DISABLE_REMEMBERED_SET if (rankSet != RankSetEMPTY) { @@ -574,7 +574,6 @@ Res SegMerge(Seg *mergedSegReturn, Seg segLo, Seg segHi, Addr base, mid, limit; Arena arena; Res res; - va_list args; AVER(NULL != mergedSegReturn); AVERT(Seg, segLo); @@ -586,7 +585,7 @@ Res SegMerge(Seg *mergedSegReturn, Seg segLo, Seg segHi, mid = SegLimit(segLo); limit = SegLimit(segHi); AVER(SegBase(segHi) == SegLimit(segLo)); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); arena = PoolArena(SegPool(segLo)); ShieldFlush(arena); /* see */ @@ -594,7 +593,6 @@ Res SegMerge(Seg *mergedSegReturn, Seg segLo, Seg segHi, /* Invoke class-specific methods to do the merge */ res = class->merge(segLo, segHi, base, mid, limit, withReservoirPermit); - va_end(args); if (ResOK != res) goto failMerge; @@ -639,7 +637,7 @@ Res SegSplit(Seg *segLoReturn, Seg *segHiReturn, Seg seg, Addr at, AVER(AddrIsAligned(at, arena->alignment)); AVER(at > base); AVER(at < limit); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); ShieldFlush(arena); /* see */ @@ -695,7 +693,7 @@ Bool SegCheck(Seg seg) /* can't assume nailed is subset of white - mightn't be during whiten */ /* CHECKL(TraceSetSub(seg->nailed, seg->white)); */ CHECKL(TraceSetCheck(seg->grey)); - CHECKL(TractCheck(seg->firstTract)); /* */ + CHECKD_NOSIG(Tract, seg->firstTract); pool = SegPool(seg); CHECKU(Pool, pool); arena = PoolArena(pool); @@ -709,7 +707,7 @@ Bool SegCheck(Seg seg) TRACT_TRACT_FOR(tract, addr, arena, seg->firstTract, seg->limit) { Seg trseg = NULL; /* suppress compiler warning */ - CHECKL(TractCheck(tract)); /* */ + CHECKD_NOSIG(Tract, tract); CHECKL(TRACT_SEG(&trseg, tract) && (trseg == seg)); CHECKL(TractWhite(tract) == seg->white); CHECKL(TractPool(tract) == pool); @@ -721,7 +719,7 @@ Bool SegCheck(Seg seg) /* the segment is initialized.) */ /* CHECKL(RingNext(&seg->poolRing) != &seg->poolRing); */ - CHECKL(RingCheck(&seg->poolRing)); + CHECKD_NOSIG(Ring, &seg->poolRing); /* "pm", "sm", and "depth" not checked. See .check.shield. */ CHECKL(RankSetCheck(seg->rankSet)); @@ -732,6 +730,8 @@ Bool SegCheck(Seg seg) CHECKL(seg->sm == AccessSetEMPTY); CHECKL(seg->pm == AccessSetEMPTY); } else { + /* Segments with ranks may only belong to scannable pools. */ + CHECKL(PoolHasAttr(pool, AttrSCAN)); /* : The Tracer only permits */ /* one rank per segment [ref?] so this field is either empty or a */ /* singleton. */ @@ -765,8 +765,8 @@ static Res segTrivInit(Seg seg, Pool pool, Addr base, Size size, AVER(SegBase(seg) == base); AVER(SegSize(seg) == size); AVER(SegPool(seg) == pool); - AVER(BoolCheck(reservoirPermit)); - AVER(ArgListCheck(args)); + AVERT(Bool, reservoirPermit); + AVERT(ArgList, args); UNUSED(args); return ResOK; } @@ -786,7 +786,7 @@ static void segTrivFinish(Seg seg) static void segNoSetGrey(Seg seg, TraceSet grey) { AVERT(Seg, seg); - AVER(TraceSetCheck(grey)); + AVERT(TraceSet, grey); AVER(seg->rankSet != RankSetEMPTY); NOTREACHED; } @@ -797,7 +797,7 @@ static void segNoSetGrey(Seg seg, TraceSet grey) static void segNoSetWhite(Seg seg, TraceSet white) { AVERT(Seg, seg); - AVER(TraceSetCheck(white)); + AVERT(TraceSet, white); NOTREACHED; } @@ -807,7 +807,7 @@ static void segNoSetWhite(Seg seg, TraceSet white) static void segNoSetRankSet(Seg seg, RankSet rankSet) { AVERT(Seg, seg); - AVER(RankSetCheck(rankSet)); + AVERT(RankSet, rankSet); NOTREACHED; } @@ -827,7 +827,7 @@ static void segNoSetSummary(Seg seg, RefSet summary) static void segNoSetRankSummary(Seg seg, RankSet rankSet, RefSet summary) { AVERT(Seg, seg); - AVER(RankSetCheck(rankSet)); + AVERT(RankSet, rankSet); UNUSED(summary); NOTREACHED; } @@ -867,7 +867,7 @@ static Res segNoMerge(Seg seg, Seg segHi, AVER(SegLimit(seg) == mid); AVER(SegBase(segHi) == mid); AVER(SegLimit(segHi) == limit); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); NOTREACHED; return ResFAIL; } @@ -903,7 +903,7 @@ static Res segTrivMerge(Seg seg, Seg segHi, AVER(SegLimit(seg) == mid); AVER(SegBase(segHi) == mid); AVER(SegLimit(segHi) == limit); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); /* .similar. */ AVER(seg->rankSet == segHi->rankSet); @@ -921,7 +921,7 @@ static Res segTrivMerge(Seg seg, Seg segHi, seg->limit = limit; TRACT_FOR(tract, addr, arena, mid, limit) { - AVER(TractCheck(tract)); /* */ + AVERT(Tract, tract); AVER(TractHasSeg(tract)); AVER(segHi == TractP(tract)); AVER(TractPool(tract) == pool); @@ -951,7 +951,7 @@ static Res segNoSplit(Seg seg, Seg segHi, AVER(mid < limit); AVER(SegBase(seg) == base); AVER(SegLimit(seg) == limit); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); NOTREACHED; return ResFAIL; @@ -982,7 +982,7 @@ static Res segTrivSplit(Seg seg, Seg segHi, AVER(mid < limit); AVER(SegBase(seg) == base); AVER(SegLimit(seg) == limit); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); /* Segment may not be exposed, or in the shield cache */ /* See & */ @@ -1004,7 +1004,7 @@ static Res segTrivSplit(Seg seg, Seg segHi, RingInit(SegPoolRing(segHi)); TRACT_FOR(tract, addr, arena, mid, limit) { - AVER(TractCheck(tract)); /* */ + AVERT(Tract, tract); AVER(TractHasSeg(tract)); AVER(seg == TractP(tract)); AVER(TractPool(tract) == pool); @@ -1095,7 +1095,7 @@ Bool GCSegCheck(GCSeg gcseg) Seg seg; CHECKS(GCSeg, gcseg); seg = &gcseg->segStruct; - CHECKL(SegCheck(seg)); + CHECKD(Seg, seg); if (gcseg->buffer != NULL) { CHECKU(Buffer, gcseg->buffer); @@ -1105,7 +1105,7 @@ Bool GCSegCheck(GCSeg gcseg) } /* The segment should be on a grey ring if and only if it is grey. */ - CHECKL(RingCheck(&gcseg->greyRing)); + CHECKD_NOSIG(Ring, &gcseg->greyRing); CHECKL((seg->grey == TraceSetEMPTY) == RingIsSingle(&gcseg->greyRing)); @@ -1137,7 +1137,7 @@ static Res gcSegInit(Seg seg, Pool pool, Addr base, Size size, AVER(SizeIsAligned(size, align)); gcseg = SegGCSeg(seg); AVER(&gcseg->segStruct == seg); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); /* Initialize the superclass fields first via next-method call */ super = SEG_SUPERCLASS(GCSegClass); @@ -1314,7 +1314,7 @@ static void gcSegSetWhite(Seg seg, TraceSet white) TRACT_TRACT_FOR(tract, addr, arena, seg->firstTract, limit) { Seg trseg = NULL; /* suppress compiler warning */ - AVER_CRITICAL(TractCheck(tract)); /* */ + AVERT_CRITICAL(Tract, tract); AVER_CRITICAL(TRACT_SEG(&trseg, tract) && (trseg == seg)); TractSetWhite(tract, white); } @@ -1502,7 +1502,7 @@ static Res gcSegMerge(Seg seg, Seg segHi, AVER(SegLimit(seg) == mid); AVER(SegBase(segHi) == mid); AVER(SegLimit(segHi) == limit); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); buf = gcsegHi->buffer; /* any buffer on segHi must be reassigned */ AVER(buf == NULL || gcseg->buffer == NULL); /* See .buffer */ @@ -1568,7 +1568,7 @@ static Res gcSegSplit(Seg seg, Seg segHi, AVER(mid < limit); AVER(SegBase(seg) == base); AVER(SegLimit(seg) == limit); - AVER(BoolCheck(withReservoirPermit)); + AVERT(Bool, withReservoirPermit); grey = SegGrey(seg); buf = gcseg->buffer; /* Look for buffer to reassign to segHi */ @@ -1651,7 +1651,7 @@ static Res gcSegDescribe(Seg seg, mps_lib_FILE *stream) Bool SegClassCheck(SegClass class) { - CHECKL(ProtocolClassCheck(&class->protocol)); + CHECKD(ProtocolClass, &class->protocol); CHECKL(class->name != NULL); /* Should be <= 6 char C identifier */ CHECKL(class->size >= sizeof(SegStruct)); CHECKL(FUNCHECK(class->init)); @@ -1688,6 +1688,7 @@ DEFINE_CLASS(SegClass, class) class->split = segTrivSplit; class->describe = segTrivDescribe; class->sig = SegClassSig; + AVERT(SegClass, class); } @@ -1712,6 +1713,7 @@ DEFINE_CLASS(GCSegClass, class) class->merge = gcSegMerge; class->split = gcSegSplit; class->describe = gcSegDescribe; + AVERT(SegClass, class); } @@ -1731,7 +1733,7 @@ void SegClassMixInNoSplitMerge(SegClass class) /* 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/segsmss.c b/mps/code/segsmss.c index 06c6b7c01fb..21a8b8846ed 100644 --- a/mps/code/segsmss.c +++ b/mps/code/segsmss.c @@ -33,8 +33,8 @@ /* Forward declarations */ -static SegClass AMSTSegClassGet(void); -static PoolClass AMSTPoolClassGet(void); +extern SegClass AMSTSegClassGet(void); +extern PoolClass AMSTPoolClassGet(void); /* Start by defining the AMST pool (AMS Test pool) */ @@ -67,7 +67,7 @@ typedef struct AMSTStruct *AMST; static Bool AMSTCheck(AMST amst) { CHECKS(AMST, amst); - CHECKL(AMSCheck(AMST2AMS(amst))); + CHECKD_NOSIG(AMS, AMST2AMS(amst)); /* */ return TRUE; } @@ -104,7 +104,7 @@ typedef struct AMSTSegStruct { static Bool AMSTSegCheck(AMSTSeg amstseg) { CHECKS(AMSTSeg, amstseg); - CHECKL(AMSSegCheck(&amstseg->amsSegStruct)); + CHECKD_NOSIG(AMSSeg, &amstseg->amsSegStruct); /* */ /* don't bother to do other checks - this is a stress test */ return TRUE; } @@ -129,7 +129,7 @@ static Res amstSegInit(Seg seg, Pool pool, Addr base, Size size, amst = Pool2AMST(pool); AVERT(AMST, amst); /* no useful checks for base and size */ - AVER(BoolCheck(reservoirPermit)); + AVERT(Bool, reservoirPermit); /* Initialize the superclass fields first via next-method call */ super = SEG_SUPERCLASS(AMSTSegClass); @@ -294,6 +294,7 @@ DEFINE_SEG_CLASS(AMSTSegClass, class) class->finish = amstSegFinish; class->split = amstSegSplit; class->merge = amstSegMerge; + AVERT(SegClass, class); } @@ -310,7 +311,7 @@ static Res AMSTSegSizePolicy(Size *sizeReturn, AVER(sizeReturn != NULL); AVERT(Pool, pool); AVER(size > 0); - AVER(RankSetCheck(rankSet)); + AVERT(RankSet, rankSet); arena = PoolArena(pool); @@ -674,6 +675,7 @@ DEFINE_POOL_CLASS(AMSTPoolClass, this) this->init = AMSTInit; this->finish = AMSTFinish; this->bufferFill = AMSTBufferFill; + AVERT(PoolClass, this); } @@ -789,7 +791,7 @@ static void *test(void *arg, size_t s) &ambigRoots[0], ambigRootsCOUNT), "root_create_table(ambig)"); - fputs(indent, stdout); + (void)fputs(indent, stdout); /* create an ap, and leave it busy */ die(mps_reserve(&busy_init, busy_ap, 64), "mps_reserve busy"); @@ -801,7 +803,7 @@ static void *test(void *arg, size_t s) printf("\nSize %"PRIuLONGEST" bytes, %"PRIuLONGEST" objects.\n", (ulongest_t)totalSize, (ulongest_t)objs); printf("%s", indent); - fflush(stdout); + (void)fflush(stdout); for(i = 0; i < exactRootsCOUNT; ++i) cdie(exactRoots[i] == objNULL || dylan_check(exactRoots[i]), "all roots check"); @@ -832,7 +834,7 @@ static void *test(void *arg, size_t s) ++objs; if (objs % 256 == 0) { printf("."); - fflush(stdout); + (void)fflush(stdout); } } diff --git a/mps/code/splay.c b/mps/code/splay.c index 9e2be1e98ad..7e061cd14f4 100644 --- a/mps/code/splay.c +++ b/mps/code/splay.c @@ -48,6 +48,7 @@ Bool SplayTreeCheck(SplayTree splay) CHECKL(FUNCHECK(splay->compare)); CHECKL(FUNCHECK(splay->nodeKey)); CHECKL(FUNCHECK(splay->updateNode)); + /* Can't use CHECKD_NOSIG because TreeEMPTY is NULL. */ CHECKL(TreeCheck(splay->root)); return TRUE; } @@ -800,7 +801,7 @@ Bool SplayTreeDelete(SplayTree splay, Tree node) { TreeClearRight(node); SplayTreeSetRoot(splay, TreeLeft(node)); TreeClearLeft(node); - SplaySplay(splay, NULL, compareGreater); + (void)SplaySplay(splay, NULL, compareGreater); leftLast = SplayTreeRoot(splay); AVER(leftLast != TreeEMPTY); AVER(!TreeHasRight(leftLast)); @@ -856,7 +857,7 @@ static Tree SplayTreeSuccessor(SplayTree splay) { /* temporarily chop off the left half-tree, inclusive of root */ SplayTreeSetRoot(splay, TreeRight(oldRoot)); TreeSetRight(oldRoot, TreeEMPTY); - SplaySplay(splay, NULL, compareLess); + (void)SplaySplay(splay, NULL, compareLess); newRoot = SplayTreeRoot(splay); AVER(newRoot != TreeEMPTY); AVER(TreeLeft(newRoot) == TreeEMPTY); @@ -968,7 +969,7 @@ Tree SplayTreeFirst(SplayTree splay) { if (SplayTreeIsEmpty(splay)) return TreeEMPTY; - SplaySplay(splay, NULL, compareLess); + (void)SplaySplay(splay, NULL, compareLess); node = SplayTreeRoot(splay); AVER(node != TreeEMPTY); AVER(TreeLeft(node) == TreeEMPTY); diff --git a/mps/code/spw3i3mv.c b/mps/code/spw3i3.c similarity index 94% rename from mps/code/spw3i3mv.c rename to mps/code/spw3i3.c index 3bb8ce94d0f..1439d069c40 100644 --- a/mps/code/spw3i3mv.c +++ b/mps/code/spw3i3.c @@ -1,4 +1,4 @@ -/* spw3i3mv.c: STACK PROBE FOR 32-BIT WINDOWS +/* spw3i3.c: STACK PROBE FOR 32-BIT WINDOWS * * $Id$ * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. @@ -13,6 +13,13 @@ #include "mpm.h" +#ifdef MPS_BUILD_PC + +/* "[ISO] Inline assembly code is not portable." */ +#pragma warn(disable: 2007) + +#endif /* MPS_BUILD_PC */ + void StackProbe(Size depth) { diff --git a/mps/code/spw3i6mv.c b/mps/code/spw3i6.c similarity index 96% rename from mps/code/spw3i6mv.c rename to mps/code/spw3i6.c index 751e9680e4b..29b1f8b8dcf 100644 --- a/mps/code/spw3i6mv.c +++ b/mps/code/spw3i6.c @@ -1,4 +1,4 @@ -/* spw3i6mv.c: STACK PROBE FOR 64-BIT WINDOWS +/* spw3i6.c: STACK PROBE FOR 64-BIT WINDOWS * * $Id$ * Copyright (c) 2013 Ravenbrook Limited. See end of file for license. @@ -16,12 +16,13 @@ * to be entered recursively. */ +#include /* _alloca */ + #include "mpm.h" -#include void StackProbe(Size depth) { - _alloca(depth*sizeof(Word)); + (void)_alloca(depth*sizeof(Word)); } diff --git a/mps/code/ssw3i3mv.c b/mps/code/ssw3i3mv.c index ac0b09fd670..d879780734a 100644 --- a/mps/code/ssw3i3mv.c +++ b/mps/code/ssw3i3mv.c @@ -37,6 +37,8 @@ Res StackScan(ScanState ss, Addr *stackBot) AVER(sizeof(((_JUMP_BUFFER *)jb)->Esi) == sizeof(Addr)); AVER(sizeof(((_JUMP_BUFFER *)jb)->Ebx) == sizeof(Addr)); + /* Ensure that the callee-save registers will be found by + StackScanInner when it's passed the address of the Ebx field. */ AVER(offsetof(_JUMP_BUFFER, Edi) == offsetof(_JUMP_BUFFER, Ebx) + 4); AVER(offsetof(_JUMP_BUFFER, Esi) == offsetof(_JUMP_BUFFER, Ebx) + 8); diff --git a/mps/code/ssw3i3pc.c b/mps/code/ssw3i3pc.c new file mode 100644 index 00000000000..e03754c7eba --- /dev/null +++ b/mps/code/ssw3i3pc.c @@ -0,0 +1,104 @@ +/* ssw3i3pc.c: STACK SCANNING FOR WIN32 WITH PELLES C + * + * $Id$ + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * + * This scans the stack and fixes the registers which may contain roots. + * See . + * + * .assume.ms-compat: We rely on the fact that Pelles C's setjmp stores + * the callee-save registers in the jmp_buf and is compatible with Microsoft + * C. The Pelles C 7.00 setjmp.h header has a comment "MS compatible". See + * also "Is Pelles C's jmp_buf compatible with Microsoft C's?" + * + * + * REFERENCES + * + * "Argument Passing and Naming Conventions"; MSDN; Microsoft Corporation; + * . + * + * "Calling conventions for different C++ compilers and operating systems"; + * Agner Fog; Copenhagen University College of Engineering; 2012-02-29; + * . + */ + +#include "mpm.h" +#include + +SRCID(ssw3i3pc, "$Id$"); + + +/* This definition isn't in the Pelles C headers, so we reproduce it here. + * See .assume.ms-compat. */ + +typedef struct __JUMP_BUFFER { + unsigned long Ebp; + unsigned long Ebx; + unsigned long Edi; + unsigned long Esi; + unsigned long Esp; + unsigned long Eip; + unsigned long Registration; + unsigned long TryLevel; + unsigned long Cookie; + unsigned long UnwindFunc; + unsigned long UnwindData[6]; +} _JUMP_BUFFER; + + +Res StackScan(ScanState ss, Addr *stackBot) +{ + jmp_buf jb; + + /* .assume.ms-compat */ + (void)setjmp(jb); + + /* Ensure that the callee-save registers will be found by + StackScanInner when it's passed the address of the Ebx field. */ + AVER(offsetof(_JUMP_BUFFER, Edi) == offsetof(_JUMP_BUFFER, Ebx) + 4); + AVER(offsetof(_JUMP_BUFFER, Esi) == offsetof(_JUMP_BUFFER, Ebx) + 8); + + return StackScanInner(ss, stackBot, (Addr *)&((_JUMP_BUFFER *)jb)->Ebx, 3); +} + + +/* C. COPYRIGHT AND LICENSE + * + * Copyright (C) 2001-2014 Ravenbrook Limited . + * All rights reserved. This is an open source license. Contact + * Ravenbrook for commercial licensing options. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Redistributions in any form must be accompanied by information on how + * to obtain complete source code for this software and any accompanying + * software that uses this software. The source code must either be + * included in the distribution or be available for no more than the cost + * of distribution plus a nominal fee, and must be freely redistributable + * under reasonable conditions. For an executable file, complete source + * code means the source code for all modules it contains. It does not + * include source code for modules or files that typically accompany the + * major components of the operating system on which the executable file + * runs. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ diff --git a/mps/code/ssw3i6mv.c b/mps/code/ssw3i6mv.c index 807577a89a2..16c33e3fb74 100644 --- a/mps/code/ssw3i6mv.c +++ b/mps/code/ssw3i6mv.c @@ -1,7 +1,7 @@ -/* ssw3i6mv.c: STACK SCANNING FOR WIN32 WITH MICROSOFT C +/* ssw3i6mv.c: STACK SCANNING FOR WIN64 WITH MICROSOFT C * * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * This scans the stack and fixes the registers which may contain roots. * See . It's unlikely that the callee-save @@ -64,7 +64,7 @@ Res StackScan(ScanState ss, Addr *stackBot) /* 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/ssw3i6pc.c b/mps/code/ssw3i6pc.c new file mode 100644 index 00000000000..89fbbeac420 --- /dev/null +++ b/mps/code/ssw3i6pc.c @@ -0,0 +1,143 @@ +/* ssw3i6pc.c: STACK SCANNING FOR WIN64 WITH PELLES C + * + * $Id$ + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + * + * This scans the stack and fixes the registers which may contain roots. + * See . + * + * .assume.ms-compat: We rely on the fact that Pelles C's setjmp stores + * the callee-save registers in the jmp_buf and is compatible with Microsoft + * C. The Pelles C 7.00 setjmp.h header has a comment "MS compatible". See + * also "Is Pelles C's jmp_buf compatible with Microsoft C's?" + * + * + * REFERENCES + * + * "Overview of x64 Calling Conventions"; MSDN; Microsoft Corporation; + * . + * + * "Caller/Callee Saved Registers"; MSDN; Microsoft Corporation; + * . + * + * "Register Usage"; MSDN; Microsoft Corporation; + * . + * + * "Calling conventions for different C++ compilers and operating systems"; + * Agner Fog; Copenhagen University College of Engineering; 2012-02-29; + * . + */ + +#include "mpm.h" +#include + +SRCID(ssw3i6pc, "$Id$"); + + +/* This definition isn't in the Pelles C headers, so we reproduce it here. + * See .assume.ms-compat. */ + +typedef /* _CRT_ALIGN(16) */ struct _SETJMP_FLOAT128 { + unsigned __int64 Part[2]; +} SETJMP_FLOAT128; + +typedef struct _JUMP_BUFFER { + unsigned __int64 Frame; + unsigned __int64 Rbx; + unsigned __int64 Rsp; + unsigned __int64 Rbp; + unsigned __int64 Rsi; + unsigned __int64 Rdi; + unsigned __int64 R12; + unsigned __int64 R13; + unsigned __int64 R14; + unsigned __int64 R15; + unsigned __int64 Rip; + unsigned __int64 Spare; + + SETJMP_FLOAT128 Xmm6; + SETJMP_FLOAT128 Xmm7; + SETJMP_FLOAT128 Xmm8; + SETJMP_FLOAT128 Xmm9; + SETJMP_FLOAT128 Xmm10; + SETJMP_FLOAT128 Xmm11; + SETJMP_FLOAT128 Xmm12; + SETJMP_FLOAT128 Xmm13; + SETJMP_FLOAT128 Xmm14; + SETJMP_FLOAT128 Xmm15; +} _JUMP_BUFFER; + + +Res StackScan(ScanState ss, Addr *stackBot) +{ + jmp_buf jb; + + /* We rely on the fact that Pelles C's setjmp stores the callee-save + registers in the jmp_buf. */ + (void)setjmp(jb); + + /* These checks will just serve to warn us at compile-time if the + setjmp.h header changes to indicate that the registers we want aren't + saved any more. */ + AVER(sizeof(((_JUMP_BUFFER *)jb)->Rdi) == sizeof(Addr)); + AVER(sizeof(((_JUMP_BUFFER *)jb)->Rsi) == sizeof(Addr)); + AVER(sizeof(((_JUMP_BUFFER *)jb)->Rbp) == sizeof(Addr)); + AVER(sizeof(((_JUMP_BUFFER *)jb)->R12) == sizeof(Addr)); + AVER(sizeof(((_JUMP_BUFFER *)jb)->R13) == sizeof(Addr)); + AVER(sizeof(((_JUMP_BUFFER *)jb)->R14) == sizeof(Addr)); + AVER(sizeof(((_JUMP_BUFFER *)jb)->R15) == sizeof(Addr)); + + /* The layout of the jmp_buf forces us to harmlessly scan Rsp as well. */ + AVER(offsetof(_JUMP_BUFFER, Rsp) == offsetof(_JUMP_BUFFER, Rbx) + 8); + AVER(offsetof(_JUMP_BUFFER, Rbp) == offsetof(_JUMP_BUFFER, Rbx) + 16); + AVER(offsetof(_JUMP_BUFFER, Rsi) == offsetof(_JUMP_BUFFER, Rbx) + 24); + AVER(offsetof(_JUMP_BUFFER, Rdi) == offsetof(_JUMP_BUFFER, Rbx) + 32); + AVER(offsetof(_JUMP_BUFFER, R12) == offsetof(_JUMP_BUFFER, Rbx) + 40); + AVER(offsetof(_JUMP_BUFFER, R13) == offsetof(_JUMP_BUFFER, Rbx) + 48); + AVER(offsetof(_JUMP_BUFFER, R14) == offsetof(_JUMP_BUFFER, Rbx) + 56); + AVER(offsetof(_JUMP_BUFFER, R15) == offsetof(_JUMP_BUFFER, Rbx) + 64); + + return StackScanInner(ss, stackBot, (Addr *)&((_JUMP_BUFFER *)jb)->Rbx, 9); +} + + +/* C. COPYRIGHT AND LICENSE + * + * Copyright (C) 2001-2014 Ravenbrook Limited . + * All rights reserved. This is an open source license. Contact + * Ravenbrook for commercial licensing options. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Redistributions in any form must be accompanied by information on how + * to obtain complete source code for this software and any accompanying + * software that uses this software. The source code must either be + * included in the distribution or be available for no more than the cost + * of distribution plus a nominal fee, and must be freely redistributable + * under reasonable conditions. For an executable file, complete source + * code means the source code for all modules it contains. It does not + * include source code for modules or files that typically accompany the + * major components of the operating system on which the executable file + * runs. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ diff --git a/mps/code/steptest.c b/mps/code/steptest.c index 73cc730b790..4d6353e78df 100644 --- a/mps/code/steptest.c +++ b/mps/code/steptest.c @@ -109,7 +109,8 @@ static double my_clock(void) { FILETIME ctime, etime, ktime, utime; double dk, du; - GetProcessTimes(currentProcess, &ctime, &etime, &ktime, &utime); + cdie(GetProcessTimes(currentProcess, &ctime, &etime, &ktime, &utime) != 0, + "GetProcessTimes"); dk = ktime.dwHighDateTime * 4096.0 * 1024.0 * 1024.0 + ktime.dwLowDateTime; dk /= 10.0; @@ -391,7 +392,7 @@ static void *test(void *arg, size_t s) if (collections > old_collections) { old_collections = collections; putchar('.'); - fflush(stdout); + (void)fflush(stdout); } } @@ -419,8 +420,8 @@ static void *test(void *arg, size_t s) printf("Collection statistics:\n"); printf(" %"PRIuLONGEST" collections\n", (ulongest_t)collections); printf(" %"PRIuLONGEST" bytes condemned.\n", (ulongest_t)condemned); - printf(" %lu bytes not condemned.\n", - (unsigned long)not_condemned); + printf(" %"PRIuLONGEST" bytes not condemned.\n", + (ulongest_t)not_condemned); printf(" %"PRIuLONGEST" bytes survived.\n", (ulongest_t)live); if (condemned) { printf(" Mortality %5.2f%%.\n", @@ -429,10 +430,10 @@ static void *test(void *arg, size_t s) ((double)condemned/(condemned + not_condemned)) * 100.0); } if (collections) { - printf(" Condemned per collection %lu bytes.\n", - (unsigned long)condemned/collections); - printf(" Reclaimed per collection %lu bytes.\n", - (unsigned long)(condemned - live)/collections); + printf(" Condemned per collection %"PRIuLONGEST" bytes.\n", + (ulongest_t)condemned/collections); + printf(" Reclaimed per collection %"PRIuLONGEST" bytes.\n", + (ulongest_t)(condemned - live)/collections); } printf("Allocation statistics:\n"); diff --git a/mps/code/teletest.c b/mps/code/teletest.c index 17002585133..844fbc51329 100644 --- a/mps/code/teletest.c +++ b/mps/code/teletest.c @@ -19,19 +19,10 @@ SRCID(teletest, "$Id$"); static mps_arena_t arena; - +#define WORD_FORMAT "0x%0" PRIwWORD PRIuLONGEST #define MAX_ARGS 3 #define INPUT_BUFFER_SIZE 512 -#if (MPS_WORD_WIDTH == 32) -#define WORD_FORMAT "0x%08lx" -#elif (MPS_WORD_WIDTH == 64) -#define WORD_FORMAT "0x%016lx" -#else -#error "Unrecognized word width" -#endif - - static mps_word_t args[MAX_ARGS]; static char *stringArg; static Count argCount; @@ -43,7 +34,8 @@ static void callControl(mps_word_t reset, mps_word_t flip) old = mps_telemetry_control(reset, flip); new = mps_telemetry_control((mps_word_t)0, (mps_word_t)0); - (void)printf(WORD_FORMAT " -> " WORD_FORMAT "\n", old, new); + (void)printf(WORD_FORMAT " -> " WORD_FORMAT "\n", + (ulongest_t)old, (ulongest_t)new); } @@ -58,7 +50,7 @@ static void doRead(void) mps_word_t old; old = mps_telemetry_control((mps_word_t)0, (mps_word_t)0); - (void)printf(WORD_FORMAT "\n", old); + (void)printf(WORD_FORMAT "\n", (ulongest_t)old); } @@ -85,7 +77,7 @@ static void doIntern(void) mps_word_t id; id = mps_telemetry_intern(stringArg); - (void)printf(WORD_FORMAT "\n", id); + (void)printf(WORD_FORMAT "\n", (ulongest_t)id); } static void doLabel(void) @@ -209,13 +201,14 @@ extern int main(int argc, char *argv[]) while(1) { char input[INPUT_BUFFER_SIZE]; printf("telemetry test> "); - fflush(stdout); + (void)fflush(stdout); if (fgets(input, INPUT_BUFFER_SIZE , stdin)) { obeyCommand(input); } else { - doQuit(); + break; } } + mps_arena_destroy(arena); return EXIT_SUCCESS; } diff --git a/mps/code/testlib.c b/mps/code/testlib.c index 8ef14ca3c78..18fe005ae5b 100644 --- a/mps/code/testlib.c +++ b/mps/code/testlib.c @@ -19,19 +19,6 @@ struct itimerspec; /* stop complaints from time.h */ #endif #include -#ifdef MPS_BUILD_MV -/* MSVC warning 4702 = unreachable code - * - * job000605: believed needed to prevent VC7 warning - * for error() below, in which va_end is mandated by - * ISO C (C99:7.15.1) even though it is unreachable. - */ -#pragma warning(disable: 4702) -/* MSVC warning 4996 = stdio / C runtime 'unsafe' */ -/* Objects to: sscanf. See job001934. */ -#pragma warning( disable : 4996 ) -#endif - /* fail -- like assert, but (notionally) returns a value, so usable in an expression */ @@ -122,7 +109,7 @@ static unsigned long seed_verify_float = 1; static unsigned long rnd_verify_float(void) { double s; - s = seed_verify_float; + s = (double)seed_verify_float; s *= R_a_float; s = fmod(s, R_m_float); seed_verify_float = (unsigned long)s; @@ -285,7 +272,7 @@ void randomize(int argc, char *argv[]) argv[0], seed0); rnd_state_set(seed0); } - fflush(stdout); /* ensure seed is not lost in case of failure */ + (void)fflush(stdout); /* ensure seed is not lost in case of failure */ } unsigned long rnd_state(void) @@ -339,12 +326,13 @@ _mps_RES_ENUM(RES_STRINGS_ROW, X) /* verror -- die with message */ +ATTRIBUTE_FORMAT((printf, 1, 0)) void verror(const char *format, va_list args) { - fflush(stdout); /* synchronize */ - vfprintf(stderr, format, args); - fprintf(stderr, "\n"); - fflush(stderr); /* make sure the message is output */ + (void)fflush(stdout); /* synchronize */ + (void)vfprintf(stderr, format, args); + (void)fprintf(stderr, "\n"); + (void)fflush(stderr); /* make sure the message is output */ /* On Windows, the abort signal pops up a dialog box. This suspends * the test suite until a button is pressed, which is not acceptable * for offline testing, so if the MPS_TESTLIB_NOABORT environment @@ -360,6 +348,7 @@ void verror(const char *format, va_list args) /* error -- die with message */ +ATTRIBUTE_FORMAT((printf, 1, 2)) void error(const char *format, ...) { va_list args; @@ -413,7 +402,7 @@ void assert_die(const char *file, unsigned line, const char *condition) void testlib_init(int argc, char *argv[]) { - mps_lib_assert_fail_install(assert_die); + (void)mps_lib_assert_fail_install(assert_die); randomize(argc, argv); } diff --git a/mps/code/testlib.h b/mps/code/testlib.h index d36f26a275c..447834254f4 100644 --- a/mps/code/testlib.h +++ b/mps/code/testlib.h @@ -23,52 +23,48 @@ /* Suppress Visual C warnings at warning level 4, */ -/* see mail.richard.1997-09-25.13-26. */ +/* see mail.richard.1997-09-25.13-26 and job003715. */ /* Essentially the same settings are done in config.h. */ #ifdef MPS_BUILD_MV -/* "unreferenced inline function has been removed" (windows.h) */ -#pragma warning(disable: 4514) - /* "constant conditional" (MPS_END) */ #pragma warning(disable: 4127) -/* MSVC 2.0 generates a warning when using NOCHECK or UNUSED */ -#ifdef _MSC_VER -#if _MSC_VER < 1000 -#pragma warning(disable: 4705) -#endif -#else /* _MSC_VER */ -#error "Expected _MSC_VER to be defined for builder.mv" -#endif /* _MSC_VER */ - - -/* MSVC 10.00 on PowerPC generates erroneous warnings about */ -/* uninitialized local variables, if you take their address. */ -#ifdef MPS_ARCH_PP -#pragma warning(disable: 4701) -#endif - - -/* Non-checking varieties give many spurious warnings because parameters - * are suddenly unused, etc. We aren't interested in these. - */ - -#if defined(AVER_AND_CHECK_NONE) - -/* "unreferenced formal parameter" */ -#pragma warning(disable: 4100) - -/* "unreferenced local function has been removed" */ -#pragma warning(disable: 4505) - -#endif - - #endif /* MPS_BUILD_MV */ +/* Suppress Pelles C warnings at warning level 2 */ +/* Some of these are also done in config.h. */ + +#ifdef MPS_BUILD_PC + +/* "Structured Exception Handling is not portable." (mps_tramp). */ +#pragma warn(disable: 2008) + +/* "Unreachable code" (AVER, if condition is constantly true). */ +#pragma warn(disable: 2154) + +#endif /* MPS_BUILD_PC */ + + +/* Function attributes */ +/* These are also defined in config.h */ + +#if defined(MPS_BUILD_GC) || defined(MPS_BUILD_LL) + +/* GCC: + * Clang: + */ +#define ATTRIBUTE_FORMAT(ARGLIST) __attribute__((__format__ ARGLIST)) + +#else + +#define ATTRIBUTE_FORMAT(ARGLIST) + +#endif + + /* ulongest_t -- longest unsigned integer type * * Define a longest unsigned integer type for testing, scanning, and @@ -87,7 +83,7 @@ #error "How many beans make five?" #endif -#ifdef MPS_PF_W3I6MV +#if defined(MPS_OS_W3) && defined(MPS_ARCH_I6) #define PRIuLONGEST "llu" #define SCNuLONGEST "llu" #define SCNXLONGEST "llX" @@ -119,6 +115,20 @@ typedef long longest_t; #define testlib_unused(v) ((void)(v)) +/* max -- return larger value + * + * Note: evaluates its arguments twice. + */ + +#undef max +#define max(a, b) (((a) > (b)) ? (a) : (b)) + + +/* alignUp -- align word to alignment */ + +#define alignUp(w, a) (((w) + (a) - 1) & ~((size_t)(a) - 1)) + + /* die -- succeed or die * * If the first argument is not ResOK then prints the second @@ -167,7 +177,9 @@ void assert_die(const char *file, unsigned line, const char *condition); /* error, verror -- die with message */ +ATTRIBUTE_FORMAT((printf, 1, 2)) extern void error(const char *format, ...); +ATTRIBUTE_FORMAT((printf, 1, 0)) extern void verror(const char *format, va_list args); diff --git a/mps/code/than.c b/mps/code/than.c index 752ef3ed64c..a1dab12adc8 100644 --- a/mps/code/than.c +++ b/mps/code/than.c @@ -1,7 +1,7 @@ /* than.c: ANSI THREADS MANAGER * * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * This is a single-threaded implementation of the threads manager. * Has stubs for thread suspension. @@ -30,7 +30,7 @@ Bool ThreadCheck(Thread thread) CHECKS(Thread, thread); CHECKU(Arena, thread->arena); CHECKL(thread->serial < thread->arena->threadSerial); - CHECKL(RingCheck(&thread->arenaRing)); + CHECKD_NOSIG(Ring, &thread->arenaRing); return TRUE; } @@ -146,7 +146,7 @@ Res ThreadDescribe(Thread thread, mps_lib_FILE *stream) /* 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/thix.c b/mps/code/thix.c index 7760a5e1349..cc380dd040f 100644 --- a/mps/code/thix.c +++ b/mps/code/thix.c @@ -1,7 +1,7 @@ /* thix.c: Threads Manager for Posix threads * * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * .purpose: This is a pthreads implementation of the threads manager. * This implements . @@ -61,7 +61,7 @@ Bool ThreadCheck(Thread thread) CHECKS(Thread, thread); CHECKU(Arena, thread->arena); CHECKL(thread->serial < thread->arena->threadSerial); - CHECKL(RingCheck(&thread->arenaRing)); + CHECKD_NOSIG(Ring, &thread->arenaRing); CHECKD(PThreadext, &thread->thrextStruct); return TRUE; } @@ -292,7 +292,7 @@ Res ThreadDescribe(Thread thread, mps_lib_FILE *stream) /* 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/thw3.c b/mps/code/thw3.c index e1e5c97841b..701ffc53cdd 100644 --- a/mps/code/thw3.c +++ b/mps/code/thw3.c @@ -1,7 +1,7 @@ /* thw3i3.c: WIN32 THREAD MANAGER * * $Id$ - * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * Implements thread registration, suspension, and stack * scanning. See . @@ -60,7 +60,7 @@ Bool ThreadCheck(Thread thread) CHECKS(Thread, thread); CHECKU(Arena, thread->arena); CHECKL(thread->serial < thread->arena->threadSerial); - CHECKL(RingCheck(&thread->arenaRing)); + CHECKD_NOSIG(Ring, &thread->arenaRing); return TRUE; } @@ -233,7 +233,7 @@ Res ThreadDescribe(Thread thread, mps_lib_FILE *stream) /* 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/thxc.c b/mps/code/thxc.c index 745669cfc47..9e6a6bd325c 100644 --- a/mps/code/thxc.c +++ b/mps/code/thxc.c @@ -1,7 +1,7 @@ /* thxc.c: OS X MACH THREADS MANAGER * * $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. * * .design: See . * @@ -45,7 +45,7 @@ Bool ThreadCheck(Thread thread) CHECKS(Thread, thread); CHECKU(Arena, thread->arena); CHECKL(thread->serial < thread->arena->threadSerial); - CHECKL(RingCheck(&thread->arenaRing)); + CHECKD_NOSIG(Ring, &thread->arenaRing); CHECKL(MACH_PORT_VALID(thread->port)); return TRUE; } @@ -267,7 +267,7 @@ Res ThreadDescribe(Thread thread, mps_lib_FILE *stream) /* 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/trace.c b/mps/code/trace.c index e77f93cd483..924badcd541 100644 --- a/mps/code/trace.c +++ b/mps/code/trace.c @@ -1,7 +1,7 @@ /* trace.c: GENERIC TRACER IMPLEMENTATION * * $Id$ - * Copyright (c) 2001-2013 Ravenbrook Limited. + * Copyright (c) 2001-2014 Ravenbrook Limited. * See end of file for license. * Portions copyright (C) 2002 Global Graphics Software. * @@ -64,9 +64,9 @@ void ScanStateInit(ScanState ss, TraceSet ts, Arena arena, TraceId ti; Trace trace; - AVER(TraceSetCheck(ts)); + AVERT(TraceSet, ts); AVERT(Arena, arena); - AVER(RankCheck(rank)); + AVERT(Rank, rank); /* white is arbitrary and can't be checked */ /* NOTE: We can only currently support scanning for a set of traces with @@ -363,7 +363,7 @@ Res TraceAddWhite(Trace trace, Seg seg) if(TraceSetIsMember(SegWhite(seg), trace)) { trace->white = ZoneSetUnion(trace->white, ZoneSetOfSeg(trace->arena, seg)); /* if the pool is a moving GC, then condemned objects may move */ - if(pool->class->attr & AttrMOVINGGC) { + if(PoolHasAttr(pool, AttrMOVINGGC)) { trace->mayMove = ZoneSetUnion(trace->mayMove, ZoneSetOfSeg(trace->arena, seg)); } @@ -410,8 +410,9 @@ Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet) /* the requested zone set. Otherwise, we would bloat the */ /* foundation to no gain. Note that this doesn't exclude */ /* any segments from which the condemned set was derived, */ - if((SegPool(seg)->class->attr & AttrGC) != 0 - && ZoneSetSuper(condemnedSet, ZoneSetOfSeg(arena, seg))) { + if(PoolHasAttr(SegPool(seg), AttrGC) + && ZoneSetSuper(condemnedSet, ZoneSetOfSeg(arena, seg))) + { res = TraceAddWhite(trace, seg); if(res != ResOK) return res; @@ -503,9 +504,9 @@ static Res rootFlip(Root root, void *p) AVERT(Root, root); AVER(p != NULL); - AVER(TraceSetCheck(rf->ts)); + AVERT(TraceSet, rf->ts); AVERT(Arena, rf->arena); - AVER(RankCheck(rf->rank)); + AVERT(Rank, rf->rank); AVER(RootRank(root) <= RankEXACT); /* see .root.rank */ @@ -827,7 +828,7 @@ static void traceReclaim(Trace trace) AVER_CRITICAL(!TraceSetIsMember(SegGrey(seg), trace)); if(TraceSetIsMember(SegWhite(seg), trace)) { - AVER_CRITICAL((pool->class->attr & AttrGC) != 0); + AVER_CRITICAL(PoolHasAttr(pool, AttrGC)); STATISTIC(++trace->reclaimCount); PoolReclaim(pool, trace, seg); @@ -988,7 +989,7 @@ static Bool traceFindGrey(Seg *segReturn, Rank *rankReturn, Ring node, nextNode; AVER(segReturn != NULL); - AVER(TraceIdCheck(ti)); + AVERT(TraceId, ti); trace = ArenaTrace(arena, ti); @@ -1376,10 +1377,10 @@ void TraceScanSingleRef(TraceSet ts, Rank rank, Arena arena, { Res res; - AVER(TraceSetCheck(ts)); - AVER(RankCheck(rank)); + AVERT(TraceSet, ts); + AVERT(Rank, rank); AVERT(Arena, arena); - AVER(SegCheck(seg)); + AVERT(Seg, seg); AVER(refIO != NULL); res = traceScanSingleRefRes(ts, rank, arena, seg, refIO); @@ -1462,6 +1463,7 @@ Res TraceScanAreaTagged(ScanState ss, Addr *base, Addr *limit) * This is as TraceScanArea except words are only fixed if they are zero * when masked with a mask. */ +ATTRIBUTE_NO_SANITIZE_ADDRESS Res TraceScanAreaMasked(ScanState ss, Addr *base, Addr *limit, Word mask) { Res res; @@ -1616,9 +1618,6 @@ Res TraceStart(Trace trace, double mortality, double finishingTime) /* This is indicated by the rankSet begin non-empty. Such */ /* segments may only belong to scannable pools. */ if(SegRankSet(seg) != RankSetEMPTY) { - /* Segments with ranks may only belong to scannable pools. */ - AVER((SegPool(seg)->class->attr & AttrSCAN) != 0); - /* Turn the segment grey if there might be a reference in it */ /* to the white set. This is done by seeing if the summary */ /* of references in the segment intersects with the */ @@ -1633,19 +1632,21 @@ Res TraceStart(Trace trace, double mortality, double finishingTime) } } - if((SegPool(seg)->class->attr & AttrGC) - && !TraceSetIsMember(SegWhite(seg), trace)) { + if(PoolHasAttr(SegPool(seg), AttrGC) + && !TraceSetIsMember(SegWhite(seg), trace)) + { trace->notCondemned += size; } } } while (SegNext(&seg, arena, seg)); } - STATISTIC_BEGIN { + STATISTIC_STAT ({ /* @@ */ /* Iterate over all chains, all GenDescs within a chain, */ /* (and all PoolGens within a GenDesc). */ - Ring node, nextNode; + Ring node; + Ring nextNode; Index i; RING_FOR(node, &arena->chainRing, nextNode) { @@ -1658,7 +1659,7 @@ Res TraceStart(Trace trace, double mortality, double finishingTime) /* Now do topgen GenDesc (and all PoolGens within it). */ TraceStartPoolGen(NULL, &arena->topGen, TRUE, 0); - } STATISTIC_END; + }); res = RootsIterate(ArenaGlobals(arena), rootGrey, (void *)trace); AVER(res == ResOK); @@ -1728,7 +1729,6 @@ void TraceQuantum(Trace trace) if(traceFindGrey(&seg, &rank, arena, trace->ti)) { Res res; - AVER((SegPool(seg)->class->attr & AttrSCAN) != 0); res = traceScanSeg(TraceSetSingle(trace), rank, arena, seg); /* Allocation failures should be handled by emergency mode, and we don't expect any other error in a normal GC trace. */ @@ -1900,7 +1900,7 @@ failStart: /* 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/tract.c b/mps/code/tract.c index 69ae479cf1a..2468887bc17 100644 --- a/mps/code/tract.c +++ b/mps/code/tract.c @@ -1,7 +1,7 @@ /* tract.c: PAGE TABLES * * $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. * * .ullagepages: Pages whose page index is < allocBase are recorded as * free but never allocated as alloc starts searching after the tables. @@ -113,7 +113,7 @@ Bool ChunkCheck(Chunk chunk) CHECKS(Chunk, chunk); CHECKU(Arena, chunk->arena); CHECKL(chunk->serial < chunk->arena->chunkSerial); - CHECKL(RingCheck(&chunk->chunkRing)); + CHECKD_NOSIG(Ring, &chunk->chunkRing); CHECKL(ChunkPagesToSize(chunk, 1) == ChunkPageSize(chunk)); CHECKL(ShiftCheck(ChunkPageShift(chunk))); @@ -128,7 +128,7 @@ Bool ChunkCheck(Chunk chunk) CHECKL(chunk->allocBase <= chunk->pages); CHECKL(chunk->allocBase >= chunk->pageTablePages); - CHECKL(chunk->allocTable != NULL); + CHECKD_NOSIG(BT, chunk->allocTable); /* check that allocTable is in the chunk overhead */ CHECKL((Addr)chunk->allocTable >= chunk->base); CHECKL(AddrAdd((Addr)chunk->allocTable, BTSize(chunk->pages)) @@ -671,7 +671,7 @@ void PageFree(Chunk chunk, Index pi) /* 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/w3i3mv.nmk b/mps/code/w3i3mv.nmk index aa4bb064dd8..97a669700cc 100644 --- a/mps/code/w3i3mv.nmk +++ b/mps/code/w3i3mv.nmk @@ -5,16 +5,13 @@ PFM = w3i3mv -# /Gs appears to be necessary to suppress stack checks. Stack checks -# (if not suppressed) generate a dependency on the C library, __chkesp, -# which causes the linker step to fail when building the DLL, mpsdy.dll. -PFMDEFS = /DCONFIG_PF_STRING="w3i3mv" /DCONFIG_PF_W3I3MV \ - /DWIN32 /D_WINDOWS /Gs +PFMDEFS = /DCONFIG_PF_STRING="w3i3mv" /DCONFIG_PF_W3I3MV /DWIN32 /D_WINDOWS !INCLUDE commpre.nmk +!INCLUDE mv.nmk # MPM sources: core plus platform-specific. -MPM = $(MPMCOMMON) +MPM = $(MPMCOMMON) diff --git a/mps/code/w3i3pc.nmk b/mps/code/w3i3pc.nmk new file mode 100644 index 00000000000..d6d424b669d --- /dev/null +++ b/mps/code/w3i3pc.nmk @@ -0,0 +1,168 @@ +# w3i3pc.nmk: WINDOWS (IA-32) NMAKE FILE -*- makefile -*- +# +# $Id$ +# Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + +PFM = w3i3pc + +PFMDEFS = /DCONFIG_PF_STRING="w3i3pc" /DCONFIG_PF_W3I3PC /DWIN32 /D_WINDOWS + +!INCLUDE commpre.nmk +!INCLUDE pc.nmk + +# MPM sources: core plus platform-specific. +MPM = $(MPMCOMMON) + + + +# Source to object file mappings and CFLAGS amalgamation +# +# %%VARIETY %%PART: When adding a new variety or part, add new macros which +# expand to the files included in the part for each variety +# +# %%VARIETY: When adding a new variety, add a CFLAGS macro which expands to +# the flags that that variety should use when compiling C. And a LINKFLAGS +# macro which expands to the flags that the variety should use when building +# executables. And a LIBFLAGS macro which expands to the flags that the +# variety should use when building libraries + +!IF "$(VARIETY)" == "hot" +CFLAGS=$(CFLAGSCOMMONPRE) $(CFHOT) $(CFLAGSCOMMONPOST) +CFLAGSSQL=$(CFLAGSSQLPRE) $(CFHOT) $(CFLAGSSQLPOST) +LINKFLAGS=$(LINKFLAGSCOMMON) $(LFHOT) +LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSHOT) +MPMOBJ0 = $(MPM:<=w3i3pc\hot\) +PLINTHOBJ0 = $(PLINTH:<=w3i3pc\hot\) +AMSOBJ0 = $(AMS:<=w3i3pc\hot\) +AMCOBJ0 = $(AMC:<=w3i3pc\hot\) +AWLOBJ0 = $(AWL:<=w3i3pc\hot\) +LOOBJ0 = $(LO:<=w3i3pc\hot\) +SNCOBJ0 = $(SNC:<=w3i3pc\hot\) +MVFFOBJ0 = $(MVFF:<=w3i3pc\hot\) +DWOBJ0 = $(DW:<=w3i3pc\hot\) +FMTTESTOBJ0 = $(FMTTEST:<=w3i3pc\hot\) +POOLNOBJ0 = $(POOLN:<=w3i3pc\hot\) +TESTLIBOBJ0 = $(TESTLIB:<=w3i3pc\hot\) + +!ELSEIF "$(VARIETY)" == "cool" +CFLAGS=$(CFLAGSCOMMONPRE) $(CFCOOL) $(CFLAGSCOMMONPOST) +CFLAGSSQL=$(CFLAGSSQLPRE) $(CFCOOL) $(CFLAGSSQLPOST) +LINKFLAGS=$(LINKFLAGSCOMMON) $(LFCOOL) +LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSCOOL) +MPMOBJ0 = $(MPM:<=w3i3pc\cool\) +PLINTHOBJ0 = $(PLINTH:<=w3i3pc\cool\) +AMSOBJ0 = $(AMS:<=w3i3pc\cool\) +AMCOBJ0 = $(AMC:<=w3i3pc\cool\) +AWLOBJ0 = $(AWL:<=w3i3pc\cool\) +LOOBJ0 = $(LO:<=w3i3pc\cool\) +SNCOBJ0 = $(SNC:<=w3i3pc\cool\) +MVFFOBJ0 = $(MVFF:<=w3i3pc\cool\) +DWOBJ0 = $(DW:<=w3i3pc\cool\) +FMTTESTOBJ0 = $(FMTTEST:<=w3i3pc\cool\) +POOLNOBJ0 = $(POOLN:<=w3i3pc\cool\) +TESTLIBOBJ0 = $(TESTLIB:<=w3i3pc\cool\) + +!ELSEIF "$(VARIETY)" == "rash" +CFLAGS=$(CFLAGSCOMMONPRE) $(CFRASH) $(CFLAGSCOMMONPOST) +CFLAGSSQL=$(CFLAGSSQLPRE) $(CFRASH) $(CFLAGSSQLPOST) +LINKFLAGS=$(LINKFLAGSCOMMON) $(LFRASH) +LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSRASH) +MPMOBJ0 = $(MPM:<=w3i3pc\rash\) +PLINTHOBJ0 = $(PLINTH:<=w3i3pc\rash\) +AMSOBJ0 = $(AMS:<=w3i3pc\rash\) +AMCOBJ0 = $(AMC:<=w3i3pc\rash\) +AWLOBJ0 = $(AWL:<=w3i3pc\rash\) +LOOBJ0 = $(LO:<=w3i3pc\rash\) +SNCOBJ0 = $(SNC:<=w3i3pc\rash\) +MVFFOBJ0 = $(MVFF:<=w3i3pc\rash\) +DWOBJ0 = $(DW:<=w3i3pc\rash\) +FMTTESTOBJ0 = $(FMTTEST:<=w3i3pc\rash\) +POOLNOBJ0 = $(POOLN:<=w3i3pc\rash\) +TESTLIBOBJ0 = $(TESTLIB:<=w3i3pc\rash\) + +#!ELSEIF "$(VARIETY)" == "cv" +#CFLAGS=$(CFLAGSCOMMON) $(CFCV) +#LINKFLAGS=$(LINKFLAGSCOMMON) $(LFCV) +#LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSCV) +#MPMOBJ0 = $(MPM:<=w3i3pc\cv\) +#MPMOBJ = $(MPMOBJ0:>=.obj) +#PLINTHOBJ0 = $(PLINTH:<=w3i3pc\cv\) +#PLINTHOBJ = $(PLINTHOBJ0:>=.obj) +#AMSOBJ0 = $(AMS:<=w3i3pc\cv\) +#AMSOBJ = $(AMSOBJ0:>=.obj) +#AMCOBJ0 = $(AMC:<=w3i3pc\cv\) +#AMCOBJ = $(AMCOBJ0:>=.obj) +#AWLOBJ0 = $(AWL:<=w3i3pc\cv\) +#AWLOBJ = $(AWLOBJ0:>=.obj) +#LOOBJ0 = $(LO:<=w3i3pc\cv\) +#LOOBJ = $(LOOBJ0:>=.obj) +#SNCOBJ0 = $(SNC:<=w3i3pc\cv\) +#SNCOBJ = $(SNCOBJ0:>=.obj) +#DWOBJ0 = $(DW:<=w3i3pc\cv\) +#DWOBJ = $(DWOBJ0:>=.obj) +#POOLNOBJ0 = $(POOLN:<=w3i3pc\cv\) +#POOLNOBJ = $(POOLNOBJ0:>=.obj) +#TESTLIBOBJ0 = $(TESTLIB:<=w3i3pc\cv\) +#TESTLIBOBJ = $(TESTLIBOBJ0:>=.obj) + +!ENDIF + +# %%PART: When adding a new part, add new macros which expand to the object +# files included in the part + +MPMOBJ = $(MPMOBJ0:>=.obj) +PLINTHOBJ = $(PLINTHOBJ0:>=.obj) +AMSOBJ = $(AMSOBJ0:>=.obj) +AMCOBJ = $(AMCOBJ0:>=.obj) +AWLOBJ = $(AWLOBJ0:>=.obj) +LOOBJ = $(LOOBJ0:>=.obj) +SNCOBJ = $(SNCOBJ0:>=.obj) +MVFFOBJ = $(MVFFOBJ0:>=.obj) +DWOBJ = $(DWOBJ0:>=.obj) +FMTTESTOBJ = $(FMTTESTOBJ0:>=.obj) +POOLNOBJ = $(POOLNOBJ0:>=.obj) +TESTLIBOBJ = $(TESTLIBOBJ0:>=.obj) + + +!INCLUDE commpost.nmk + + +# C. COPYRIGHT AND LICENSE +# +# Copyright (C) 2001-2014 Ravenbrook Limited . +# All rights reserved. This is an open source license. Contact +# Ravenbrook for commercial licensing options. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Redistributions in any form must be accompanied by information on how +# to obtain complete source code for this software and any accompanying +# software that uses this software. The source code must either be +# included in the distribution or be available for no more than the cost +# of distribution plus a nominal fee, and must be freely redistributable +# under reasonable conditions. For an executable file, complete source +# code means the source code for all modules it contains. It does not +# include source code for modules or files that typically accompany the +# major components of the operating system on which the executable file +# runs. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mps/code/w3i6mv.nmk b/mps/code/w3i6mv.nmk index 0f0399a079e..6d31a81452d 100644 --- a/mps/code/w3i6mv.nmk +++ b/mps/code/w3i6mv.nmk @@ -5,15 +5,11 @@ PFM = w3i6mv -# /Gs appears to be necessary to suppress stack checks. Stack checks -# (if not suppressed) generate a dependency on the C library, __chkesp, -# which causes the linker step to fail when building the DLL, mpsdy.dll. -PFMDEFS = /DCONFIG_PF_STRING="w3i6mv" /DCONFIG_PF_W3I6MV \ - /DWIN32 /D_WINDOWS /Gs +PFMDEFS = /DCONFIG_PF_STRING="w3i6mv" /DCONFIG_PF_W3I6MV /DWIN32 /D_WINDOWS MASM = ml64 # MPM sources: core plus platform-specific. -MPM = $(MPMCOMMON) +MPM = $(MPMCOMMON) !INCLUDE commpre.nmk diff --git a/mps/code/w3i6pc.nmk b/mps/code/w3i6pc.nmk new file mode 100644 index 00000000000..1decdde0083 --- /dev/null +++ b/mps/code/w3i6pc.nmk @@ -0,0 +1,172 @@ +# -*- makefile -*- +# +# w3i6pc.nmk: NMAKE FILE FOR WINDOWS/x64/PELLES C +# +# $Id: //info.ravenbrook.com/project/mps/branch/2014-03-21/pellesc/code/w3i6pc.nmk#1 $ +# Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. + +PFM = w3i6pc + +PFMDEFS = /DCONFIG_PF_STRING="w3i6pc" /DCONFIG_PF_W3I6PC /DWIN32 /D_WINDOWS + +!INCLUDE commpre.nmk +!INCLUDE pc.nmk + +CFLAGSCOMMONPRE = $(CFLAGSCOMMONPRE) /Tamd64-coff + +# MPM sources: core plus platform-specific. +MPM = $(MPMCOMMON) + + + +# Source to object file mappings and CFLAGS amalgamation +# +# %%VARIETY %%PART: When adding a new variety or part, add new macros which +# expand to the files included in the part for each variety +# +# %%VARIETY: When adding a new variety, add a CFLAGS macro which expands to +# the flags that that variety should use when compiling C. And a LINKFLAGS +# macro which expands to the flags that the variety should use when building +# executables. And a LIBFLAGS macro which expands to the flags that the +# variety should use when building libraries + +!IF "$(VARIETY)" == "hot" +CFLAGS=$(CFLAGSCOMMONPRE) $(CFHOT) $(CFLAGSCOMMONPOST) +CFLAGSSQL=$(CFLAGSSQLPRE) $(CFHOT) $(CFLAGSSQLPOST) +LINKFLAGS=$(LINKFLAGSCOMMON) $(LFHOT) +LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSHOT) +MPMOBJ0 = $(MPM:<=w3i6pc\hot\) +PLINTHOBJ0 = $(PLINTH:<=w3i6pc\hot\) +AMSOBJ0 = $(AMS:<=w3i6pc\hot\) +AMCOBJ0 = $(AMC:<=w3i6pc\hot\) +AWLOBJ0 = $(AWL:<=w3i6pc\hot\) +LOOBJ0 = $(LO:<=w3i6pc\hot\) +SNCOBJ0 = $(SNC:<=w3i6pc\hot\) +MVFFOBJ0 = $(MVFF:<=w3i6pc\hot\) +DWOBJ0 = $(DW:<=w3i6pc\hot\) +FMTTESTOBJ0 = $(FMTTEST:<=w3i6pc\hot\) +POOLNOBJ0 = $(POOLN:<=w3i6pc\hot\) +TESTLIBOBJ0 = $(TESTLIB:<=w3i6pc\hot\) + +!ELSEIF "$(VARIETY)" == "cool" +CFLAGS=$(CFLAGSCOMMONPRE) $(CFCOOL) $(CFLAGSCOMMONPOST) +CFLAGSSQL=$(CFLAGSSQLPRE) $(CFCOOL) $(CFLAGSSQLPOST) +LINKFLAGS=$(LINKFLAGSCOMMON) $(LFCOOL) +LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSCOOL) +MPMOBJ0 = $(MPM:<=w3i6pc\cool\) +PLINTHOBJ0 = $(PLINTH:<=w3i6pc\cool\) +AMSOBJ0 = $(AMS:<=w3i6pc\cool\) +AMCOBJ0 = $(AMC:<=w3i6pc\cool\) +AWLOBJ0 = $(AWL:<=w3i6pc\cool\) +LOOBJ0 = $(LO:<=w3i6pc\cool\) +SNCOBJ0 = $(SNC:<=w3i6pc\cool\) +MVFFOBJ0 = $(MVFF:<=w3i6pc\cool\) +DWOBJ0 = $(DW:<=w3i6pc\cool\) +FMTTESTOBJ0 = $(FMTTEST:<=w3i6pc\cool\) +POOLNOBJ0 = $(POOLN:<=w3i6pc\cool\) +TESTLIBOBJ0 = $(TESTLIB:<=w3i6pc\cool\) + +!ELSEIF "$(VARIETY)" == "rash" +CFLAGS=$(CFLAGSCOMMONPRE) $(CFRASH) $(CFLAGSCOMMONPOST) +CFLAGSSQL=$(CFLAGSSQLPRE) $(CFRASH) $(CFLAGSSQLPOST) +LINKFLAGS=$(LINKFLAGSCOMMON) $(LFRASH) +LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSRASH) +MPMOBJ0 = $(MPM:<=w3i6pc\rash\) +PLINTHOBJ0 = $(PLINTH:<=w3i6pc\rash\) +AMSOBJ0 = $(AMS:<=w3i6pc\rash\) +AMCOBJ0 = $(AMC:<=w3i6pc\rash\) +AWLOBJ0 = $(AWL:<=w3i6pc\rash\) +LOOBJ0 = $(LO:<=w3i6pc\rash\) +SNCOBJ0 = $(SNC:<=w3i6pc\rash\) +MVFFOBJ0 = $(MVFF:<=w3i6pc\rash\) +DWOBJ0 = $(DW:<=w3i6pc\rash\) +FMTTESTOBJ0 = $(FMTTEST:<=w3i6pc\rash\) +POOLNOBJ0 = $(POOLN:<=w3i6pc\rash\) +TESTLIBOBJ0 = $(TESTLIB:<=w3i6pc\rash\) + +#!ELSEIF "$(VARIETY)" == "cv" +#CFLAGS=$(CFLAGSCOMMON) $(CFCV) +#LINKFLAGS=$(LINKFLAGSCOMMON) $(LFCV) +#LIBFLAGS=$(LIBFLAGSCOMMON) $(LIBFLAGSCV) +#MPMOBJ0 = $(MPM:<=w3i6pc\cv\) +#MPMOBJ = $(MPMOBJ0:>=.obj) +#PLINTHOBJ0 = $(PLINTH:<=w3i6pc\cv\) +#PLINTHOBJ = $(PLINTHOBJ0:>=.obj) +#AMSOBJ0 = $(AMS:<=w3i6pc\cv\) +#AMSOBJ = $(AMSOBJ0:>=.obj) +#AMCOBJ0 = $(AMC:<=w3i6pc\cv\) +#AMCOBJ = $(AMCOBJ0:>=.obj) +#AWLOBJ0 = $(AWL:<=w3i6pc\cv\) +#AWLOBJ = $(AWLOBJ0:>=.obj) +#LOOBJ0 = $(LO:<=w3i6pc\cv\) +#LOOBJ = $(LOOBJ0:>=.obj) +#SNCOBJ0 = $(SNC:<=w3i6pc\cv\) +#SNCOBJ = $(SNCOBJ0:>=.obj) +#DWOBJ0 = $(DW:<=w3i6pc\cv\) +#DWOBJ = $(DWOBJ0:>=.obj) +#POOLNOBJ0 = $(POOLN:<=w3i6pc\cv\) +#POOLNOBJ = $(POOLNOBJ0:>=.obj) +#TESTLIBOBJ0 = $(TESTLIB:<=w3i6pc\cv\) +#TESTLIBOBJ = $(TESTLIBOBJ0:>=.obj) + +!ENDIF + +# %%PART: When adding a new part, add new macros which expand to the object +# files included in the part + +MPMOBJ = $(MPMOBJ0:>=.obj) +PLINTHOBJ = $(PLINTHOBJ0:>=.obj) +AMSOBJ = $(AMSOBJ0:>=.obj) +AMCOBJ = $(AMCOBJ0:>=.obj) +AWLOBJ = $(AWLOBJ0:>=.obj) +LOOBJ = $(LOOBJ0:>=.obj) +SNCOBJ = $(SNCOBJ0:>=.obj) +MVFFOBJ = $(MVFFOBJ0:>=.obj) +DWOBJ = $(DWOBJ0:>=.obj) +FMTTESTOBJ = $(FMTTESTOBJ0:>=.obj) +POOLNOBJ = $(POOLNOBJ0:>=.obj) +TESTLIBOBJ = $(TESTLIBOBJ0:>=.obj) + + +!INCLUDE commpost.nmk + + +# C. COPYRIGHT AND LICENSE +# +# Copyright (C) 2001-2014 Ravenbrook Limited . +# All rights reserved. This is an open source license. Contact +# Ravenbrook for commercial licensing options. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Redistributions in any form must be accompanied by information on how +# to obtain complete source code for this software and any accompanying +# software that uses this software. The source code must either be +# included in the distribution or be available for no more than the cost +# of distribution plus a nominal fee, and must be freely redistributable +# under reasonable conditions. For an executable file, complete source +# code means the source code for all modules it contains. It does not +# include source code for modules or files that typically accompany the +# major components of the operating system on which the executable file +# runs. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +# PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mps/code/walk.c b/mps/code/walk.c index b17540e4954..3f7f67f99e1 100644 --- a/mps/code/walk.c +++ b/mps/code/walk.c @@ -1,7 +1,7 @@ /* walk.c: OBJECT WALKER * * $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" @@ -77,7 +77,7 @@ static void ArenaFormattedObjectsWalk(Arena arena, FormattedObjectsStepMethod f, do { Pool pool; pool = SegPool(seg); - if (pool->class->attr & AttrFMT) { + if (PoolHasAttr(pool, AttrFMT)) { ShieldExpose(arena, seg); PoolWalk(pool, seg, f, p, s); ShieldCover(arena, seg); @@ -171,7 +171,7 @@ static Bool rootsStepClosureCheck(rootsStepClosure rsc) CHECKL(FUNCHECK(rsc->f)); /* p and s fields are arbitrary closures which cannot be checked */ if (rsc->root != NULL) { - CHECKL(RootCheck(rsc->root)); + CHECKD_NOSIG(Root, rsc->root); /* */ } return TRUE; } @@ -243,7 +243,7 @@ static Res RootsWalkFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) /* If the segment isn't GCable then the ref is not to the heap and */ /* shouldn't be passed to the client. */ - AVER((SegPool(seg)->class->attr & AttrGC) != 0); + AVER(PoolHasAttr(SegPool(seg), AttrGC)); /* Call the client closure - .assume.rootaddr */ rsc->f((mps_addr_t*)refIO, (mps_root_t)rsc->root, rsc->p, rsc->s); @@ -307,8 +307,9 @@ static Res ArenaRootsWalk(Globals arenaGlobals, mps_roots_stepper_t f, /* NOTE: I'm not sure why this is. RB 2012-07-24 */ if (SegFirst(&seg, arena)) { do { - if ((SegPool(seg)->class->attr & AttrGC) != 0) { - TraceAddWhite(trace, seg); + if (PoolHasAttr(SegPool(seg), AttrGC)) { + res = TraceAddWhite(trace, seg); + AVER(res == ResOK); } } while (SegNext(&seg, arena, seg)); } @@ -362,7 +363,7 @@ void mps_arena_roots_walk(mps_arena_t mps_arena, mps_roots_stepper_t f, /* 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/walkt0.c b/mps/code/walkt0.c index 3365874c153..629a5276ead 100644 --- a/mps/code/walkt0.c +++ b/mps/code/walkt0.c @@ -11,6 +11,8 @@ #include "testlib.h" #include "mpslib.h" #include "mpscamc.h" +#include "mpscams.h" +#include "mpscawl.h" #include "mpsavm.h" #include "mpstd.h" #ifdef MPS_OS_W3 @@ -126,11 +128,16 @@ static void stepper(mps_addr_t object, mps_fmt_t format, return; } +static mps_addr_t test_awl_find_dependent(mps_addr_t addr) +{ + testlib_unused(addr); + return NULL; +} + /* test -- the body of the test */ -static void *test(void *arg, size_t s) +static void *test(mps_arena_t arena, mps_class_t pool_class) { - mps_arena_t arena; mps_chain_t chain; mps_fmt_t format; mps_pool_t pool; @@ -139,14 +146,15 @@ static void *test(void *arg, size_t s) unsigned long objs; struct stepper_data sdStruct, *sd; - arena = (mps_arena_t)arg; - (void)s; /* unused */ - die(dylan_fmt(&format, arena), "fmt_create"); die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); - die(mps_pool_create(&pool, arena, mps_class_amc(), format, chain), - "pool_create(amc)"); + MPS_ARGS_BEGIN(args) { + MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format); + MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain); + 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"); + } MPS_ARGS_END(args); die(mps_ap_create(&ap, pool, mps_rank_exact()), "ap_create"); @@ -199,7 +207,6 @@ int main(int argc, char *argv[]) { mps_arena_t arena; mps_thr_t thread; - void *r; testlib_init(argc, argv); @@ -207,7 +214,11 @@ int main(int argc, char *argv[]) testArenaSIZE), "arena_create"); die(mps_thread_reg(&thread, arena), "thread_reg"); - mps_tramp(&r, test, arena, 0); + + test(arena, mps_class_amc()); + test(arena, mps_class_awl()); + /* TODO: test(arena, mps_class_ams()); -- see job003738 */ + mps_thread_dereg(thread); mps_arena_destroy(arena); diff --git a/mps/code/zcoll.c b/mps/code/zcoll.c index 639a323957a..20cb8f06dc1 100644 --- a/mps/code/zcoll.c +++ b/mps/code/zcoll.c @@ -69,13 +69,6 @@ #include /* clock */ -#ifdef MPS_BUILD_MV -/* MSVC warning 4996 = stdio / C runtime 'unsafe' */ -/* Objects to: sscanf. See job001934. */ -#pragma warning( disable : 4996 ) -#endif - - /* testChain -- generation parameters for the test */ #define genCOUNT 2 static mps_gen_param_s testChain[genCOUNT] = { @@ -119,12 +112,11 @@ static void showStatsAscii(size_t notcon, size_t con, size_t live, size_t alimit count = (a < 200) ? a + 1 : c; for(i = 0; i < count; i++) { - printf( (i == a) ? "A" - : (i < n) ? "n" - : (i < l) ? "L" - : (i < c) ? "_" - : " " - ); + putchar((i == a) ? 'A' + : (i < n) ? 'n' + : (i < l) ? 'L' + : (i < c) ? '_' + : ' '); } printf("\n"); } @@ -197,8 +189,8 @@ static void get(mps_arena_t arena) switch(type) { case mps_message_type_gc_start(): { mclockBegin = mps_message_clock(arena, message); - printf(" %5lu: (%5lu)", - mclockBegin, mclockBegin - mclockEnd); + printf(" %5"PRIuLONGEST": (%5"PRIuLONGEST")", + (ulongest_t)mclockBegin, (ulongest_t)(mclockBegin - mclockEnd)); printf(" Coll Begin (%s)\n", mps_message_gc_start_why(arena, message)); break; @@ -212,8 +204,8 @@ static void get(mps_arena_t arena) mclockEnd = mps_message_clock(arena, message); - printf(" %5lu: (%5lu)", - mclockEnd, mclockEnd - mclockBegin); + printf(" %5"PRIuLONGEST": (%5"PRIuLONGEST")", + (ulongest_t)mclockEnd, (ulongest_t)(mclockEnd - mclockBegin)); printf(" Coll End "); showStatsText(notcon, con, live); if(rnd()==0) showStatsAscii(notcon, con, live, alimit); @@ -223,7 +215,8 @@ static void get(mps_arena_t arena) mps_message_finalization_ref(&objaddr, arena, message); obj = objaddr; objind = DYLAN_INT_INT(DYLAN_VECTOR_SLOT(obj, 0)); - printf(" Finalization for object %lu at %p\n", objind, objaddr); + printf(" Finalization for object %"PRIuLONGEST" at %p\n", + (ulongest_t)objind, objaddr); break; } default: { @@ -302,7 +295,7 @@ static void CatalogCheck(void) mps_word_t w; void *Catalog, *Page, *Art, *Poly; unsigned long Catalogs = 0, Pages = 0, Arts = 0, Polys = 0; - int i, j, k; + size_t i, j, k; /* retrieve Catalog from root */ Catalog = myrootExact[CatalogRootIndex]; @@ -360,7 +353,7 @@ static void CatalogDo(mps_arena_t arena, mps_ap_t ap) { mps_word_t v; void *Catalog, *Page, *Art, *Poly; - int i, j, k; + size_t i, j, k; die(make_dylan_vector(&v, ap, CatalogFix + CatalogVar), "Catalog"); DYLAN_VECTOR_SLOT(v, 0) = DYLAN_INT(CatalogSig); @@ -370,7 +363,7 @@ static void CatalogDo(mps_arena_t arena, mps_ap_t ap) myrootExact[CatalogRootIndex] = Catalog; get(arena); - fflush(stdout); + (void)fflush(stdout); CatalogCheck(); for(i = 0; i < CatalogVar; i += 1) { @@ -382,8 +375,8 @@ static void CatalogDo(mps_arena_t arena, mps_ap_t ap) DYLAN_VECTOR_SLOT(Catalog, CatalogFix + i) = (mps_word_t)Page; get(arena); - printf("Page %d: make articles\n", i); - fflush(stdout); + printf("Page %"PRIuLONGEST": make articles\n", (ulongest_t)i); + (void)fflush(stdout); for(j = 0; j < PageVar; j += 1) { die(make_dylan_vector(&v, ap, ArtFix + ArtVar), "Art"); @@ -405,7 +398,7 @@ static void CatalogDo(mps_arena_t arena, mps_ap_t ap) } } } - fflush(stdout); + (void)fflush(stdout); CatalogCheck(); } @@ -532,7 +525,7 @@ static void Make(mps_arena_t arena, mps_ap_t ap, unsigned randm, unsigned keep1i static void Rootdrop(char rank_char) { - unsigned i; + size_t i; if(rank_char == 'A') { for(i = 0; i < myrootAmbigCOUNT; ++i) { @@ -551,7 +544,7 @@ static void Rootdrop(char rank_char) #define stackwipedepth 50000 static void stackwipe(void) { - unsigned iw; + size_t iw; unsigned long aw[stackwipedepth]; /* Do some pointless work that the compiler won't optimise away, so that @@ -625,7 +618,7 @@ static void testscriptC(mps_arena_t arena, mps_ap_t ap, const char *script) script += sb; printf(" Collect\n"); stackwipe(); - mps_arena_collect(arena); + die(mps_arena_collect(arena), "mps_arena_collect"); mps_arena_release(arena); break; } @@ -735,7 +728,7 @@ static void *testscriptB(void *arg, size_t s) mps_fmt_t fmt; mps_chain_t chain; mps_pool_t amc; - int i; + size_t i; mps_root_t root_table_Ambig; mps_root_t root_table_Exact; mps_ap_t ap; @@ -937,7 +930,7 @@ int main(int argc, char *argv[]) /* C. COPYRIGHT AND LICENSE * - * Copyright (c) 2001-2014 Ravenbrook Limited . + * Copyright (c) 2008-2014 Ravenbrook Limited . * All rights reserved. This is an open source license. Contact * Ravenbrook for commercial licensing options. * diff --git a/mps/code/zmess.c b/mps/code/zmess.c index 1c87ac56cf2..a97c10ea8f1 100644 --- a/mps/code/zmess.c +++ b/mps/code/zmess.c @@ -179,7 +179,8 @@ static void report(mps_arena_t arena, const char *pm, Bool discard) mps_message_finalization_ref(&objaddr, arena, message); obj = objaddr; objind = DYLAN_INT_INT(DYLAN_VECTOR_SLOT(obj, 0)); - printf(" Finalization for object %lu at %p\n", objind, objaddr); + printf(" Finalization for object %"PRIuLONGEST" at %p\n", + (ulongest_t)objind, objaddr); cdie(myroot[objind] == NULL, "finalized live"); cdie(state[objind] == finalizableSTATE, "not finalizable"); state[objind] = finalizedSTATE; @@ -242,7 +243,7 @@ static void testscriptC(mps_arena_t arena, const char *script) } case 'C': { printf(" Collect\n"); - mps_arena_collect(arena); + die(mps_arena_collect(arena), "mps_arena_collect"); break; } case 'F': { @@ -308,7 +309,7 @@ static void *testscriptB(void *arg, size_t s) mps_root_t root_table; mps_ap_t ap; mps_root_t root_stackreg; - int i; + size_t i; int N = myrootCOUNT - 1; void *stack_starts_here; /* stack scanning starts here */ @@ -441,6 +442,9 @@ static void testscriptA(const char *script) * * TIMCA_remote returns a Bool, true for let "ControlAlloc succeed". */ + +#ifdef TEST_CONTROLALLOC_FAILURE + static const char *TIMCA_str = ""; static int TIMCA_done = 0; static void TIMCA_setup(const char *string) @@ -480,6 +484,8 @@ Bool TIMCA_remote(void) return succeed; } +#endif /* TEST_CONTROLALLOC_FAILURE */ + /* main -- runs various test scripts * @@ -534,7 +540,8 @@ int main(int argc, char *argv[]) * * See . */ - if(0) { +#if TEST_CONTROLALLOC_FAILURE + { /* ArenaCreate unable to pre-allocate: THESE SHOULD FAIL */ /* manually edit if(0) -> if(1) to test these */ if(0) { @@ -561,6 +568,7 @@ int main(int argc, char *argv[]) TIMCA_setup(""); /* must reset it! */ } +#endif printf("%s: Conclusion: Failed to find any defects.\n", argv[0]); return 0; diff --git a/mps/design/check.txt b/mps/design/check.txt index c0d2a8a97b3..47d757d3945 100644 --- a/mps/design/check.txt +++ b/mps/design/check.txt @@ -95,17 +95,30 @@ type structure pointer, possibly invoking ``Check`` (depending on level; see `.level`_). It should be called with the child type and pointer. -_`.full-type`: ``CHECKS()``, ``CHECKD()``, ``CHECKU()``, all operate -only on fully fledged types. This means the type has to provide a -function ``Bool TypeCheck(Type type)`` where ``Type`` is substituted -for the name of the type (for example, ``PoolCheck()``), and the -expression ``obj->sig`` must be a valid value of type ``Sig`` whenever -``obj`` is a valid value of type ``Type``. +_`.full-type`: Use ``CHECKS()``, ``CHECKD()`` or ``CHECKU()`` on all +types that satisfy these three requirements: -_`.type.no-sig`: This tag is to be referenced in implementations -whenever the form ``CHECKL(ThingCheck(thing))`` is used instead of -``CHECK{U,D}(Thing, thing)`` because ``Thing`` is not a fully fledged -type (`.full-type`_). +_`.full-type.pointer`: The type is a pointer type. + +_`.full-type.check`: The type provides a function ``Bool TypeCheck(Type +type)`` where ``Type`` is substituted for the name of the type (for +example, ``PoolCheck()``). + +_`.full-type.sig`: The expression ``obj->sig`` is a valid value of +type ``Sig`` whenever ``obj`` is a valid value of type ``Type``. + +_`.partial-type`: Where the type satisfies `.full-type.pointer`_ and +`.full-type.check`_ but not `.full-type.sig`_ because the type lacks a +signature in order to save space (this applies to small structures +that are embedded many times in other structures, for example +``Ring``), use ``CHECKD_NOSIG()``. + +_`.hidden-type`: Where the type satisfies `.full-type.pointer`_ and +`.full-type.check`_ but not `.full-type.sig`_ because the structure +has a signature but the structure definition is not visible at point +of checking (for example ``Root``), use ``CHECKD_NOSIG()`` and +reference this tag. The structure could be considered for addition to +``mpmst.h``. Document History diff --git a/mps/design/interface-c.txt b/mps/design/interface-c.txt index fabf45f6344..1585318fa28 100644 --- a/mps/design/interface-c.txt +++ b/mps/design/interface-c.txt @@ -6,7 +6,7 @@ C interface design :Tag: design.mps.interface.c :Author: Richard Brooksby :Date: 1996-07-29 -:Status: incomplete document +:Status: complete design :Revision: $Id$ :Copyright: See `Copyright and License`_. :Index terms: pair: C interface; design @@ -29,7 +29,9 @@ Goals _`.goal.c`: The file impl.h.mps is the C external interface to the MPS. It is the default interface between client code written in C and -the MPS. _`.goal.cpp`: impl.h.mps is not specifically designed to be +the MPS. + +_`.goal.cpp`: impl.h.mps is not specifically designed to be an interface to C++, but should be usable from C++. @@ -38,36 +40,32 @@ Requirements _`.req`: The interface must provide an interface from client code written in C to the functionality of the MPS required by the product -(see req.product), Dylan (req.dylan), and the Core RIP (req.epcore). +(see req.product), and Open Dylan (req.dylan). -``mps.h`` may not include internal MPS header files (such as -``pool.h``). +_`.req.separation`: The external interface may not include internal +MPS header files (such as ``pool.h``). -It is essential that the interface cope well with change, in order to -avoid restricting possible future MPS developments. This means that -the interface must be "open ended" in its definitions. This accounts -for some of the apparently tortuous methods of doing things -(``mps_fmt_A_t``, for example). The requirement is that the MPS should +_`.req.flexibility`: It is essential that the interface cope well with +change, in order to avoid restricting possible future MPS +developments. This means that the interface must be "open ended" in +its definitions. This accounts for some of the apparently tortuous +methods of doing things (such as the keyword argument mechanism; see +design.mps.keyword-arguments_). The requirement is that the MPS should be able to add new functionality, or alter the implementation of existing functionality, without affecting existing client code. A stronger requirement is that the MPS should be able to change without *recompiling* client code. This is not always possible. -.. note:: +.. _design.mps.keyword-arguments: keyword-arguments - `.naming.global` was presumably done in response to unwritten - requirements regarding the use of the name spaces in C, perhaps - these: +_`.req.name.iso`: The interface shall not conflict in terms of +naming with any interfaces specified by ISO C and all reasonable +future versions. - - _`.req.name.iso`: The interface shall not conflict in terms of - naming with any interfaces specified by ISO C and all reasonable - future versions. - - - _`.req.name.general`: The interface shall use a documented and - reasonably small portion of the namespace so that clients can - interoperate easily. - - David Jones, 1998-10-01. +_`.req.name.general`: The interface shall use a documented and +reasonably small portion of the namespace so that clients can use the +MPS C interface in combination with other interfaces without name +conflicts. Architecture @@ -82,13 +80,18 @@ layer" which does the job of converting types and checking parameters before calling through to the MPS proper, using internal MPS methods. -General conventions -------------------- +Naming conventions +------------------ _`.naming`: The external interface names should adhere to the -documented interface conventions; these are found in -doc.mps.ref-man.if-conv(0).naming. They are paraphrased/recreated -here. +documented interface conventions; these are found in the “`Interface +conventions`_” chapter of the Reference Manual. They are +paraphrased/recreated here. + +.. _Interface conventions: ../topic/interface.html + +_`.naming.file`: All files in the external interface have names +starting with ``mps``. _`.naming.unixy`: The external interface does not follow the same naming conventions as the internal code. The interface is designed to @@ -97,13 +100,13 @@ resemble a more conventional C, Unix, or Posix naming convention. _`.naming.case`: Identifiers are in lower case, except non-function-like macros, which are in upper case. -_`.naming.global`: All publicised identifiers are -prefixed ``mps_`` or ``MPS_``. +_`.naming.global`: All documented identifiers begin ``mps_`` or +``MPS_``. -_`.naming.all`: All identifiers defined by the MPS -should begin ``mps_`` or ``MPS_`` or ``_mps_``. +_`.naming.all`: All identifiers defined by the MPS begin ``mps_`` or +``MPS_`` or ``_mps_``. -_`.naming.type`: Types are suffixed ``_t``. +_`.naming.type`: Types are suffixed ``_t``, except for structure and union types. _`.naming.struct`: Structure types and tags are suffixed ``_s``. @@ -117,15 +120,14 @@ structure and union members, macros, macro parameters, labels. _`.naming.scope.labels`: labels (for ``goto`` statements) should be rare, only in special block macros and probably not even then. -.. note:: - - This principle is not adhered to in the source code, which uses - ``goto`` for handling error cases. Gareth Rees, 2013-05-27. - _`.naming.scope.other`: The naming convention would also extend to enumeration types and parameters in functions prototypes but both of those are prohibited from having names in an interface file. + +Type conventions +---------------- + _`.type.gen`: The interface defines memory addresses as ``void *`` and sizes as ``size_t`` for compatibility with standard C (in particular, with ``malloc()``). These types must be binary compatible with the @@ -139,13 +141,13 @@ which are never defined. These types are cast to the corresponding internal types in ``mpsi.c``. _`.type.trans`: Some transparent structures are defined. The client is -expected to read these, or poke about in them, under restrictions -which should be documented. The most important is probably the -allocation point (``mps_ap_s``) which is part of allocation buffers. -The transparent structures must be binary compatible with -corresponding internal structures. For example, the fields of -``mps_ap_s`` must correspond with ``APStruct`` internally. This is -checked by ``mpsi.c`` in ``mps_check()``. +expected to read these, or poke about in them, under documented +restrictions. The most important is the allocation point structure +(``mps_ap_s``) which is part of allocation buffers. The transparent +structures must be binary compatible with corresponding internal +structures. For example, the fields of ``mps_ap_s`` must correspond +with ``APStruct`` internally. This is checked by ``mpsi.c`` in +``mps_check()``. _`.type.pseudo`: Some pseudo-opaque structures are defined. These only exist so that code can be inlined using macros. The client code @@ -153,9 +155,9 @@ shouldn't mess with them. The most important case of this is the scan state (``mps_ss_s``) which is accessed by the in-line scanning macros, ``MPS_SCAN_*`` and ``MPS_FIX*``. -_`.type.enum`: There should be no enumeration types in the interface. -Note that enum specifiers (to declare integer constants) are fine as -long as no type is declared. See guide.impl.c.misc.enum.type. +_`.type.enum`: There are no enumeration types in the interface. Note +that enum specifiers (to declare integer constants) are fine as long +as no type is declared. See guide.impl.c.misc.enum.type. _`.type.fun`: Whenever function types or derived function types (such as pointer to function) are declared a prototype should be used and @@ -184,39 +186,32 @@ See guide.impl.c.misc.prototype.parameters. Checking -------- -_`.check.space`: When the arena needs to be recovered from a parameter -it is check using ``AVERT(Foo, foo)`` before any attempt to call -``FooArena(foo)``. The macro ``AVERT()`` in impl.h.assert performs -simple thread-safe checking of ``foo``, so it can be called outside of -``ArenaEnter()`` and ``ArenaLeave()``. +_`.check.avert`: Before any use of a function paramater ``FOO *foo`` +it is checked using ``AVERT(Foo, foo)``. The macro ``AVERT()`` in +impl.h.check performs simple thread-safe checking of ``foo``, so it +can be called outside of ``ArenaEnter()`` and ``ArenaLeave()``. _`.check.types`: We use definitions of types in both our external interface and our internal code, and we want to make sure that they are compatible. (The external interface changes less often and hides -more information.) At first, we were just checking their sizes, which -wasn't very good, but I've come up with some macros which check the -assignment compatibility of the types too. This is a sufficiently -useful trick that I thought I'd send it round. It may be useful in -other places where types and structures need to be checked for -compatibility at compile time. - -These macros don't generate warnings on the compilers I've tried. +more information.) This checking uses the following macros. ``COMPATLVALUE(lvalue1, lvalue2)`` -This macro checks the assignment compatibility of two lvalues. It uses -``sizeof()`` to ensure that the assignments have no effect. :: +_`.check.types.compat.lvalue`: This macro checks the assignment +compatibility of two lvalues. It uses ``sizeof()`` to ensure that the +assignments have no effect. :: #define COMPATLVALUE(lv1, lv2) \ ((void)sizeof((lv1) = (lv2)), (void)sizeof((lv2) = (lv1)), TRUE) ``COMPATTYPE(type1, type2)`` -This macro checks that two types are assignment-compatible and equal -in size. The hack here is that it generates an lvalue for each type by -casting zero to a pointer to the type. The use of ``sizeof()`` avoids -the undefined behaviour that would otherwise result from dereferencing -a null pointer. :: +_`.check.types.compat.type`: This macro checks that two types are +assignment-compatible and equal in size. The hack here is that it +generates an lvalue for each type by casting zero to a pointer to the +type. The use of ``sizeof()`` avoids the undefined behaviour that +would otherwise result from dereferencing a null pointer. :: #define COMPATTYPE(t1, t2) \ (sizeof(t1) == sizeof(t2) && \ @@ -224,8 +219,8 @@ a null pointer. :: ``COMPATFIELDAPPROX(structure1, field1, structure2, field2)`` -This macro checks that the offset and size of two fields in two -structure types are the same. :: +_`.check.types.compat.field.approx`: This macro checks that the offset +and size of two fields in two structure types are the same. :: #define COMPATFIELDAPPROX(s1, f1, s2, f2) \ (sizeof(((s1 *)0)->f1) == sizeof(((s2 *)0)->f2) && \ @@ -233,8 +228,8 @@ structure types are the same. :: ``COMPATFIELD(structure1, field1, structure2, field2)`` -This macro checks the offset, size, and assignment-compatibility of -two fields in two structure types. :: +_`.check.types.compat.field`: This macro checks the offset, size, and +assignment-compatibility of two fields in two structure types. :: #define COMPATFIELD(s1, f1, s2, f2) \ (COMPATFIELDAPPROX(s1, f1, s2, f2) && \ @@ -247,21 +242,34 @@ Binary compatibility issues As in, "Enumeration types are not allowed" (see mail.richard.1995-09-08.09-28). -There are two main aspects to run-time compatibility: binary interface -and protocol. The binary interface is all the information needed to -correctly use the library, and includes external symbol linkage, +_`.compat`: There are two main aspects to run-time compatibility: +binary interface and protocol. + +_`.compat.binary`: The binary interface is all the information needed +to correctly use the library, and includes external symbol linkage, calling conventions, type representation compatibility, structure -layouts, etc. The protocol is how the library is actually used by the -client code -- whether this is called before that -- and determines -the semantic correctness of the client with respect to the library. +layouts, etc. -The binary interface is determined completely by the header file and -the target. The header file specifies the external names and the -types, and the target platform specifies calling conventions and type -representation. There is therefore a many-to-one mapping between the -header file version and the binary interface. +_`.compat.binary.unneeded`: Binary compatibility is not required by +the open source MPS: we expect (and indeed, recommend) that a client +program is compiled against the MPS sources. Nonetheless we try to +maintain binary compatibility in case the capability is required in +future. -The protocol is determined by the implementation of the library. +_`.compat.binary.dependencies`: The binary interface is determined +completely by the header file and the target. The header file +specifies the external names and the types, and the target platform +specifies calling conventions and type representation. There is +therefore a many-to-one mapping between the header file version and +the binary interface. + +_`.compat.protocol`: The protocol is how the library is actually used +by the client code -- whether this is called before that -- and +determines the semantic correctness of the client with respect to the +library. + +_`.compat.protocol.dependencies`: The protocol is determined by the +implementation of the library. Constraints @@ -291,34 +299,59 @@ interface constrains ``Word`` to being the same size as C's generic pointer type, ``void *``. +Implementation +-------------- + +_`.impl`: The external interface consists of the following header +files: + +_`.impl.mps`: ``mps.h`` is the main external interface, containing of +type and function declarations needed by all clients of the MPS. + +_`.impl.mpstd`: ``mpstd.h`` is the MPS target detection header. It +decodes preprocessor symbols which are predefined by build +environments in order to determine the target platform (see +design.mps.config_), and then defines uniform symbols, such as +``MPS_ARCH_I3``, for use externally and internally by the MPS. +``mpstd.h`` is not included by any of the other external headers, as +it relies on exact set of preprocessor constants defined by compilers. + +.. _design.mps.config: config + +_`.impl.mpsio`: ``mpsio.h`` is the interface to the MPS I/O subsystem, +part of the plinth. See design.mps.io_. + +.. _design.mps.io: io + +_`.impl.mpslib`: ``mpslib.h`` is the interface to the MPS Library +Interface, part of the plinth. See design.mps.lib_. + +.. _design.mps.lib: lib + +_`.impl.mpsa`: Interfaces to arena classes are in files with names +starting ``mpsa``: for example, the interface to the Virtual Memory +arena class is in ``mpsavm.h``. + +_`.impl.mpsc`: Interfaces to pool classes are in files with names +starting ``mpsc``: for example, the interface to the MVFF pool class +is in ``mpscmvff.h``. + + Notes ----- -The file ``mpstd.h`` is the MPS target detection header. It decodes -preprocessor symbols which are predefined by build environments in -order to determine the target platform, and then defines uniform -symbols, such as ``MPS_ARCH_I3``, for use internally by the MPS. +_`.fmt.extend`: ``mps_fmt_A_t`` is so called because new pool classes +might require new format methods, but these methods cannot be added to +the format structure without breaking binary compatibility. Therefore +these new pool classes would use new format structures named +``mps_fmt_B_t`` and so on. -There is a design document for the mps interface, -design.mps.interface, but it was written before we had the idea of -having a C interface layer. It is quite relevant, though, and could be -updated. We should use it during the review. - -All exported identifiers and file names should begin with ``mps_`` or -``MPS_`` so that they don't clash with other systems. - -We should probably have a specialized set of rules and a special -checklist for this interface. - -_`.fmt.extend`: This paragraph should be an explanation of why -``mps_fmt_A_t`` is so called. The underlying reason is future -extensibility. - -_`.thread-safety`: Most calls through this interface lock the space +_`.thread-safety`: Most calls through this interface lock the arena and therefore make the MPM single-threaded. In order to do this they -must recover the space from their parameters. Methods such as -``ThreadSpace()`` must therefore be callable when the space is *not* -locked. These methods are tagged with the tag of this note. +must recover the arena from their parameters. Methods such as +``FormatArena()`` and ``ThreadArena()`` must therefore be callable +when the arena is *not* locked. These methods are tagged with the tag +of this note. _`.lock-free`: Certain functions inside the MPM are thread-safe and do not need to be serialized by using locks. They are marked with the tag diff --git a/mps/design/keyword-arguments.txt b/mps/design/keyword-arguments.txt index 0c698036875..849829ca661 100644 --- a/mps/design/keyword-arguments.txt +++ b/mps/design/keyword-arguments.txt @@ -103,10 +103,10 @@ but ``arg.h`` provides a macro for this:: We define keys as static structures (rather than, say, an enum) because: - The set of keys can be extended indefinitely. -- The set of keys can be extended by indepdently linked modules. +- The set of keys can be extended by independently linked modules. - The structure contents allow strong checking of argument lists. -In the MPS Interface, we declare keys like this:: +In the MPS C Interface, we declare keys like this:: extern const struct mps_key_s _mps_key_extend_by; #define MPS_KEY_EXTEND_BY (&_mps_key_extend_by) diff --git a/mps/design/nailboard.txt b/mps/design/nailboard.txt index 8c8bca594af..d54a58cf03c 100644 --- a/mps/design/nailboard.txt +++ b/mps/design/nailboard.txt @@ -6,7 +6,7 @@ Nailboards for ambiguously referenced segments :Tag: design.mps.nailboard :Author: Gareth Rees :Date: 2014-01-15 -:Status: incomplete design +:Status: complete design :Revision: $Id$ :Copyright: See section `Copyright and License`_. :Index terms: pair: nailboard; design @@ -80,9 +80,14 @@ corresponding word in the level *k*\−1 table is set). _`.impl.scale`: Here ``scale`` is an arbitrary scale factor that must be a power of 2. It could in future be supplied as a parameter when creating a nailboard, but in the current implementation it is always -:c:macro:`MPS_WORD_WIDTH`. +``MPS_WORD_WIDTH``. -_`.impl.table.last`: The last bit table is one word long or shorter. +_`.impl.table.last`: The last bit table is always shorter than one +word. This is slightly wasteful in some cases (for example, a +nailboard with 64 nails and ``scale`` 64 will have two levels, the +second level having just one bit), but allows the code to support +small nailboards without special cases in the code (consider the case +of a nailboard with just one nail). _`.impl.size`: The size of the level *i* bit table is the ceiling of @@ -113,7 +118,8 @@ it is reclaimed. _`.impl.isresrange.strategy`: The strategy for testing to see if any nails are set in a range is to handle the cases that are expected to be common first. In particular, we expect that there will only be few -nails in a nailboard, so most calls to :c:func:`NailboardIsResRange` will return ``TRUE``. +nails in a nailboard, so most calls to ``NailboardIsResRange()`` will +return ``TRUE``. _`.impl.isresrange.alignment`: When testing a range against a level of a nailboard, the base and limit of the range will typically not align @@ -170,6 +176,32 @@ one-sided: that is, we don't need to look at the right splinter of a left splinter or vice versa, because we know that it is empty. +Future +------ + +_`.future.tune`: The implementation makes heavy use of +``BTIsResRange``, but this function is not well tuned for scanning +small arrays (which we expect to be the common case for nailboards). +Performance might be improved by special-casing the small levels. + +_`.future.limit`: In C and C++, a pointer to "one past the last +element of an array object" (the limit of the object in our +terminology) is a valid pointer and can be used in pointer arithmetic. +See §6.5.6.8–9 of [C1999]. So in theory a programmer could have such +as pointer as the only reference keeping an object alive, and still +expect to be able to subtract from it to get back to the object. The +current nailboard implementation does not support this use case. + + +References +---------- + +.. [C1999] + International Standard ISO/IEC 9899:1999; + "Programming languages — C"; + + + Document History ---------------- diff --git a/mps/design/type.txt b/mps/design/type.txt index 6a7efc93529..6ce0da3c035 100644 --- a/mps/design/type.txt +++ b/mps/design/type.txt @@ -6,7 +6,7 @@ General MPS types :Tag: design.mps.type :Author: Richard Brooksby :Date: 1996-10-23 -:Status: incomplete document +:Status: complete document :Revision: $Id$ :Copyright: See `Copyright and License`_. :Index terms: pair: general types; design @@ -32,6 +32,87 @@ say ``Byte`` in your code if it's what you mean. Concrete types -------------- +``typedef unsigned AccessSet`` + +_`.access-set`: An ``AccessSet`` is a bitset of ``Access`` modes, +which are ``AccessREAD`` and ``AccessWRITE``. ``AccessSetEMPTY`` is +the empty ``AccessSet``. + + +``typedef struct AddrStruct *Addr`` + +_`.addr`: ``Addr`` is the type used for "managed addresses", that is, +addresses of objects managed by the MPS. + +_`.addr.def`: ``Addr`` is defined as ``struct AddrStruct *``, but +``AddrStruct`` is never defined. This means that ``Addr`` is always an +incomplete type, which prevents accidental dereferencing, arithmetic, +or assignment to other pointer types. + +_`.addr.use`: ``Addr`` should be used whenever the code needs to deal +with addresses. It should not be used for the addresses of memory +manager data structures themselves, so that the memory manager remains +amenable to working in a separate address space. Be careful not to +confuse ``Addr`` with ``void *``. + +_`.addr.ops`: Limited arithmetic is allowed on addresses using +``AddrAdd()`` and ``AddrOffset()`` (impl.c.mpm). Addresses may also be +compared using the relational operators ``==``, ``!=``, ``<``, ``<=``, +``>``, and ``>=``. + +_`.addr.ops.mem`: We need efficient operators similar to ``memset()``, +``memcpy()``, and ``memcmp()`` on ``Addr``; these are called ``AddrSet()``, +``AddrCopy()``, and ``AddrComp()``. When ``Addr`` is compatible with +``void *``, these are implemented through the functions +``mps_lib_memset()``, ``mps_lib_memcpy()``, and ``mps_lib_memcmp()`` +functions in the plinth (impl.h.mpm). + +_`.addr.conv.c`: ``Addr`` is converted to ``mps_addr_t`` in the MPS C +Interface. ``mps_addr_t`` is defined to be the same as ``void *``, so +using the MPS C Interface confines the memory manager to the same +address space as the client data. + + +``typedef Word Align`` + +_`.align`: ``Align`` is an unsigned integral type which is used to +represent the alignment of managed addresses. All alignments are +positive powers of two. ``Align`` is large enough to hold the maximum +possible alignment. + +_`.align.use`: ``Align`` should be used whenever the code needs to +deal with the alignment of a managed address. + +_`.align.conv.c`: ``Align`` is converted to ``mps_align_t`` in the MPS +C Interface. + + +``typedef unsigned Attr`` + +_`.attr`: Pool attributes. A bitset of pool or pool class +attributes, which are: + +=================== =================================================== +Attribute Description +=================== =================================================== +``AttrALLOC`` Supports the ``PoolAlloc`` interface. +``AttrBUF`` Supports the buffer interface. +``AttrFMT`` Contains formatted objects. + Used to decide which pools to walk. +``AttrFREE`` Supports the ``PoolFree`` interface. +``AttrGC`` Is garbage collecting, that is, parts may be + reclaimed. Used to decide which segments are + condemned. +``AttrMOVINGGC`` Is moving, that is, objects may move in memory. + Used to update the set of zones that might have + moved and so implement location dependency. +``AttrSCAN`` Contains references and must be scanned. +=================== =================================================== + +There is an attribute field in the pool class (``PoolClassStruct``) +which declares the attributes of that class. + + ``typedef int Bool`` _`.bool`: The ``Bool`` type is mostly defined so that the intention of @@ -71,63 +152,135 @@ for ``BoolCheck`` on the PC Aaron. "With" ran in 97.7% of the time (averaged over 3 runs). -``typedef int Res`` +``typedef unsigned BufferMode`` -_`.res`: ``Res`` is the type of result codes. A result code indicates -the success or failure of an operation, along with the reason for -failure. Like Unix error codes, the meaning of the code depends on the -call that returned it. These codes are just broad categories with -mnemonic names for various sorts of problems. +_`.buffermode`: ``BufferMode`` is a bitset of buffer attributes. See +design.mps.buffer_. It is a sum of the following: -=================== ======================================================= -Result code Description -=================== ======================================================= -``ResOK`` The operation succeeded. Return parameters may only be - updated if OK is returned, otherwise they must be left - untouched. -------------------- ------------------------------------------------------- -``ResFAIL`` Something went wrong which doesn't fall into any of the - other categories. The exact meaning depends on the - call. See documentation. -------------------- ------------------------------------------------------- -``ResRESOURCE`` A needed resource could not be obtained. Which resource - depends on the call. See also ``ResMEMORY``, which is a - special case of this. -------------------- ------------------------------------------------------- -``ResMEMORY`` Needed memory (committed memory, not address space) - could not be obtained. -------------------- ------------------------------------------------------- -``ResLIMIT`` An internal limitation was reached. For example, the - maximum number of somethings was reached. We should - avoid returning this by not including static - limitations in our code, as far as possible. (See - rule.impl.constrain and - rule.impl.limits.) -------------------- ------------------------------------------------------- -``ResUNIMPL`` The operation, or some vital part of it, is - unimplemented. This might be returned by functions - which are no longer supported, or by operations which - are included for future expansion, but not yet - supported. -------------------- ------------------------------------------------------- -``ResIO`` An I/O error occurred. Exactly what depends on the - function. -------------------- ------------------------------------------------------- -``ResCOMMIT_LIMIT`` The arena's commit limit would have been exceeded - as a result of allocation. -------------------- ------------------------------------------------------- -``ResPARAM`` An invalid parameter was passed. Normally reserved for - parameters passed from the client. -=================== ======================================================= +.. _design.mps.buffer: buffer -_`.res.use`: ``Res`` should be returned from any function which might -fail. Any other results of the function should be passed back in -"return" parameters (pointers to locations to fill in with the -results). +======================== ============================================== +Mode Description +======================== ============================================== +``BufferModeATTACHED`` Buffer is attached to a region of memory. +``BufferModeFLIPPED`` Buffer has been flipped. +``BufferModeLOGGED`` Buffer emits the events ``BufferReserve`` and + ``BufferCommit``. +``BufferModeTRANSITION`` Buffer is in the process of being detached. +======================== ============================================== -.. note:: This is documented elsewhere, I think -- richard -_`.res.use.spec`: The most specific code should be returned. +``typedef unsigned char Byte`` + +_`.byte`: ``Byte`` is an unsigned integral type corresponding to the +unit in which most sizes are measured, and also the units of +``sizeof``. + +_`.byte.use`: ``Byte`` should be used in preference to ``char`` or +``unsigned char`` wherever it is necessary to deal with bytes +directly. + +_`.byte.source`: ``Byte`` is a just pedagogic version of ``unsigned +char``, since ``char`` is the unit of ``sizeof``. + + +``typedef Word Clock`` + +_`.clock`: ``Clock`` is an unsigned integral type representing clock +time since some epoch. + +_`.clock.use`: A ``Clock`` value is returned by the plinth function +``mps_clock``. It is used to make collection scheduling decisions and +to calibrate the time stamps on events in the telemetry stream. + +_`.clock.units`: The plinth function ``mps_clocks_per_sec`` defines +the units of a ``Clock`` value. + +_`.clock.conv.c`: ``Clock`` is converted to ``mps_clock_t`` in the MPS +C Interface. + + +``typedef unsigned Compare`` + +_`.compare`: ``Compare`` is the type of tri-state comparison +values. + +================== ==================================================== +Value Description +================== ==================================================== +``CompareLESS`` A value compares less than another value. +``CompareEQUAL`` Two values compare the same. +``CompareGREATER`` A value compares greater than another value. +================== ==================================================== + + +``typedef Word Count`` + +_`.count`: ``Count`` is an unsigned integral type which is large +enough to hold the size of any collection of objects in the MPS. + +_`.count.use`: ``Count`` should be used for a number of objects +(control or managed) where the maximum number of objects cannot be +statically determined. If the maximum number can be statically +determined then the smallest unsigned integer with a large enough +range may be used instead (although ``Count`` may be preferable for +clarity). + +_`.count.use.other`: ``Count`` may also be used to count things that +aren't represented by objects (for example, levels), but only where it +can be determined that the maximum count is less than the number of +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. + +``Epoch`` is converted to ``mps_word_t`` in the MPS C Interface, as a +field of ``mps_ld_s``. + + +``typedef unsigned FindDelete`` + +_`.finddelete`: ``FindDelete`` represents an instruction to one of the +*find* methods of a ``Land`` as to what it should do if it finds a +suitable block. See design.mps.land_. It takes one of the following +values: + +.. _design.mps.land: land + +==================== ================================================== +Value Description +==================== ================================================== +``FindDeleteNONE`` Don't delete after finding. +``FindDeleteLOW`` Delete from low end of block. +``FindDeleteHIGH`` Delete from high end of block. +``FindDeleteENTIRE`` Delete entire block. +==================== ================================================== + + +``typedef unsigned FrameState`` + +_`.framestate`: ``FrameState`` represents the current state in a +buffer frame's lifecycle. See design.mps.alloc-frame_. It takes one of +the following values: + +.. _design.mps.alloc-frame: alloc-frame + +========================== ============================================ +State Description +========================== ============================================ +``BufferFrameVALID`` Indicates that ``PushFrame()`` can be a + lightweight operation and need not be + synchronized. +``BufferFramePOP_PENDING`` Indicates that there has been a + ``PopFrame()`` operation that the pool + must respond to. +``BufferFrameDISABLED`` Indicates that the pool has disabled + support for lightweight operations for + this buffer. +========================== ============================================ ``typedef void (*Fun)(void)`` @@ -142,6 +295,328 @@ through to a third function ``h``, where ``h`` knows the real type of ``f`` but ``g`` doesn't. +``typedef Word Index`` + +_`.index`: ``Index`` is an unsigned integral type which is large +enough to hold any array index. + +_`.index.use`: ``Index`` should be used where the maximum size of the +array cannot be statically determined. If the maximum size can be +determined then the smallest unsigned integer with a large enough +range may be used instead. + + +``typedef unsigned MessageType`` + +_`.messagetype`: ``MessageType`` is the type of a message. See +design.mps.message_. It takes one of the following values: + +.. _design.mps.message: message + +=========================== =========================================== +Message type Description +=========================== =========================================== +``MessageTypeFINALIZATION`` A block is finalizable. +``MessageTypeGC`` A garbage collection finished. +``MessageTypeGCSTART`` A garbage collection started. +=========================== =========================================== + + +``typedef unsigned Rank`` + +_`.rank`: ``Rank`` is an enumeration which represents the rank of a +reference. The ranks are: + +============= ===== ================================================== +Rank Index Description +============= ===== ================================================== +``RankAMBIG`` 0 The reference is ambiguous. That is, it must be + assumed to be a reference, but not updated in + case it isn't. +``RankEXACT`` 1 The reference is exact, and refers to an object. +``RankFINAL`` 2 The reference is exact and final, so special + action is required if only final or weak + references remain to the object. +``RankWEAK`` 3 The reference is exact and weak, so should + be deleted if only weak references remain to the + object. +============= ===== ================================================== + +``Rank`` is stored with segments and roots, and passed around. + +``Rank`` is converted to ``mps_rank_t`` in the MPS C Interface. + +The ordering of the ranks is important. It is the order in which the +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:: + + This documentation should be expanded and moved to its own + document, then referenced from the implementation more thoroughly. + + +``typedef unsigned RankSet`` + +_`.rankset`: ``RankSet`` is a set of ranks, represented as a bitset. + + +``typedef Addr Ref`` + +_`.ref`: ``Ref`` is a reference to a managed object (as opposed to any +old managed address). ``Ref`` should be used where a reference is +intended. + +.. note:: This isn't too clear -- richard + + +``typedef Word RefSet`` + +_`.refset`: ``RefSet`` is a conservative approximation to a set of +references. See design.mps.refset_. + +.. _design.mps.refset: refset + + +``typedef int Res`` + +_`.res`: ``Res`` is the type of result codes. A result code indicates +the success or failure of an operation, along with the reason for +failure. Like Unix error codes, the meaning of the code depends on the +call that returned it. These codes are just broad categories with +mnemonic names for various sorts of problems. + +=================== =================================================== +Result code Description +=================== =================================================== +``ResOK`` The operation succeeded. Return parameters may only + be updated if OK is returned, otherwise they must + be left untouched. +``ResCOMMIT_LIMIT`` The arena's commit limit would have been exceeded + as a result of allocation. +``ResFAIL`` Something went wrong which doesn't fall into any of + the other categories. The exact meaning depends + on the call. See documentation. +``ResIO`` An I/O error occurred. Exactly what depends on the + function. +``ResLIMIT`` An internal limitation was reached. For example, + the maximum number of somethings was reached. We + should avoid returning this by not including + static limitations in our code, as far as + possible. (See rule.impl.constrain and + rule.impl.limits.) +``ResMEMORY`` Needed memory (committed memory, not address space) + could not be obtained. +``ResPARAM`` An invalid parameter was passed. Normally reserved + for parameters passed from the client. +``ResRESOURCE`` A needed resource could not be obtained. Which + resource depends on the call. See also + ``ResMEMORY``, which is a special case of this. +``ResUNIMPL`` The operation, or some vital part of it, is + unimplemented. This might be returned by + functions which are no longer supported, or by + operations which are included for future + expansion, but not yet supported. +=================== =================================================== + +_`.res.use`: ``Res`` should be returned from any function which might +fail. Any other results of the function should be passed back in +"return" parameters (pointers to locations to fill in with the +results). + +.. note:: This is documented elsewhere, I think -- richard + +_`.res.use.spec`: The most specific code should be returned. + + +``typedef unsigned RootMode`` + +_`.rootmode`: ``RootMode`` is an unsigned integral type which is used +to represent an attribute of a root: + +============================= ========================================= +Root mode Description +============================= ========================================= +``RootModeCONSTANT`` Client program will not change the root + after it is registered. +``RootModePROTECTABLE`` Root is protectable: the MPS may place + a barrier on any page containing any + part of the root. +``RootModePROTECTABLE_INNER`` Root is protectable: the MPS may place + a barrier on any page completely covered + by part of the root. +============================= ========================================= + +_`.rootmode.const.unused`: ``RootModeCONSTANT`` has no effect. This +mode was introduced in the hope of being able to maintain a +:term:`remembered set` for the root without needing a :term:`write +barrier`, but it can't work as described, since you can't reliably +create a valid registered constant root that contains any references. +(If you add the references before registering the root, they may have +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. + + +``typedef int RootVar`` + +_`.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 +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. +================== ==================================================== + + +``typedef unsigned Serial`` + +_`.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] + +Why? Consistency checking, debugging, and logging. Not well thought +out. + + +``typedef unsigned Shift`` + +_`.shift`: ``Shift`` is an unsigned integral type which can hold the +amount by which a ``Word`` can be shifted. It is therefore large +enough to hold the word width (in bits). + +_`.shift.use`: ``Shift`` should be used whenever a shift value (the +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. + + +``typedef unsigned long Sig`` + +_`.sig`: ``Sig`` is the type of signatures, which are written into +structures when they are created, and invalidated when they are +destroyed. They provide a limited form of run-time type checking and +dynamic scope checking. See design.mps.sig_. + +.. _design.mps.sig: sig + + +``typedef Word Size`` + +_`.size`: ``Size`` is an unsigned integral type large enough to +hold the size of any object which the MPS might manage. + +_`.size.byte`: ``Size`` should hold a size calculated in bytes. + +.. warning:: + + This is violated by ``GenParams.capacity`` (which is measured in + kilobytes). + +_`.size.use`: ``Size`` should be used whenever the code needs to deal +with the size of managed memory or client objects. It should not be +used for the sizes of the memory manager's own data structures, so +that the memory manager is amenable to working in a separate address +space. Be careful not to confuse it with ``size_t``. + +_`.size.ops`: ``SizeIsAligned()``, ``SizeAlignUp()``, +``SizeAlignDown()`` and ``SizeRoundUp()``. + +_`.size.conv.c`: ``Size`` is converted to ``size_t`` in the MPS C +Interface. This constrains the memory manager to the same address +space as the client data. + + +``typedef unsigned TraceId`` + +_`.traceid`: A ``TraceId`` is an unsigned integer which is less than +``TRACE_MAX``. Each running trace has a different ``TraceId`` which is +used to index into tables and bitfields used to remember the state of +that trace. + + +``typedef unsigned TraceSet`` + +_`.traceset`: A ``TraceSet`` is a bitset of ``TraceId``, +represented in the obvious way:: + + member(ti, ts) ⇔ ((1<``, and ``>=``. - -_`.addr.ops.mem`: We need efficient operators similar to ``memset()``, -``memcpy()``, and ``memcmp()`` on ``Addr``; these are called ``AddrSet()``, -``AddrCopy()``, and ``AddrComp()``. When ``Addr`` is compatible with -``void *``, these are implemented through the functions -``mps_lib_memset()``, ``mps_lib_memcpy()``, and ``mps_lib_memcmp()`` -functions in the plinth (impl.h.mpm). - -.. note:: - - No other implementation exists at present. pekka 1998-09-07 - -_`.addr.conv.c`: ``Addr`` is converted to ``mps_addr_t`` in the MPS C -Interface. ``mps_addr_t`` is defined to be the same as ``void *``, so -using the MPS C Interface confines the memory manager to the same -address space as the client data. - - -``typedef Word Size`` - -_`.size`: ``Size`` is an unsigned integral type large enough to -hold the size of any object which the MPS might manage. - -_`.size.byte`: ``Size`` should hold a size calculated in bytes. - -.. warning:: This may not be true for all existing code. - -_`.size.use`: ``Size`` should be used whenever the code needs to deal -with the size of managed memory or client objects. It should not be -used for the sizes of the memory manager's own data structures, so -that the memory manager is amenable to working in a separate address -space. Be careful not to confuse it with ``size_t``. - -_`.size.ops`: ``SizeIsAligned()``, ``SizeAlignUp()``, -``SizeAlignDown()`` and ``SizeRoundUp()``. - -_`.size.conv.c`: ``Size`` is converted to ``size_t`` in the MPS C -Interface. This constrains the memory manager to the same address -space as the client data. - - -``typedef Word Align`` - -_`.align`: ``Align`` is an unsigned integral type which is used to -represent the alignment of managed addresses. All alignments are -positive powers of two. ``Align`` is large enough to hold the maximum -possible alignment. - -_`.align.use`: ``Align`` should be used whenever the code needs to -deal with the alignment of a managed address. - -_`.align.conv.c`: ``Align`` is converted to ``mps_align_t`` in the MPS -C Interface. - - -``typedef unsigned Shift`` - -_`.shift`: ``Shift`` is an unsigned integral type which can hold the -amount by which a ``Word`` can be shifted. It is therefore large -enough to hold the word width (in bits). - -_`.shift.use`: ``Shift`` should be used whenever a shift value (the -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. - -_`.shift.conv.c`: ``Shift`` is converted to ``mps_shift_t`` in the MPS -C Interface. - - -``typedef Addr Ref`` - -_`.ref`: ``Ref`` is a reference to a managed object (as opposed to any -old managed address). ``Ref`` should be used where a reference is -intended. - -.. note:: This isn't too clear -- richard - - -``typedef Word RefSet`` - -_`.refset`: ``RefSet`` is a conservative approximation to a set of -references. See design.mps.refset. - - -``typedef unsigned Rank`` - -_`.rank`: ``Rank`` is an enumeration which represents the rank of a -reference. The ranks are: - -============= ===== ===================================================== -Rank Index Description -============= ===== ===================================================== -``RankAMBIG`` 0 The reference is ambiguous. That is, it must be - assumed to be a reference, but not updated in case it - isn't. -------------- ----- ----------------------------------------------------- -``RankEXACT`` 1 The reference is exact, and refers to an object. -------------- ----- ----------------------------------------------------- -``RankFINAL`` 2 The reference is exact and final, so special action - is required if only final or weak references remain - to the object. -------------- ----- ----------------------------------------------------- -``RankWEAK`` 3 The reference is exact and weak, so should be deleted - if only weak references remain to the object. -============= ===== ===================================================== - -``Rank`` is stored with segments and roots, and passed around. - -``Rank`` is converted to ``mps_rank_t`` in the MPS C Interface. - -The ordering of the ranks is important. It is the order in which the -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:: - - This documentation should be expanded and moved to its own - document, then referenced from the implementation more thoroughly. - - -``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. - -``Epoch`` is converted to ``mps_word_t`` in the MPS C Interface, as a -field of ``mps_ld_s``. - - -``typedef unsigned TraceId`` - -_`.traceid`: A ``TraceId`` is an unsigned integer which is less than -``TRACE_MAX``. Each running trace has a different ``TraceId`` which is -used to index into tables and bitfields used to remember the state of -that trace. - - -``typedef unsigned TraceSet`` - -_`.traceset`: A ``TraceSet`` is a bitset of ``TraceId``, -represented in the obvious way:: - - member(ti, ts) ⇔ ((1<operator.name); - return obj_error; } @@ -4007,7 +4005,6 @@ static mps_res_t obj_scan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit) assert(0); fprintf(stderr, "Unexpected object on the heap\n"); abort(); - return MPS_RES_FAIL; } } } MPS_SCAN_END(ss); @@ -4078,7 +4075,6 @@ static mps_addr_t obj_skip(mps_addr_t base) assert(0); fprintf(stderr, "Unexpected object on the heap\n"); abort(); - return NULL; } return base; } diff --git a/mps/example/scheme/scheme-boehm.c b/mps/example/scheme/scheme-boehm.c index 839f1a56fd3..8d039433bb4 100644 --- a/mps/example/scheme/scheme-boehm.c +++ b/mps/example/scheme/scheme-boehm.c @@ -1,6 +1,6 @@ /* scheme.c -- SCHEME INTERPRETER EXAMPLE FOR THE MEMORY POOL SYSTEM * - * Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * TO DO * - unbounded integers, other number types. @@ -1728,8 +1728,6 @@ static obj_t entry_do(obj_t env, obj_t op_env, obj_t operator, obj_t operands) return result; } } - error("%s: unimplemented", operator->operator.name); - return obj_error; } @@ -3638,7 +3636,7 @@ int main(int argc, char *argv[]) /* 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/example/scheme/scheme-malloc.c b/mps/example/scheme/scheme-malloc.c index 799e7db66cf..1333ce73aef 100644 --- a/mps/example/scheme/scheme-malloc.c +++ b/mps/example/scheme/scheme-malloc.c @@ -1,6 +1,6 @@ /* scheme.c -- SCHEME INTERPRETER EXAMPLE FOR THE MEMORY POOL SYSTEM * - * Copyright (c) 2001-2013 Ravenbrook Limited. See end of file for license. + * Copyright (c) 2001-2014 Ravenbrook Limited. See end of file for license. * * TO DO * - unbounded integers, other number types. @@ -1728,8 +1728,6 @@ static obj_t entry_do(obj_t env, obj_t op_env, obj_t operator, obj_t operands) return result; } } - error("%s: unimplemented", operator->operator.name); - return obj_error; } @@ -3635,7 +3633,7 @@ int main(int argc, char *argv[]) /* 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/example/scheme/scheme.c b/mps/example/scheme/scheme.c index 4b2b36797c5..8a8dcf48ed7 100644 --- a/mps/example/scheme/scheme.c +++ b/mps/example/scheme/scheme.c @@ -2037,8 +2037,6 @@ static obj_t entry_do(obj_t env, obj_t op_env, obj_t operator, obj_t operands) return result; } } - error("%s: unimplemented", operator->operator.name); - return obj_error; } @@ -3994,7 +3992,6 @@ static mps_res_t obj_scan(mps_ss_t ss, mps_addr_t base, mps_addr_t limit) assert(0); fprintf(stderr, "Unexpected object on the heap\n"); abort(); - return MPS_RES_FAIL; } } } MPS_SCAN_END(ss); @@ -4071,7 +4068,6 @@ static mps_addr_t obj_skip(mps_addr_t base) assert(0); fprintf(stderr, "Unexpected object on the heap\n"); abort(); - return NULL; } return base; } diff --git a/mps/manual/.p4ignore b/mps/manual/.p4ignore index 3902ee8b103..ef6464692c9 100644 --- a/mps/manual/.p4ignore +++ b/mps/manual/.p4ignore @@ -1,2 +1,3 @@ doctrees converted +html diff --git a/mps/manual/build.txt b/mps/manual/build.txt index c10763ec761..5403d7ffc44 100644 --- a/mps/manual/build.txt +++ b/mps/manual/build.txt @@ -151,9 +151,9 @@ Platform OS Architecture Compiler Makefile Historically, the MPS worked on a much wider variety of platforms, and still could: IRIX, OSF/1 (Tru64), Solaris, SunOS, Classic Mac OS; MIPS, PowerPC, ALPHA, SPARC v8, SPARC v9; Metrowerks Codewarrior, -SunPro C, Digital C, EGCS. If you are interested in support on any of -these platforms or any new platforms, please contact Ravenbrook at -`mps-questions@ravenbrook.com `_. +SunPro C, Digital C, EGCS, Pelles C. If you are interested in support +on any of these platforms or any new platforms, please contact +Ravenbrook at `mps-questions@ravenbrook.com `_. Running make @@ -190,9 +190,10 @@ You will need to switch your build environment between 32-bit and 64-bit using Microsoft's ``setenv`` command, for example, ``setenv /x86`` or ``setenv /x64``. -To build just one target, run the command:: +To build just one target, run one of these commands:: - nmake /f w3i3mv.nmk + nmake /f w3i3mv.nmk (32-bit) + nmake /f w3i6mv.nmk (64-bit) On Mac OS X, you can build from the command line with:: @@ -264,6 +265,7 @@ this program, you need to install the SQLite3 development resources. it contains files named ``sqlite3.c`` and ``sqlite3.h``. Copy these two files into the ``code`` directory in the MPS Kit. Then in the "Visual Studio Command Prompt", visit the ``code`` directory and run - the command:: + one of these commands:: - nmake /f w3i3mv.nmk mpseventsql.exe + nmake /f w3i3mv.nmk mpseventsql.exe (32-bit) + nmake /f w3i6mv.nmk mpseventsql.exe (64-bit) diff --git a/mps/manual/source/design/index.rst b/mps/manual/source/design/index.rst index f7207cc9950..49d5b1cd85f 100644 --- a/mps/manual/source/design/index.rst +++ b/mps/manual/source/design/index.rst @@ -13,8 +13,10 @@ Design freelist guide.hex.trans guide.impl.c.format + interface-c keyword-arguments nailboard range ring sig + type diff --git a/mps/manual/source/design/old.rst b/mps/manual/source/design/old.rst index 38d22aa270d..b002b14ef35 100644 --- a/mps/manual/source/design/old.rst +++ b/mps/manual/source/design/old.rst @@ -25,7 +25,6 @@ Old design diag finalize fix - interface-c io lib lock @@ -62,7 +61,6 @@ Old design thread-manager thread-safety trace - type version-library version vm diff --git a/mps/manual/source/guide/lang.rst b/mps/manual/source/guide/lang.rst index 3b71f61ff20..916782424d5 100644 --- a/mps/manual/source/guide/lang.rst +++ b/mps/manual/source/guide/lang.rst @@ -905,6 +905,10 @@ changes size:: 3. The order of operations at the end is important: the old root must be de-registered before its memory is freed. + 4. When calling :c:func:`mps_root_create_table`, take care to + avoid undefined behaviour due to :term:`type punning`. See the + :ref:`warning `. + .. topics:: :ref:`topic-root`. diff --git a/mps/manual/source/pool/amc.rst b/mps/manual/source/pool/amc.rst index 37d03f263eb..4f326b9f78f 100644 --- a/mps/manual/source/pool/amc.rst +++ b/mps/manual/source/pool/amc.rst @@ -113,12 +113,18 @@ AMC interface method`, a :term:`forward method`, an :term:`is-forwarded method` and a :term:`padding method`. - It accepts one optional keyword argument: + It accepts two optional keyword arguments: * :c:macro:`MPS_KEY_CHAIN` (type :c:type:`mps_chain_t`) specifies the :term:`generation chain` for the pool. If not specified, the pool will use the arena's default chain. + * :c:macro:`MPS_KEY_INTERIOR` (type :c:type:`mps_bool_t`, default + ``TRUE``) specifies whether :term:`ambiguous ` :term:`interior pointers` to blocks in the pool keep + objects alive. If this is ``FALSE``, then only :term:`client + pointers` keep objects alive. + For example:: MPS_ARGS_BEGIN(args) { diff --git a/mps/manual/source/pool/amcz.rst b/mps/manual/source/pool/amcz.rst index 70d38ffa6ab..61555fd180a 100644 --- a/mps/manual/source/pool/amcz.rst +++ b/mps/manual/source/pool/amcz.rst @@ -68,12 +68,18 @@ AMCZ interface method`, an :term:`is-forwarded method` and a :term:`padding method`. - It accepts one optional keyword argument: + It accepts two optional keyword arguments: * :c:macro:`MPS_KEY_CHAIN` (type :c:type:`mps_chain_t`) specifies the :term:`generation chain` for the pool. If not specified, the pool will use the arena's default chain. + * :c:macro:`MPS_KEY_INTERIOR` (type :c:type:`mps_bool_t`, default + ``TRUE``) specifies whether :term:`ambiguous ` :term:`interior pointers` to blocks in the pool keep + objects alive. If this is ``FALSE``, then only :term:`client + pointers` keep objects alive. + For example:: MPS_ARGS_BEGIN(args) { diff --git a/mps/manual/source/pool/intro.rst b/mps/manual/source/pool/intro.rst index ea2a03ce562..ed8f83b8d4a 100644 --- a/mps/manual/source/pool/intro.rst +++ b/mps/manual/source/pool/intro.rst @@ -121,8 +121,8 @@ Blocks are automatically managed? [10]_ yes yes yes yes yes Blocks are promoted between generations yes yes no no no --- --- --- --- --- Blocks are manually managed? [10]_ no no no no no yes yes yes yes yes Blocks are scanned? [11]_ yes no yes yes no no no no no yes -Blocks support base pointers only? [12]_ yes yes yes yes yes --- --- --- --- yes -Blocks support internal pointers? [12]_ no no no no no --- --- --- --- no +Blocks support base pointers only? [12]_ no no yes yes yes --- --- --- --- yes +Blocks support internal pointers? [12]_ yes yes no no no --- --- --- --- no Blocks may be protected by barriers? yes no yes yes yes no no no no yes Blocks may move? yes yes no no no no no no no no Blocks may be finalized? yes yes yes yes yes no no no no no @@ -193,6 +193,10 @@ Blocks may use :term:`in-band headers`? yes yes yes yes yes just past the end of the header) is considered to be a reference to the block. + Pools that support internal pointers can be switched to + base pointers only, by setting the optional keyword + argument :c:macro:`MPS_KEY_INTERIOR` to ``FALSE`` when + calling :c:func:`mps_pool_create_k`. .. index:: single: pool class; writing diff --git a/mps/manual/source/release.rst b/mps/manual/source/release.rst index 3e6f650e146..294b6545b91 100644 --- a/mps/manual/source/release.rst +++ b/mps/manual/source/release.rst @@ -3,6 +3,30 @@ Release notes ============= +.. _release-notes-1.114: + +Release 1.114.0 +--------------- + +New features +............ + +#. :term:`Ambiguous ` :term:`interior pointers` + now keep objects in :ref:`pool-amc` and :ref:`pool-amcz` pools + alive. + + This means that if the compiler optimizes away a pointer to the + base of an object, leaving an interior pointer as the only + reference keeping the object alive, this does not cause the object + to be incorrectly collected. Or, if you are writing your own + compiler, you can now perform such an optimization safely. + + If you require the old behaviour (in which ambiguous interior + pointers were ignored) then you can set the + :c:macro:`MPS_KEY_INTERIOR` keyword argument to ``FALSE`` when + calling :c:func:`mps_pool_create_k`. + + .. _release-notes-1.113: Release 1.113.0 @@ -144,3 +168,86 @@ Other changes exception while the MPS is holding the arena lock. See job003640_. .. _job003640: https://www.ravenbrook.com/project/mps/issue/job003640/ + + +.. _release-notes-1.111: + +Release 1.111.0 +--------------- + +New features +............ + +#. Reporting features have been removed from the :ref:`mpseventcnv + ` utility. Instead, the telemetry system + comes with two new utility programs to assist with reporting and + analysis: :ref:`mpseventtxt ` converts an + event stream into human-readable form, and :ref:`mpseventsql + ` loads an event stream into a SQLite + database for further analysis. See :ref:`topic-telemetry`. + +#. The new pool class MFS provide manually managed allocation of + fixed-size objects. See :ref:`pool-mfs`. + +#. The new pool class MVT provide manually managed allocation of + variable-size objects using a *temporal fit* allocation policy + (that is, objects that are allocated togther are expected to be + freed together). See :ref:`pool-mvt`. + + +Interface changes +................. + +#. It is no longer necessary for client programs to use + :c:func:`mps_tramp` to ensure that exceptions due to barrier hits + are caught. This function is now deprecated. + +#. You can set the environment variable + :envvar:`MPS_TELEMETRY_CONTROL` to ``all`` to make the telemetry + system output all events. See :ref:`topic-telemetry`. + +#. New functions :c:func:`mps_telemetry_get`, + :c:func:`mps_telemetry_set` and :c:func:`mps_telemetry_reset` + provide a more convenient interface to telemetry control than + :c:func:`mps_telemetry_control`, which is now deprecated. See + :ref:`topic-telemetry`. + +#. The pool classes :ref:`pool-mv` and :ref:`pool-snc` are now + deprecated. + +#. Allocation frames are now deprecated. See :ref:`topic-frame`. + +#. Additionally, the functions :c:func:`mps_arena_expose`, + :c:func:`mps_arena_unsafe_expose_remember_protection`, + :c:func:`mps_arena_unsafe_restore_protection`, + :c:func:`mps_arena_roots_walk`, and :c:func:`mps_fix` are now + deprecated. + + +Other changes +............. + +#. :c:func:`mps_arena_step` no longer unclamps the arena as a side + effect. If the arena is clamped or parked before calling + :c:func:`mps_arena_step`, it is clamped afterwards. See job003320_. + + .. _job003320: https://www.ravenbrook.com/project/mps/issue/job003320/ + +#. The ambiguous stack scanner, :c:func:`mps_stack_scan_ambig`, no + longer asserts on Linux when there are multiple threads. See + job003412_. + + .. _job003412: https://www.ravenbrook.com/project/mps/issue/job003412/ + +#. It is no longer possible for the "ramp" allocation pattern, + :c:func:`mps_alloc_pattern_ramp()`, to get stuck. Now + :c:func:`mps_ap_alloc_pattern_end` reliably clears this pattern. + See job003454_. + + .. _job003454: https://www.ravenbrook.com/project/mps/issue/job003454/ + +#. The build system now correctly detects the FreeBSD operating system + running on the x86-64 architecture, for FreeBSD version 9.1 or + later. See job003473_. + + .. _job003473: https://www.ravenbrook.com/project/mps/issue/job003473/ diff --git a/mps/manual/source/topic/finalization.rst b/mps/manual/source/topic/finalization.rst index 0f1d1d908ed..32f618f19e7 100644 --- a/mps/manual/source/topic/finalization.rst +++ b/mps/manual/source/topic/finalization.rst @@ -157,7 +157,7 @@ Cautions prompt release of scarce resources. For example, Scheme provides the ``(with-input-from-file)`` procedure which specifies that the created port has :term:`dynamic extent` (and so can be closed as - soon as the procedure exits). + soon as the procedure exits, even if it is still reachable). #. The MPS does not finalize objects in the context of :c:func:`mps_arena_destroy` or :c:func:`mps_pool_destroy`. @@ -185,8 +185,8 @@ Cautions described under :c:func:`mps_pool_destroy`, but the objects do not get finalized. - The only reliable way to ensure that all finalizable object - gets finalized is to maintain a table of :term:`weak + The only reliable way to ensure that all finalizable objects + are finalized is to maintain a table of :term:`weak references (1)` to all such objects. The weak references don't prevent the objects from being finalized, but you can iterate over the list at an appropriate point and finalize any diff --git a/mps/manual/source/topic/interface.rst b/mps/manual/source/topic/interface.rst index eb3d0dcfeca..478c22b8026 100644 --- a/mps/manual/source/topic/interface.rst +++ b/mps/manual/source/topic/interface.rst @@ -205,11 +205,11 @@ Instead, we recommend this approach:: struct foo *fp; res = mps_alloc(&p, pool, sizeof(struct foo)); if(res) /* handle error case */; - fp = (struct foo *)p; + fp = p; -This is portable because conversion from ``void *`` to any other -:term:`object pointer` type is defined by :ref:`ISO/IEC 9899:1990 -` §6.3.2.3.1. +This has defined behaviour because conversion from ``void *`` to any +other :term:`object pointer` type is defined by :ref:`ISO/IEC +9899:1990 ` §6.3.2.3.1. .. index:: diff --git a/mps/manual/source/topic/keyword.rst b/mps/manual/source/topic/keyword.rst index 5f804a63847..665daa91e64 100644 --- a/mps/manual/source/topic/keyword.rst +++ b/mps/manual/source/topic/keyword.rst @@ -104,6 +104,7 @@ now :c:macro:`MPS_KEY_ARGS_END`. :c:macro:`MPS_KEY_FMT_SKIP` :c:type:`mps_fmt_skip_t` ``fmt_skip`` :c:func:`mps_fmt_create_k` :c:macro:`MPS_KEY_FORMAT` :c:type:`mps_fmt_t` ``format`` :c:func:`mps_class_amc`, :c:func:`mps_class_amcz`, :c:func:`mps_class_ams`, :c:func:`mps_class_awl`, :c:func:`mps_class_lo` , :c:func:`mps_class_snc` :c:macro:`MPS_KEY_GEN` :c:type:`unsigned` ``u`` :c:func:`mps_class_ams`, :c:func:`mps_class_awl`, :c:func:`mps_class_lo` + :c:macro:`MPS_KEY_INTERIOR` :c:type:`mps_bool_t` ``b`` :c:func:`mps_class_amc`, :c:func:`mps_class_amcz` :c:macro:`MPS_KEY_MAX_SIZE` :c:type:`size_t` ``size`` :c:func:`mps_class_mv` :c:macro:`MPS_KEY_MEAN_SIZE` :c:type:`size_t` ``size`` :c:func:`mps_class_mv`, :c:func:`mps_class_mvt`, :c:func:`mps_class_mvff` :c:macro:`MPS_KEY_MFS_UNIT_SIZE` :c:type:`size_t` ``size`` :c:func:`mps_class_mfs` diff --git a/mps/manual/source/topic/platform.rst b/mps/manual/source/topic/platform.rst index 0fbc4d59890..c9a1cb12b69 100644 --- a/mps/manual/source/topic/platform.rst +++ b/mps/manual/source/topic/platform.rst @@ -300,6 +300,7 @@ Formerly supported compiler toolchains: ``gp`` GCC with profiling ``MPS_BUILD_GP`` ``lc`` LCC ``MPS_BUILD_LC`` ``mw`` Metrowerks CodeWarrior ``MPS_BUILD_MW`` +``pc`` Pelles C ``MPS_BUILD_PC`` ``sc`` SunPro C ``MPS_BUILD_SC`` ====== ======================================= ================ @@ -348,7 +349,9 @@ Platform Status ``w3almv`` *Not supported* ``w3i3m9`` *Not supported* ``w3i3mv`` Supported +``w3i3pc`` *Not supported* ``w3i6mv`` Supported +``w3i6pc`` *Not supported* ``w3ppmv`` *Not supported* ``xci3gc`` *Not supported* ``xci3ll`` Supported diff --git a/mps/manual/source/topic/root.rst b/mps/manual/source/topic/root.rst index efc87fb8e45..e28c9c87a6d 100644 --- a/mps/manual/source/topic/root.rst +++ b/mps/manual/source/topic/root.rst @@ -271,7 +271,7 @@ allowing the MPS to detect whether they have changed. The :term:`root mode` for :term:`protectable roots`. This tells the MPS that it may place a :term:`barrier (1)` on any - :term:`page` which any part of the :term:`root` covers. No + :term:`page` containing any part of the :term:`root`. No :term:`format method` or :term:`scan method` (except for the one for this root) may write data in this root. They may read it. @@ -514,6 +514,28 @@ Root interface The registered root description persists until it is destroyed by calling :c:func:`mps_root_destroy`. + .. _topic-root-type-pun: + + .. warning:: + + The ``base`` argument has type ``mps_addr_t *`` (a typedef for + ``void **``) but the table of references most likely has some + other pointer type, ``my_object *`` say. It is tempting to + write:: + + mps_root_create_table(..., (mps_addr_t *)my_table, ...) + + but this is :term:`type punning`, and its behaviour is not + defined in ANSI/ISO Standard C. (GCC and Clang have a warning + flag ``-Wstrict-aliasing`` which detects some errors of this + form.) + + To ensure well-defined behaviour, the pointer must be + converted via ``void *`` (or via :c:type:`mps_addr_t`, which + is a typedef for ``void *``), like this:: + + mps_addr_t base = my_table; + mps_root_create_table(..., base, ...) .. c:function:: mps_res_t mps_root_create_table_masked(mps_root_t *root_o, mps_arena_t arena, mps_rank_t rank, mps_rm_t rm, mps_addr_t *base, size_t count, mps_word_t mask) @@ -558,13 +580,17 @@ Root interface mps_res_t res; mps_root_t root; + mps_addr_t base = symtab; res = mps_root_create_table_masked(&root, arena, mps_rank_exact(), (mps_rm_t)0, - symtab, symtab_size * 2, + base, symtab_size * 2, (mps_word_t)TAG_MASK); if (res != MPS_RES_OK) errror("can't create symtab root"); + .. warning:: + + See the warning for :c:func:`mps_root_create_table` above. .. c:function:: void mps_root_destroy(mps_root_t root) diff --git a/mps/manual/source/topic/scanning.rst b/mps/manual/source/topic/scanning.rst index 1dbb15399c8..474ec637dd8 100644 --- a/mps/manual/source/topic/scanning.rst +++ b/mps/manual/source/topic/scanning.rst @@ -56,7 +56,7 @@ region to be scanned. They must carry out the following steps: a pointer to a location containing the reference. #. If :c:func:`MPS_FIX2` returns a :term:`result code` other than - :c:func:`MPS_RES_OK`, return this result code from the scanning + :c:macro:`MPS_RES_OK`, return this result code from the scanning function as soon as practicable. #. If :c:func:`MPS_FIX2` returns :c:macro:`MPS_RES_OK`, it may have diff --git a/mps/test/function/46.c b/mps/test/function/46.c index d79138215ea..c5cd9437859 100644 --- a/mps/test/function/46.c +++ b/mps/test/function/46.c @@ -169,6 +169,6 @@ int main(void) stackpointer=&m; /* hack to get stack pointer */ easy_tramp(test); - report("result", "unknown"); + pass(); return 0; } diff --git a/mps/test/function/6.c b/mps/test/function/6.c index 6c761089d85..7e56e09317a 100644 --- a/mps/test/function/6.c +++ b/mps/test/function/6.c @@ -61,7 +61,7 @@ static void test(void) for (j = 1; j < 100; j++) { comment("%i of 100", j); - p = allocdumb(ap, sizeof(mps_ld_s)); + p = allocdumb(ap, sizeof(mycell)); ld = (mps_ld_t) getdata(p); b = a; diff --git a/mps/test/testsets/passing b/mps/test/testsets/passing index 41421d36166..64c72fe2982 100644 --- a/mps/test/testsets/passing +++ b/mps/test/testsets/passing @@ -7,7 +7,7 @@ function/1.c % function/3.c -- interactive test, can't run unattended % function/4.c -- interactive test, can't run unattended function/5.c -% function/6.c -- job003494 +function/6.c function/7.c % function/8.c -- tries to exhaust memory by mps_arena_create function/9.c @@ -48,12 +48,12 @@ function/42.c function/43.c function/44.c function/45.c -% function/46.c -- report("result", "unknown"); @@@@ +function/46.c function/47.c function/48.c function/49.c function/50.c -% function/51.c -- would pass if we allowed iter = 4 @@@@ +% function/51.c -- job003739 function/52.c function/53.c function/55.c diff --git a/mps/tool/testrun.bat b/mps/tool/testrun.bat index 5496ef5afea..b8f7c89d314 100755 --- a/mps/tool/testrun.bat +++ b/mps/tool/testrun.bat @@ -28,7 +28,7 @@ set LOGDIR=%TMP%\mps-%PFM%-%VARIETY%-log echo MPS test suite echo Logging test output to %LOGDIR% echo Test directory: %PFM%\%VARIETY% -rmdir /q /s %LOGDIR% +if exist %LOGDIR% rmdir /q /s %LOGDIR% mkdir %LOGDIR% @rem Determine which tests to run.