mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-03-24 07:41:54 -07:00
Catch-up merge from master, mainly to pick up gcbench.
Copied from Perforce Change: 184335 ServerID: perforce.ravenbrook.com
This commit is contained in:
commit
ad8e5e5cd4
11 changed files with 584 additions and 27 deletions
|
|
@ -100,7 +100,7 @@ static Res clientChunkCreate(Chunk *chunkReturn, Addr base, Addr limit,
|
|||
|
||||
AVER(chunkReturn != NULL);
|
||||
AVER(base != (Addr)0);
|
||||
/* @@@@ Should refuse on small chunks, instead of AVERring. */
|
||||
/* TODO: Should refuse on small chunks, instead of AVERring. */
|
||||
AVER(limit != (Addr)0);
|
||||
AVER(limit > base);
|
||||
|
||||
|
|
@ -113,7 +113,7 @@ static Res clientChunkCreate(Chunk *chunkReturn, Addr base, Addr limit,
|
|||
goto failBootInit;
|
||||
|
||||
/* Allocate the chunk. */
|
||||
/* See <design/arena/>.@@@@ */
|
||||
/* TODO: Add reference to design. */
|
||||
res = BootAlloc(&p, boot, sizeof(ClientChunkStruct), MPS_PF_ALIGN);
|
||||
if (res != ResOK)
|
||||
goto failChunkAlloc;
|
||||
|
|
@ -154,7 +154,9 @@ static Res ClientChunkInit(Chunk chunk, BootBlock boot)
|
|||
AVERT(BootBlock, boot);
|
||||
UNUSED(boot);
|
||||
|
||||
clChunk->freePages = chunk->pages; /* too large @@@@ */
|
||||
/* TODO: An old comment claimed this is too large.
|
||||
Does it fail to exclude the page table or something? */
|
||||
clChunk->freePages = chunk->pages;
|
||||
|
||||
/* Put the page table as late as possible, as in VM systems we don't want */
|
||||
/* to map it. */
|
||||
|
|
|
|||
|
|
@ -31,8 +31,10 @@
|
|||
SRCID(arenavm, "$Id$");
|
||||
|
||||
|
||||
/* @@@@ Arbitrary calculation for the maximum number of distinct */
|
||||
/* object sets for generations. Should be in config.h. */
|
||||
/* Arbitrary calculation for the maximum number of distinct */
|
||||
/* object sets for generations. */
|
||||
/* TODO: Should be in config.h. */
|
||||
/* TODO: The arena shouldn't be managing generations */
|
||||
/* .gencount.const: Must be a constant suitable for use as an */
|
||||
/* array size. */
|
||||
#define VMArenaGenCount ((Count)(MPS_WORD_WIDTH/2))
|
||||
|
|
@ -401,7 +403,7 @@ static Res VMChunkInit(Chunk chunk, BootBlock boot)
|
|||
goto failAllocPageTable;
|
||||
chunk->pageTable = p;
|
||||
|
||||
/* Actually commit all the tables. <design/arenavm/>.@@@@ */
|
||||
/* Map memory for the bit tables. */
|
||||
if (vmChunk->overheadMappedLimit < overheadLimit) {
|
||||
overheadLimit = AddrAlignUp(overheadLimit, ChunkPageSize(chunk));
|
||||
res = vmArenaMap(VMChunkVMArena(vmChunk), vmChunk->vm,
|
||||
|
|
@ -899,7 +901,7 @@ static Bool pagesFindFreeWithSegPref(Index *baseReturn, VMChunk *chunkReturn,
|
|||
preferred = pref->zones;
|
||||
}
|
||||
|
||||
/* @@@@ Some of these tests might be duplicates. If we're about */
|
||||
/* Some of these tests might be duplicates. If we're about */
|
||||
/* to run out of virtual address space, then slow allocation is */
|
||||
/* probably the least of our worries. */
|
||||
|
||||
|
|
|
|||
|
|
@ -778,7 +778,8 @@ Bool BufferCommit(Buffer buffer, Addr p, Size size)
|
|||
/* .commit.after: If a flip occurs at this point, the pool will */
|
||||
/* see "initAtFlip" above the object, which is valid, so it will */
|
||||
/* be collected. The commit must succeed when trip is called. */
|
||||
/* The pointer "p" will have been fixed up. (@@@@ Will it?) */
|
||||
/* The pointer "p" will have been fixed up. */
|
||||
/* TODO: Check the above assertion and explain why it is so. */
|
||||
/* .commit.trip: Trip the buffer if a flip has occurred. */
|
||||
if (buffer->ap_s.limit == 0)
|
||||
return BufferTrip(buffer, p, size);
|
||||
|
|
@ -887,7 +888,7 @@ void BufferFlip(Buffer buffer)
|
|||
&& !BufferIsReset(buffer)) {
|
||||
AVER(buffer->initAtFlip == (Addr)0);
|
||||
buffer->initAtFlip = buffer->ap_s.init;
|
||||
/* Memory Barrier here? @@@@ */
|
||||
/* TODO: Is a memory barrier required here? */
|
||||
buffer->ap_s.limit = (Addr)0;
|
||||
buffer->mode |= BufferModeFLIPPED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ static mps_word_t dylan_make_WV(mps_word_t version, mps_word_t vb,
|
|||
vf);
|
||||
}
|
||||
|
||||
static mps_res_t dylan_make_wrapper_wrapper(void)
|
||||
mps_res_t dylan_make_wrappers(void)
|
||||
{
|
||||
if(ww == NULL) {
|
||||
ww = malloc(sizeof(mps_word_t) * (BASIC_WRAPPER_SIZE + 1));
|
||||
|
|
@ -74,7 +74,6 @@ static mps_res_t dylan_make_wrapper_wrapper(void)
|
|||
return MPS_RES_OK;
|
||||
}
|
||||
|
||||
|
||||
/* dylan_init -- turn raw memory into initialised dylan-vector (or pad)
|
||||
*
|
||||
* If the raw memory is large enough, initialises it to a dylan-vector,
|
||||
|
|
@ -92,7 +91,7 @@ mps_res_t dylan_init(mps_addr_t addr, size_t size,
|
|||
/* Make sure the size is aligned. */
|
||||
assert((size & (ALIGN-1)) == 0);
|
||||
|
||||
res = dylan_make_wrapper_wrapper();
|
||||
res = dylan_make_wrappers();
|
||||
if (res != MPS_RES_OK)
|
||||
return res;
|
||||
|
||||
|
|
@ -127,7 +126,7 @@ mps_res_t make_dylan_vector(mps_word_t *v, mps_ap_t ap, size_t slots)
|
|||
size_t size;
|
||||
size_t i;
|
||||
|
||||
res = dylan_make_wrapper_wrapper();
|
||||
res = dylan_make_wrappers();
|
||||
if (res != MPS_RES_OK)
|
||||
return res;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ extern mps_addr_t dylan_read(mps_addr_t addr);
|
|||
extern mps_bool_t dylan_check(mps_addr_t addr);
|
||||
extern void dylan_pad(mps_addr_t addr, size_t size);
|
||||
extern int dylan_wrapper_check(mps_word_t *w);
|
||||
extern mps_res_t dylan_make_wrappers(void);
|
||||
|
||||
extern mps_res_t make_dylan_vector(mps_word_t *v, mps_ap_t ap, size_t slots);
|
||||
|
||||
|
|
|
|||
467
mps/code/gcbench.c
Normal file
467
mps/code/gcbench.c
Normal file
|
|
@ -0,0 +1,467 @@
|
|||
/* gcbench.c -- "GC" Benchmark on ANSI C library
|
||||
*
|
||||
* $Id$
|
||||
* Copyright 2014 Ravenbrook Limited. See end of file for license.
|
||||
*
|
||||
* This is an allocation stress benchmark test for gc pools
|
||||
*/
|
||||
|
||||
#include "mps.c"
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <alloca.h>
|
||||
#include <pthread.h>
|
||||
#include "getopt.h"
|
||||
#include "testlib.h"
|
||||
|
||||
#include "fmtdy.h"
|
||||
#include "fmtdytst.h"
|
||||
|
||||
#define RESMUST(expr) \
|
||||
do { \
|
||||
mps_res_t res = (expr); \
|
||||
if (res != MPS_RES_OK) { \
|
||||
fprintf(stderr, #expr " returned %d\n", res); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static mps_arena_t arena;
|
||||
static mps_pool_t pool;
|
||||
static mps_fmt_t format;
|
||||
static mps_chain_t chain;
|
||||
static mps_gen_param_s genDefault[] = {
|
||||
{ 5 * 1024 * 1024, 0.85 },
|
||||
{ 50 * 1024 * 1024, 0.45 } };
|
||||
|
||||
/* objNULL needs to be odd so that it's ignored in exactRoots. */
|
||||
#define objNULL ((obj_t)MPS_WORD_CONST(0xDECEA5ED))
|
||||
#define genLIMIT 100
|
||||
|
||||
static rnd_state_t seed = 0; /* random number seed */
|
||||
static unsigned nthreads = 1; /* threads */
|
||||
static unsigned niter = 5; /* iterations */
|
||||
static unsigned npass = 10; /* passes over tree */
|
||||
static size_t width = 2; /* width of tree nodes */
|
||||
static unsigned depth = 20; /* depth of tree */
|
||||
static double preuse = 0.2; /* probability of reuse */
|
||||
static double pupdate = 0.1; /* probability of update */
|
||||
static unsigned ngen = 0; /* number of generations specified */
|
||||
static mps_gen_param_s gen[genLIMIT]; /* generation parameters */
|
||||
static size_t arenasize = 256ul * 1024 * 1024; /* arena size */
|
||||
|
||||
typedef struct gcthread_s *gcthread_t;
|
||||
|
||||
typedef void *(*gcthread_fn_t)(gcthread_t thread);
|
||||
|
||||
struct gcthread_s {
|
||||
pthread_t pthread;
|
||||
mps_thr_t mps_thread;
|
||||
mps_root_t reg_root;
|
||||
mps_ap_t ap;
|
||||
gcthread_fn_t fn;
|
||||
};
|
||||
|
||||
typedef mps_word_t obj_t;
|
||||
|
||||
static obj_t mkvector(mps_ap_t ap, size_t n) {
|
||||
mps_word_t v;
|
||||
RESMUST(make_dylan_vector(&v, ap, n));
|
||||
return v;
|
||||
}
|
||||
|
||||
static obj_t aref(obj_t v, size_t i) {
|
||||
return DYLAN_VECTOR_SLOT(v, i);
|
||||
}
|
||||
|
||||
static void aset(obj_t v, size_t i, obj_t val) {
|
||||
DYLAN_VECTOR_SLOT(v, i) = val;
|
||||
}
|
||||
|
||||
/* mktree - make a tree of nodes with depth d. */
|
||||
static obj_t mktree(mps_ap_t ap, unsigned d) {
|
||||
obj_t tree;
|
||||
size_t i;
|
||||
if (d <= 0) return objNULL;
|
||||
tree = mkvector(ap, width);
|
||||
for (i = 0; i < width; ++i) {
|
||||
aset(tree, i, mktree(ap, d - 1));
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
static obj_t random_subtree(obj_t tree, unsigned levels) {
|
||||
while(tree != objNULL && levels > 0) {
|
||||
tree = aref(tree, rnd() % width);
|
||||
--levels;
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
/* new_tree - Make a new tree from an old tree.
|
||||
* The new tree is the same depth as the old tree and
|
||||
* reuses old nodes with probability preuse.
|
||||
* NOTE: If a new node is reused multiple times, the total size
|
||||
* will be smaller.
|
||||
* NOTE: Changing preuse will dramatically change how much work
|
||||
* is done. In particular, if preuse==1, the old tree is returned
|
||||
* unchanged. */
|
||||
static obj_t new_tree(mps_ap_t ap, obj_t oldtree, unsigned d) {
|
||||
obj_t subtree;
|
||||
size_t i;
|
||||
if (rnd_double() < preuse) {
|
||||
subtree = random_subtree(oldtree, depth - d);
|
||||
} else {
|
||||
if (d == 0)
|
||||
return objNULL;
|
||||
subtree = mkvector(ap, width);
|
||||
for (i = 0; i < width; ++i) {
|
||||
aset(subtree, i, new_tree(ap, oldtree, d - 1));
|
||||
}
|
||||
}
|
||||
return subtree;
|
||||
}
|
||||
|
||||
/* Update tree to be identical tree but with nodes reallocated
|
||||
* with probability pupdate. This avoids writing to vector slots
|
||||
* if unecessary. */
|
||||
static obj_t update_tree(mps_ap_t ap, obj_t oldtree, unsigned d) {
|
||||
obj_t tree;
|
||||
size_t i;
|
||||
if (oldtree == objNULL || d == 0)
|
||||
return oldtree;
|
||||
if (rnd_double() < pupdate) {
|
||||
tree = mkvector(ap, width);
|
||||
for (i = 0; i < width; ++i) {
|
||||
aset(tree, i, update_tree(ap, aref(oldtree, i), d - 1));
|
||||
}
|
||||
} else {
|
||||
tree = oldtree;
|
||||
for (i = 0; i < width; ++i) {
|
||||
obj_t oldsubtree = aref(oldtree, i);
|
||||
obj_t subtree = update_tree(ap, oldsubtree, d - 1);
|
||||
if (subtree != oldsubtree) {
|
||||
aset(tree, i, subtree);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
static void *gc_tree(gcthread_t thread) {
|
||||
unsigned i, j;
|
||||
mps_ap_t ap = thread->ap;
|
||||
for (i = 0; i < niter; ++i) {
|
||||
obj_t tree = mktree(ap, depth);
|
||||
for (j = 0 ; j < npass; ++j) {
|
||||
if (preuse < 1.0)
|
||||
tree = new_tree(ap, tree, depth);
|
||||
if (pupdate > 0.0)
|
||||
tree = update_tree(ap, tree, depth);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* start -- start routine for each thread */
|
||||
static void *start(void *p) {
|
||||
gcthread_t thread = p;
|
||||
void *marker;
|
||||
RESMUST(mps_thread_reg(&thread->mps_thread, arena));
|
||||
RESMUST(mps_root_create_reg(&thread->reg_root, arena,
|
||||
mps_rank_ambig(), (mps_rm_t)0,
|
||||
thread->mps_thread, &mps_stack_scan_ambig,
|
||||
&marker, (size_t)0));
|
||||
RESMUST(mps_ap_create_k(&thread->ap, pool, mps_args_none));
|
||||
thread->fn(thread);
|
||||
mps_ap_destroy(thread->ap);
|
||||
mps_root_destroy(thread->reg_root);
|
||||
mps_thread_dereg(thread->mps_thread);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void weave(gcthread_fn_t fn)
|
||||
{
|
||||
gcthread_t threads = alloca(sizeof(threads[0]) * nthreads);
|
||||
unsigned t;
|
||||
|
||||
for (t = 0; t < nthreads; ++t) {
|
||||
gcthread_t thread = &threads[t];
|
||||
int err;
|
||||
thread->fn = fn;
|
||||
err = pthread_create(&thread->pthread, NULL, start, thread);
|
||||
if (err != 0) {
|
||||
fprintf(stderr, "Unable to create thread: %d\n", err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
for (t = 0; t < nthreads; ++t) {
|
||||
gcthread_t thread = &threads[t];
|
||||
int err = pthread_join(thread->pthread, NULL);
|
||||
if (err != 0) {
|
||||
fprintf(stderr, "Unable to join thread: %d\n", err);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void weave1(gcthread_fn_t fn)
|
||||
{
|
||||
gcthread_t thread = alloca(sizeof(thread[0]));
|
||||
|
||||
thread->fn = fn;
|
||||
start(thread);
|
||||
}
|
||||
|
||||
|
||||
static void watch(gcthread_fn_t fn, const char *name)
|
||||
{
|
||||
clock_t start, finish;
|
||||
|
||||
start = clock();
|
||||
if (nthreads == 1)
|
||||
weave1(fn);
|
||||
else
|
||||
weave(fn);
|
||||
finish = clock();
|
||||
|
||||
printf("%s: %g\n", name, (double)(finish - start) / CLOCKS_PER_SEC);
|
||||
}
|
||||
|
||||
|
||||
/* Setup MPS arena and call benchmark. */
|
||||
|
||||
static void arena_setup(gcthread_fn_t fn,
|
||||
mps_class_t pool_class,
|
||||
const char *name)
|
||||
{
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_ARENA_SIZE, arenasize);
|
||||
MPS_ARGS_DONE(args);
|
||||
RESMUST(mps_arena_create_k(&arena, mps_arena_class_vm(), args));
|
||||
} MPS_ARGS_END(args);
|
||||
RESMUST(dylan_fmt(&format, arena));
|
||||
/* Make wrappers now to avoid race condition. */
|
||||
/* dylan_make_wrappers() uses malloc. */
|
||||
RESMUST(dylan_make_wrappers());
|
||||
RESMUST(mps_chain_create(&chain, arena, ngen, gen));
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain);
|
||||
MPS_ARGS_DONE(args);
|
||||
RESMUST(mps_pool_create_k(&pool, arena, pool_class, args));
|
||||
} MPS_ARGS_END(args);
|
||||
watch(fn, name);
|
||||
mps_pool_destroy(pool);
|
||||
mps_fmt_destroy(format);
|
||||
mps_chain_destroy(chain);
|
||||
mps_arena_destroy(arena);
|
||||
}
|
||||
|
||||
|
||||
/* Command-line options definitions. See getopt_long(3). */
|
||||
|
||||
static struct option longopts[] = {
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"nthreads", required_argument, NULL, 't'},
|
||||
{"niter", required_argument, NULL, 'i'},
|
||||
{"npass", required_argument, NULL, 'p'},
|
||||
{"gen", required_argument, NULL, 'g'},
|
||||
{"arena-size",required_argument, NULL, 'm'},
|
||||
{"width", required_argument, NULL, 'w'},
|
||||
{"depth", required_argument, NULL, 'd'},
|
||||
{"preuse", required_argument, NULL, 'r'},
|
||||
{"pupdate", required_argument, NULL, 'u'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
gcthread_fn_t fn;
|
||||
mps_class_t (*pool_class)(void);
|
||||
} pools[] = {
|
||||
{"amc", gc_tree, mps_class_amc},
|
||||
{"ams", gc_tree, mps_class_ams},
|
||||
};
|
||||
|
||||
|
||||
/* Command-line driver */
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int ch;
|
||||
unsigned i;
|
||||
|
||||
seed = rnd_seed();
|
||||
|
||||
while ((ch = getopt_long(argc, argv, "ht:i:p:g:m:w:d:r:u:x:", longopts, NULL)) != -1)
|
||||
switch (ch) {
|
||||
case 't':
|
||||
nthreads = (unsigned)strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'i':
|
||||
niter = (unsigned)strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'p':
|
||||
npass = (unsigned)strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'g':
|
||||
if (ngen >= genLIMIT) {
|
||||
fprintf(stderr, "exceeded genLIMIT\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
{
|
||||
char *p;
|
||||
size_t cap = 0;
|
||||
double mort = 0.0;
|
||||
cap = (size_t)strtoul(optarg, &p, 10);
|
||||
switch(toupper(*p)) {
|
||||
case 'G': cap *= 1024;
|
||||
case 'M': cap *= 1024;
|
||||
case 'K': p++; break;
|
||||
default: cap = 0; break;
|
||||
}
|
||||
if (sscanf(p, ",%lg", &mort) != 1 || cap == 0) {
|
||||
fprintf(stderr, "Bad gen format '%s'\n"
|
||||
"Each gen option has format --gen=capacity[KMG],mortality\n"
|
||||
"where capacity is a size specified in kilobytes, megabytes or gigabytes\n"
|
||||
"and mortality is a number between 0 and 1\n"
|
||||
"e.g.: --gen=500K,0.85 --gen=20M,0.45\n", optarg);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
gen[ngen].mps_capacity = cap;
|
||||
gen[ngen].mps_mortality = mort;
|
||||
ngen++;
|
||||
}
|
||||
break;
|
||||
case 'm': {
|
||||
char *p;
|
||||
arenasize = (unsigned)strtoul(optarg, &p, 10);
|
||||
switch(toupper(*p)) {
|
||||
case 'G': arenasize *= 1024;
|
||||
case 'M': arenasize *= 1024;
|
||||
case 'K': arenasize *= 1024; break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'w':
|
||||
width = (size_t)strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'd':
|
||||
depth = (unsigned)strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'r':
|
||||
preuse = strtod(optarg, NULL);
|
||||
break;
|
||||
case 'u':
|
||||
pupdate = strtod(optarg, NULL);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"Usage: %s [option...] [test...]\n"
|
||||
"Options:\n"
|
||||
" -t n, --nthreads=n\n"
|
||||
" Launch n threads each running the test (default %u).\n"
|
||||
" -i n, --niter=n\n"
|
||||
" Iterate each test n times (default %u).\n"
|
||||
" -p n, --npass=n\n"
|
||||
" Pass over the tree n times (default %u).\n"
|
||||
" -g c,m, --gen=c[KMG],m\n"
|
||||
" Generation with capacity c (in Kb) and mortality m\n"
|
||||
" Use multiple times for multiple generations.\n"
|
||||
" -m n, --arena-size=n[KMG]?\n"
|
||||
" Initial size of arena (default %lu).\n"
|
||||
" -w n, --width=n\n"
|
||||
" Width of tree nodes made (default %lu)\n",
|
||||
argv[0],
|
||||
nthreads,
|
||||
niter,
|
||||
npass,
|
||||
(unsigned long)arenasize,
|
||||
(unsigned long)width);
|
||||
fprintf(stderr,
|
||||
" -d n, --depth=n\n"
|
||||
" Depth of tree made (default %u)\n"
|
||||
" -r p, --preuse=p\n"
|
||||
" Probability of reusing a node (default %g)\n"
|
||||
" -u p, --pupdate=p\n"
|
||||
" Probability of updating a node (default %g)\n"
|
||||
"Tests:\n"
|
||||
" amc pool class AMC\n"
|
||||
" ams pool class AMS\n",
|
||||
depth,
|
||||
preuse,
|
||||
pupdate);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (ngen == 0) {
|
||||
memcpy(gen, genDefault, sizeof(genDefault));
|
||||
ngen = sizeof(genDefault) / sizeof(genDefault[0]);
|
||||
}
|
||||
|
||||
printf("seed: %lu\n", seed);
|
||||
|
||||
while (argc > 0) {
|
||||
for (i = 0; i < sizeof(pools) / sizeof(pools[0]); ++i)
|
||||
if (strcmp(argv[0], pools[i].name) == 0)
|
||||
goto found;
|
||||
fprintf(stderr, "unknown pool test \"%s\"\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
found:
|
||||
rnd_state_set(seed);
|
||||
arena_setup(pools[i].fn, pools[i].pool_class(), pools[i].name);
|
||||
--argc;
|
||||
++argv;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited <http://www.ravenbrook.com/>.
|
||||
* 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.
|
||||
*/
|
||||
|
|
@ -204,7 +204,6 @@
|
|||
3124CAFB156BE82000753214 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
|
||||
3124CAFC156BE82900753214 /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
3150AE53156ABA2500A6E22A /* libmps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 31EEABFB156AAF9D00714D05 /* libmps.a */; };
|
||||
318DA8CF1892B1210089718C /* djbench.c in Sources */ = {isa = PBXBuildFile; fileRef = 318DA8CE1892B1210089718C /* djbench.c */; };
|
||||
318DA8D21892B13B0089718C /* getoptl.c in Sources */ = {isa = PBXBuildFile; fileRef = 318DA8D11892B13B0089718C /* getoptl.c */; };
|
||||
318DA8D31892B27E0089718C /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
|
||||
31A47BA4156C1E130039B1C2 /* mps.c in Sources */ = {isa = PBXBuildFile; fileRef = 31A47BA3156C1E130039B1C2 /* mps.c */; };
|
||||
|
|
@ -246,6 +245,13 @@
|
|||
31EEAC9F156AB73400714D05 /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
|
||||
31FCAE161769244F008C034C /* mps.c in Sources */ = {isa = PBXBuildFile; fileRef = 31A47BA3156C1E130039B1C2 /* mps.c */; };
|
||||
31FCAE19176924D4008C034C /* scheme.c in Sources */ = {isa = PBXBuildFile; fileRef = 31FCAE18176924D4008C034C /* scheme.c */; };
|
||||
6313D46918A400B200EB03EF /* testlib.c in Sources */ = {isa = PBXBuildFile; fileRef = 31EEAC9E156AB73400714D05 /* testlib.c */; };
|
||||
6313D46A18A400B200EB03EF /* getoptl.c in Sources */ = {isa = PBXBuildFile; fileRef = 318DA8D11892B13B0089718C /* getoptl.c */; };
|
||||
6313D47318A4028E00EB03EF /* djbench.c in Sources */ = {isa = PBXBuildFile; fileRef = 318DA8CE1892B1210089718C /* djbench.c */; };
|
||||
6313D47418A4029200EB03EF /* gcbench.c in Sources */ = {isa = PBXBuildFile; fileRef = 6313D46618A3FDC900EB03EF /* gcbench.c */; };
|
||||
6313D47518A40C6300EB03EF /* fmtdytst.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC7156BE48D00753214 /* fmtdytst.c */; };
|
||||
6313D47618A40C7B00EB03EF /* fmtdy.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CAC6156BE48D00753214 /* fmtdy.c */; };
|
||||
6313D47718A40D0400EB03EF /* fmtno.c in Sources */ = {isa = PBXBuildFile; fileRef = 3124CACC156BE4C200753214 /* fmtno.c */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
|
@ -1121,6 +1127,15 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
6313D46D18A400B200EB03EF /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = /usr/share/man/man1/;
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
|
|
@ -1334,6 +1349,8 @@
|
|||
31F6CCAD1739B0CF00C48748 /* mpscsnc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mpscsnc.h; sourceTree = "<group>"; };
|
||||
31FCAE0A17692403008C034C /* scheme */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = scheme; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
31FCAE18176924D4008C034C /* scheme.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = scheme.c; path = ../example/scheme/scheme.c; sourceTree = "<group>"; };
|
||||
6313D46618A3FDC900EB03EF /* gcbench.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = gcbench.c; sourceTree = "<group>"; };
|
||||
6313D47218A400B200EB03EF /* gcbench */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = gcbench; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
|
@ -1654,6 +1671,13 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
6313D46C18A400B200EB03EF /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
|
|
@ -1744,6 +1768,7 @@
|
|||
318DA8D01892B13B0089718C /* getopt.h */,
|
||||
318DA8D11892B13B0089718C /* getoptl.c */,
|
||||
318DA8CE1892B1210089718C /* djbench.c */,
|
||||
6313D46618A3FDC900EB03EF /* gcbench.c */,
|
||||
);
|
||||
name = Benchmarks;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -1816,6 +1841,7 @@
|
|||
224CC799175E1821002FF81B /* fotest */,
|
||||
31FCAE0A17692403008C034C /* scheme */,
|
||||
318DA8CD1892B0F30089718C /* djbench */,
|
||||
6313D47218A400B200EB03EF /* gcbench */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -2705,6 +2731,23 @@
|
|||
productReference = 31FCAE0A17692403008C034C /* scheme */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
6313D46718A400B200EB03EF /* gcbench */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 6313D46E18A400B200EB03EF /* Build configuration list for PBXNativeTarget "gcbench" */;
|
||||
buildPhases = (
|
||||
6313D46818A400B200EB03EF /* Sources */,
|
||||
6313D46C18A400B200EB03EF /* Frameworks */,
|
||||
6313D46D18A400B200EB03EF /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = gcbench;
|
||||
productName = scheme;
|
||||
productReference = 6313D47218A400B200EB03EF /* gcbench */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
|
|
@ -2767,6 +2810,7 @@
|
|||
22CDE8EF16E9E97D00366D0A /* testrun */,
|
||||
31FCAE0917692403008C034C /* scheme */,
|
||||
318DA8C31892B0F30089718C /* djbench */,
|
||||
6313D46718A400B200EB03EF /* gcbench */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
|
@ -3109,8 +3153,8 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
318DA8D31892B27E0089718C /* testlib.c in Sources */,
|
||||
6313D47318A4028E00EB03EF /* djbench.c in Sources */,
|
||||
318DA8D21892B13B0089718C /* getoptl.c in Sources */,
|
||||
318DA8CF1892B1210089718C /* djbench.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -3208,6 +3252,19 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
6313D46818A400B200EB03EF /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6313D47718A40D0400EB03EF /* fmtno.c in Sources */,
|
||||
6313D46918A400B200EB03EF /* testlib.c in Sources */,
|
||||
6313D47418A4029200EB03EF /* gcbench.c in Sources */,
|
||||
6313D47518A40C6300EB03EF /* fmtdytst.c in Sources */,
|
||||
6313D47618A40C7B00EB03EF /* fmtdy.c in Sources */,
|
||||
6313D46A18A400B200EB03EF /* getoptl.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
|
|
@ -4874,6 +4931,30 @@
|
|||
};
|
||||
name = Release;
|
||||
};
|
||||
6313D46F18A400B200EB03EF /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = NO;
|
||||
PRODUCT_NAME = gcbench;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
6313D47018A400B200EB03EF /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = NO;
|
||||
PRODUCT_NAME = gcbench;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
6313D47118A400B200EB03EF /* RASH */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = NO;
|
||||
PRODUCT_NAME = gcbench;
|
||||
};
|
||||
name = RASH;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
|
|
@ -5307,6 +5388,16 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
6313D46E18A400B200EB03EF /* Build configuration list for PBXNativeTarget "gcbench" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
6313D46F18A400B200EB03EF /* Debug */,
|
||||
6313D47018A400B200EB03EF /* Release */,
|
||||
6313D47118A400B200EB03EF /* RASH */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 31EEABDA156AAE9E00714D05 /* Project object */;
|
||||
|
|
|
|||
|
|
@ -832,8 +832,8 @@ static Res MVTInsert(MVT mvt, Addr base, Addr limit)
|
|||
|
||||
if (RangeSize(&newRange) >= mvt->reuseSize) {
|
||||
/* The new range is big enough that it might have been coalesced
|
||||
* with ranges on the ABQ, so ensure that they are removed before
|
||||
* reserving the new range.
|
||||
* with ranges on the ABQ, so ensure that the corresponding ranges
|
||||
* are coalesced on the ABQ.
|
||||
*/
|
||||
ABQIterate(MVTABQ(mvt), MVTDeleteOverlapping, &newRange, 0);
|
||||
MVTReserve(mvt, &newRange);
|
||||
|
|
|
|||
|
|
@ -399,9 +399,7 @@ Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet)
|
|||
arena = trace->arena;
|
||||
|
||||
if(SegFirst(&seg, arena)) {
|
||||
Addr base;
|
||||
do {
|
||||
base = SegBase(seg);
|
||||
/* Segment should be black now. */
|
||||
AVER(!TraceSetIsMember(SegGrey(seg), trace));
|
||||
AVER(!TraceSetIsMember(SegWhite(seg), trace));
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* version.c: VERSION INSPECTION
|
||||
*
|
||||
* $Id$
|
||||
* Copyright (c) 2001-2013 Ravenbrook Limited.
|
||||
* Copyright (c) 2001-2014 Ravenbrook Limited.
|
||||
* See end of file for license.
|
||||
*
|
||||
* PURPOSE
|
||||
|
|
@ -29,7 +29,7 @@ SRCID(version, "$Id$");
|
|||
* (Note: before 2006-02-01 the style was "release.epcore.chub")
|
||||
*/
|
||||
|
||||
#define MPS_RELEASE "release/1.112.0"
|
||||
#define MPS_RELEASE "release/1.113.0"
|
||||
|
||||
|
||||
/* MPSCopyrightNotice -- copyright notice for the binary
|
||||
|
|
@ -39,7 +39,7 @@ SRCID(version, "$Id$");
|
|||
*/
|
||||
|
||||
char MPSCopyrightNotice[] =
|
||||
"Portions copyright (c) 2010-2013 Ravenbrook Limited and Global Graphics Software.";
|
||||
"Portions copyright (c) 2010-2014 Ravenbrook Limited and Global Graphics Software.";
|
||||
|
||||
|
||||
/* MPSVersion -- return version string
|
||||
|
|
@ -63,7 +63,7 @@ char *MPSVersion(void)
|
|||
|
||||
/* C. COPYRIGHT AND LICENSE
|
||||
*
|
||||
* Copyright (C) 2001-2013 Ravenbrook Limited
|
||||
* Copyright (C) 2001-2014 Ravenbrook Limited
|
||||
* <http://www.ravenbrook.com/>.
|
||||
* All rights reserved. This is an open source license. Contact
|
||||
* Ravenbrook for commercial licensing options.
|
||||
|
|
|
|||
|
|
@ -74,10 +74,8 @@ static void ArenaFormattedObjectsWalk(Arena arena, FormattedObjectsStepMethod f,
|
|||
AVERT(FormattedObjectsStepClosure, c);
|
||||
|
||||
if (SegFirst(&seg, arena)) {
|
||||
Addr base;
|
||||
do {
|
||||
Pool pool;
|
||||
base = SegBase(seg);
|
||||
pool = SegPool(seg);
|
||||
if (pool->class->attr & AttrFMT) {
|
||||
ShieldExpose(arena, seg);
|
||||
|
|
@ -308,9 +306,7 @@ static Res ArenaRootsWalk(Globals arenaGlobals, mps_roots_stepper_t f,
|
|||
/* ArenaRootsWalk only passes references to GCable pools to the client. */
|
||||
/* NOTE: I'm not sure why this is. RB 2012-07-24 */
|
||||
if (SegFirst(&seg, arena)) {
|
||||
Addr base;
|
||||
do {
|
||||
base = SegBase(seg);
|
||||
if ((SegPool(seg)->class->attr & AttrGC) != 0) {
|
||||
TraceAddWhite(trace, seg);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue