mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-03-27 01:01:52 -07:00
Merge branch/2014-04-22/condemn into the master sources.
Copied from Perforce Change: 185812 ServerID: perforce.ravenbrook.com
This commit is contained in:
commit
2c19172293
7 changed files with 185 additions and 161 deletions
|
|
@ -27,7 +27,7 @@
|
|||
#define totalSizeSTEP 200 * (size_t)1024
|
||||
/* objNULL needs to be odd so that it's ignored in exactRoots. */
|
||||
#define objNULL ((mps_addr_t)MPS_WORD_CONST(0xDECEA5ED))
|
||||
#define testArenaSIZE ((size_t)16<<20)
|
||||
#define testArenaSIZE ((size_t)1<<20)
|
||||
#define initTestFREQ 3000
|
||||
#define splatTestFREQ 6000
|
||||
static mps_gen_param_s testChain[1] = { { 160, 0.90 } };
|
||||
|
|
@ -107,7 +107,8 @@ static mps_addr_t make(void)
|
|||
static mps_pool_debug_option_s freecheckOptions =
|
||||
{ NULL, 0, (const void *)"Dead", 4 };
|
||||
|
||||
static void *test(void *arg, size_t haveAmbigous)
|
||||
static void test_pool(mps_class_t pool_class, mps_arg_s args[],
|
||||
size_t haveAmbiguous)
|
||||
{
|
||||
mps_pool_t pool;
|
||||
mps_root_t exactRoot, ambigRoot = NULL;
|
||||
|
|
@ -116,14 +117,13 @@ static void *test(void *arg, size_t haveAmbigous)
|
|||
mps_ap_t busy_ap;
|
||||
mps_addr_t busy_init;
|
||||
|
||||
pool = (mps_pool_t)arg;
|
||||
|
||||
die(mps_pool_create_k(&pool, arena, pool_class, args), "pool_create");
|
||||
die(mps_ap_create(&ap, pool, mps_rank_exact()), "BufferCreate");
|
||||
die(mps_ap_create(&busy_ap, pool, mps_rank_exact()), "BufferCreate 2");
|
||||
|
||||
for(i = 0; i < exactRootsCOUNT; ++i)
|
||||
exactRoots[i] = objNULL;
|
||||
if (haveAmbigous)
|
||||
if (haveAmbiguous)
|
||||
for(i = 0; i < ambigRootsCOUNT; ++i)
|
||||
ambigRoots[i] = rnd_addr();
|
||||
|
||||
|
|
@ -132,7 +132,7 @@ static void *test(void *arg, size_t haveAmbigous)
|
|||
&exactRoots[0], exactRootsCOUNT,
|
||||
(mps_word_t)1),
|
||||
"root_create_table(exact)");
|
||||
if (haveAmbigous)
|
||||
if (haveAmbiguous)
|
||||
die(mps_root_create_table(&ambigRoot, arena,
|
||||
mps_rank_ambig(), (mps_rm_t)0,
|
||||
&ambigRoots[0], ambigRootsCOUNT),
|
||||
|
|
@ -154,7 +154,7 @@ static void *test(void *arg, size_t haveAmbigous)
|
|||
}
|
||||
|
||||
r = (size_t)rnd();
|
||||
if (!haveAmbigous || (r & 1)) {
|
||||
if (!haveAmbiguous || (r & 1)) {
|
||||
i = (r >> 1) % exactRootsCOUNT;
|
||||
if (exactRoots[i] != objNULL)
|
||||
cdie(dylan_check(exactRoots[i]), "dying root check");
|
||||
|
|
@ -187,80 +187,49 @@ static void *test(void *arg, size_t haveAmbigous)
|
|||
mps_ap_destroy(busy_ap);
|
||||
mps_ap_destroy(ap);
|
||||
mps_root_destroy(exactRoot);
|
||||
if (haveAmbigous)
|
||||
if (haveAmbiguous)
|
||||
mps_root_destroy(ambigRoot);
|
||||
|
||||
return NULL;
|
||||
mps_pool_destroy(pool);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
mps_thr_t thread;
|
||||
mps_fmt_t format;
|
||||
mps_chain_t chain;
|
||||
mps_pool_t pool;
|
||||
void *r;
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
|
||||
"arena_create");
|
||||
die(mps_arena_commit_limit_set(arena, 2 * testArenaSIZE), "commit_limit_set");
|
||||
|
||||
mps_message_type_enable(arena, mps_message_type_gc_start());
|
||||
mps_message_type_enable(arena, mps_message_type_gc());
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg");
|
||||
die(mps_fmt_create_A(&format, arena, dylan_fmt_A()), "fmt_create");
|
||||
die(mps_chain_create(&chain, arena, 1, testChain), "chain_create");
|
||||
|
||||
/* TODO: Add tests using the arena default chain. */
|
||||
|
||||
printf("\n\n****************************** Testing AMS Debug\n");
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, FALSE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, &freecheckOptions);
|
||||
die(mps_pool_create_k(&pool, arena, mps_class_ams_debug(), args),
|
||||
"pool_create(ams_debug,share)");
|
||||
} MPS_ARGS_END(args);
|
||||
mps_tramp(&r, test, pool, 0);
|
||||
mps_pool_destroy(pool);
|
||||
|
||||
printf("\n\n****************************** Testing AMS Debug\n");
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, &freecheckOptions);
|
||||
die(mps_pool_create_k(&pool, arena, mps_class_ams_debug(), args),
|
||||
"pool_create(ams_debug,ambig)");
|
||||
} MPS_ARGS_END(args);
|
||||
mps_tramp(&r, test, pool, 1);
|
||||
mps_pool_destroy(pool);
|
||||
|
||||
printf("\n\n****************************** Testing AMS\n");
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, TRUE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, &freecheckOptions);
|
||||
die(mps_pool_create_k(&pool, arena, mps_class_ams(), args),
|
||||
"pool_create(ams,ambig)");
|
||||
} MPS_ARGS_END(args);
|
||||
mps_tramp(&r, test, pool, 1);
|
||||
mps_pool_destroy(pool);
|
||||
|
||||
printf("\n\n****************************** Testing AMS\n");
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, FALSE);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, &freecheckOptions);
|
||||
die(mps_pool_create_k(&pool, arena, mps_class_ams(), args),
|
||||
"pool_create(ams,share)");
|
||||
} MPS_ARGS_END(args);
|
||||
mps_tramp(&r, test, pool, 0);
|
||||
mps_pool_destroy(pool);
|
||||
for (i = 0; i < 8; i++) {
|
||||
int debug = i % 2;
|
||||
int ownChain = (i / 2) % 2;
|
||||
int ambig = (i / 4) % 2;
|
||||
printf("\n\n*** AMS%s with %sCHAIN and %sSUPPORT_AMBIGUOUS\n",
|
||||
debug ? " Debug" : "",
|
||||
ownChain ? "" : "!",
|
||||
ambig ? "" : "!");
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, format);
|
||||
if (chain)
|
||||
MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_AMS_SUPPORT_AMBIGUOUS, ambig);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_POOL_DEBUG_OPTIONS, &freecheckOptions);
|
||||
test_pool(debug ? mps_class_ams_debug() : mps_class_ams(), args, TRUE);
|
||||
} MPS_ARGS_END(args);
|
||||
}
|
||||
|
||||
mps_chain_destroy(chain);
|
||||
mps_fmt_destroy(format);
|
||||
|
|
|
|||
|
|
@ -275,9 +275,6 @@ static void *setup(void *v, size_t s)
|
|||
die(mps_fmt_create_A(&dylanweakfmt, arena, dylan_fmt_A_weak()),
|
||||
"Format Create (weak)\n");
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
/* Ask the leafpool to allocate in the nursery, as we're using it to test
|
||||
weaknesss and want things to die in it promptly. */
|
||||
MPS_ARGS_ADD(args, MPS_KEY_GEN, 0);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, dylanfmt);
|
||||
die(mps_pool_create_k(&leafpool, arena, mps_class_lo(), args),
|
||||
"Leaf Pool Create\n");
|
||||
|
|
|
|||
|
|
@ -277,9 +277,6 @@ static void *setup(void *v, size_t s)
|
|||
die(EnsureHeaderFormat(&dylanfmt, arena), "EnsureHeaderFormat");
|
||||
die(EnsureHeaderWeakFormat(&dylanweakfmt, arena), "EnsureHeaderWeakFormat");
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
/* Ask the leafpool to allocate in the nursery, as we're using it to test
|
||||
weaknesss and want things to die in it promptly. */
|
||||
MPS_ARGS_ADD(args, MPS_KEY_GEN, 0);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, dylanfmt);
|
||||
die(mps_pool_create_k(&leafpool, arena, mps_class_lo(), args),
|
||||
"Leaf Pool Create\n");
|
||||
|
|
|
|||
|
|
@ -81,7 +81,6 @@ extern Bool ChainCheck(Chain chain);
|
|||
|
||||
extern double ChainDeferral(Chain chain);
|
||||
extern Res ChainCondemnAuto(double *mortalityReturn, Chain chain, Trace trace);
|
||||
extern Res ChainCondemnAll(Chain chain, Trace trace);
|
||||
extern void ChainStartGC(Chain chain, Trace trace);
|
||||
extern void ChainEndGC(Chain chain, Trace trace);
|
||||
extern size_t ChainGens(Chain chain);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,20 @@
|
|||
*
|
||||
* DESIGN
|
||||
*
|
||||
* .mode: This test has two modes.
|
||||
*
|
||||
* .mode.park: In this mode, we use the arena's default generation
|
||||
* chain, leave the arena parked and call mps_arena_collect. This
|
||||
* tests that the default generation chain works and that all segments
|
||||
* get condemned via TraceStartCollectAll. (See job003771 item 4.)
|
||||
*
|
||||
* .mode.poll: In this mode, we use our own generation chain (with
|
||||
* small generations), allocate into generation 1, unclamp the arena,
|
||||
* and provoke collection by allocating. This tests that custom
|
||||
* generation chains work, and that segments get condemned via
|
||||
* TracePoll even if there is no allocation into generation 0 of the
|
||||
* chain. (See job003771 item 5.)
|
||||
*
|
||||
* DEPENDENCIES
|
||||
*
|
||||
* This test uses the dylan object format, but the reliance on this
|
||||
|
|
@ -16,6 +30,7 @@
|
|||
* This code was created by first copying <code/finalcv.c>
|
||||
*/
|
||||
|
||||
#include "mpm.h"
|
||||
#include "testlib.h"
|
||||
#include "mpslib.h"
|
||||
#include "mps.h"
|
||||
|
|
@ -30,10 +45,15 @@
|
|||
|
||||
#include <stdio.h> /* fflush, printf, stdout */
|
||||
|
||||
enum {
|
||||
ModePARK, /* .mode.park */
|
||||
ModePOLL /* .mode.poll */
|
||||
};
|
||||
|
||||
|
||||
#define testArenaSIZE ((size_t)16<<20)
|
||||
#define rootCOUNT 20
|
||||
#define maxtreeDEPTH 10
|
||||
#define maxtreeDEPTH 9
|
||||
#define collectionCOUNT 10
|
||||
|
||||
|
||||
|
|
@ -126,17 +146,21 @@ static mps_addr_t test_awl_find_dependent(mps_addr_t addr)
|
|||
|
||||
static void *root[rootCOUNT];
|
||||
|
||||
static void test_trees(const char *name, mps_arena_t arena, mps_ap_t ap,
|
||||
static void test_trees(int mode, const char *name, mps_arena_t arena,
|
||||
mps_ap_t ap,
|
||||
mps_word_t (*make)(mps_word_t, mps_ap_t),
|
||||
void (*reg)(mps_word_t, mps_arena_t))
|
||||
{
|
||||
size_t collections = 0;
|
||||
size_t finals = 0;
|
||||
size_t i;
|
||||
int object_alloc;
|
||||
|
||||
object_count = 0;
|
||||
|
||||
printf("Making some %s finalized trees of objects.\n", name);
|
||||
mps_arena_park(arena);
|
||||
|
||||
/* make some trees */
|
||||
for(i = 0; i < rootCOUNT; ++i) {
|
||||
root[i] = (void *)(*make)(maxtreeDEPTH, ap);
|
||||
|
|
@ -151,10 +175,23 @@ static void test_trees(const char *name, mps_arena_t arena, mps_ap_t ap,
|
|||
|
||||
while (finals < object_count && collections < collectionCOUNT) {
|
||||
mps_word_t final_this_time = 0;
|
||||
printf("Collecting...");
|
||||
(void)fflush(stdout);
|
||||
die(mps_arena_collect(arena), "collect");
|
||||
printf(" Done.\n");
|
||||
switch (mode) {
|
||||
default:
|
||||
case ModePARK:
|
||||
printf("Collecting...");
|
||||
(void)fflush(stdout);
|
||||
die(mps_arena_collect(arena), "collect");
|
||||
printf(" Done.\n");
|
||||
break;
|
||||
case ModePOLL:
|
||||
mps_arena_release(arena);
|
||||
printf("Allocating...");
|
||||
(void)fflush(stdout);
|
||||
object_alloc = 0;
|
||||
while (object_alloc < 1000 && !mps_message_poll(arena))
|
||||
(void)DYLAN_INT(object_alloc++);
|
||||
break;
|
||||
}
|
||||
++ collections;
|
||||
while (mps_message_poll(arena)) {
|
||||
mps_message_t message;
|
||||
|
|
@ -170,10 +207,14 @@ static void test_trees(const char *name, mps_arena_t arena, mps_ap_t ap,
|
|||
" of %"PRIuLONGEST"\n", (ulongest_t)final_this_time,
|
||||
(ulongest_t)finals, (ulongest_t)object_count);
|
||||
}
|
||||
cdie(finals == object_count, "Not all objects were finalized.");
|
||||
if (finals != object_count)
|
||||
error("Not all objects were finalized for %s in mode %s.",
|
||||
BufferOfAP(ap)->pool->class->name,
|
||||
mode == ModePOLL ? "POLL" : "PARK");
|
||||
}
|
||||
|
||||
static void *test(mps_arena_t arena, mps_class_t pool_class)
|
||||
static void test_pool(int mode, mps_arena_t arena, mps_chain_t chain,
|
||||
mps_class_t pool_class)
|
||||
{
|
||||
mps_ap_t ap;
|
||||
mps_fmt_t fmt;
|
||||
|
|
@ -182,10 +223,13 @@ static void *test(mps_arena_t arena, mps_class_t pool_class)
|
|||
|
||||
die(mps_fmt_create_A(&fmt, arena, dylan_fmt_A()), "fmt_create\n");
|
||||
MPS_ARGS_BEGIN(args) {
|
||||
/* Allocate into generation 0 so that they get finalized quickly. */
|
||||
MPS_ARGS_ADD(args, MPS_KEY_GEN, 0);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_FORMAT, fmt);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_AWL_FIND_DEPENDENT, test_awl_find_dependent);
|
||||
if (mode == ModePOLL) {
|
||||
MPS_ARGS_ADD(args, MPS_KEY_CHAIN, chain);
|
||||
MPS_ARGS_ADD(args, MPS_KEY_GEN, 1);
|
||||
}
|
||||
if (pool_class == mps_class_awl())
|
||||
MPS_ARGS_ADD(args, MPS_KEY_AWL_FIND_DEPENDENT, test_awl_find_dependent);
|
||||
die(mps_pool_create_k(&pool, arena, pool_class, args),
|
||||
"pool_create\n");
|
||||
} MPS_ARGS_END(args);
|
||||
|
|
@ -194,19 +238,25 @@ static void *test(mps_arena_t arena, mps_class_t pool_class)
|
|||
"root_create\n");
|
||||
die(mps_ap_create(&ap, pool, mps_rank_exact()), "ap_create\n");
|
||||
|
||||
mps_message_type_enable(arena, mps_message_type_finalization());
|
||||
|
||||
mps_arena_park(arena);
|
||||
|
||||
test_trees("numbered", arena, ap, make_numbered_tree, register_numbered_tree);
|
||||
test_trees("indirect", arena, ap, make_indirect_tree, register_indirect_tree);
|
||||
test_trees(mode, "numbered", arena, ap, make_numbered_tree,
|
||||
register_numbered_tree);
|
||||
test_trees(mode, "indirect", arena, ap, make_indirect_tree,
|
||||
register_indirect_tree);
|
||||
|
||||
mps_ap_destroy(ap);
|
||||
mps_root_destroy(mps_root);
|
||||
mps_pool_destroy(pool);
|
||||
mps_fmt_destroy(fmt);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
static void test_mode(int mode, mps_arena_t arena, mps_chain_t chain)
|
||||
{
|
||||
test_pool(mode, arena, chain, mps_class_amc());
|
||||
test_pool(mode, arena, chain, mps_class_amcz());
|
||||
test_pool(mode, arena, chain, mps_class_ams());
|
||||
/* test_pool(mode, arena, chain, mps_class_lo()); TODO: job003773 */
|
||||
/* test_pool(mode, arena, chain, mps_class_awl()); TODO: job003772 */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -214,19 +264,27 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
mps_arena_t arena;
|
||||
mps_thr_t thread;
|
||||
mps_chain_t chain;
|
||||
mps_gen_param_s params[2];
|
||||
size_t gens = 2;
|
||||
size_t i;
|
||||
|
||||
testlib_init(argc, argv);
|
||||
|
||||
die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE),
|
||||
"arena_create\n");
|
||||
mps_message_type_enable(arena, mps_message_type_finalization());
|
||||
die(mps_thread_reg(&thread, arena), "thread_reg\n");
|
||||
for (i = 0; i < gens; ++i) {
|
||||
params[i].mps_capacity = 1;
|
||||
params[i].mps_mortality = 0.5;
|
||||
}
|
||||
die(mps_chain_create(&chain, arena, gens, params), "chain_create\n");
|
||||
|
||||
test(arena, mps_class_amc());
|
||||
test(arena, mps_class_amcz());
|
||||
test(arena, mps_class_ams());
|
||||
test(arena, mps_class_awl());
|
||||
/* TODO: test(arena, mps_class_lo()); */
|
||||
test_mode(ModePOLL, arena, chain);
|
||||
test_mode(ModePARK, arena, NULL);
|
||||
|
||||
mps_chain_destroy(chain);
|
||||
mps_thread_dereg(thread);
|
||||
mps_arena_destroy(arena);
|
||||
|
||||
|
|
|
|||
101
mps/code/locus.c
101
mps/code/locus.c
|
|
@ -287,13 +287,21 @@ Res ChainAlloc(Seg *segReturn, Chain chain, Serial genNr, SegClass class,
|
|||
|
||||
double ChainDeferral(Chain chain)
|
||||
{
|
||||
double time = DBL_MAX;
|
||||
size_t i;
|
||||
|
||||
AVERT(Chain, chain);
|
||||
|
||||
if (chain->activeTraces != TraceSetEMPTY)
|
||||
return DBL_MAX;
|
||||
else
|
||||
return chain->gens[0].capacity * 1024.0
|
||||
- (double)GenDescNewSize(&chain->gens[0]);
|
||||
if (chain->activeTraces == TraceSetEMPTY) {
|
||||
for (i = 0; i < chain->genCount; ++i) {
|
||||
double genTime = chain->gens[i].capacity * 1024.0
|
||||
- (double)GenDescNewSize(&chain->gens[i]);
|
||||
if (genTime < time)
|
||||
time = genTime;
|
||||
}
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -306,7 +314,7 @@ double ChainDeferral(Chain chain)
|
|||
Res ChainCondemnAuto(double *mortalityReturn, Chain chain, Trace trace)
|
||||
{
|
||||
Res res;
|
||||
Serial topCondemnedGenSerial, currGenSerial;
|
||||
size_t topCondemnedGen, i;
|
||||
GenDesc gen;
|
||||
ZoneSet condemnedSet = ZoneSetEMPTY;
|
||||
Size condemnedSize = 0, survivorSize = 0, genNewSize, genTotalSize;
|
||||
|
|
@ -314,33 +322,39 @@ Res ChainCondemnAuto(double *mortalityReturn, Chain chain, Trace trace)
|
|||
AVERT(Chain, chain);
|
||||
AVERT(Trace, trace);
|
||||
|
||||
/* Find lowest gen within its capacity, set topCondemnedGenSerial to the */
|
||||
/* preceeding one. */
|
||||
currGenSerial = 0;
|
||||
gen = &chain->gens[0];
|
||||
AVERT(GenDesc, gen);
|
||||
genNewSize = GenDescNewSize(gen);
|
||||
do { /* At this point, we've decided to collect currGenSerial. */
|
||||
topCondemnedGenSerial = currGenSerial;
|
||||
/* Find the highest generation that's over capacity. We will condemn
|
||||
* this and all lower generations in the chain. */
|
||||
topCondemnedGen = chain->genCount;
|
||||
for (;;) {
|
||||
/* It's an error to call this function unless some generation is
|
||||
* over capacity as reported by ChainDeferral. */
|
||||
AVER(topCondemnedGen > 0);
|
||||
if (topCondemnedGen == 0)
|
||||
return ResFAIL;
|
||||
-- topCondemnedGen;
|
||||
gen = &chain->gens[topCondemnedGen];
|
||||
AVERT(GenDesc, gen);
|
||||
genNewSize = GenDescNewSize(gen);
|
||||
if (genNewSize >= gen->capacity * (Size)1024)
|
||||
break;
|
||||
}
|
||||
|
||||
/* At this point, we've decided to condemn topCondemnedGen and all
|
||||
* lower generations. */
|
||||
for (i = 0; i <= topCondemnedGen; ++i) {
|
||||
gen = &chain->gens[i];
|
||||
AVERT(GenDesc, gen);
|
||||
condemnedSet = ZoneSetUnion(condemnedSet, gen->zones);
|
||||
genTotalSize = GenDescTotalSize(gen);
|
||||
genNewSize = GenDescNewSize(gen);
|
||||
condemnedSize += genTotalSize;
|
||||
survivorSize += (Size)(genNewSize * (1.0 - gen->mortality))
|
||||
/* predict survivors will survive again */
|
||||
+ (genTotalSize - genNewSize);
|
||||
|
||||
/* is there another one to consider? */
|
||||
currGenSerial += 1;
|
||||
if (currGenSerial >= chain->genCount)
|
||||
break; /* reached the top */
|
||||
gen = &chain->gens[currGenSerial];
|
||||
AVERT(GenDesc, gen);
|
||||
genNewSize = GenDescNewSize(gen);
|
||||
} while (genNewSize >= gen->capacity * (Size)1024);
|
||||
}
|
||||
|
||||
AVER(condemnedSet != ZoneSetEMPTY || condemnedSize == 0);
|
||||
EVENT3(ChainCondemnAuto, chain, topCondemnedGenSerial, chain->genCount);
|
||||
UNUSED(topCondemnedGenSerial); /* only used for EVENT */
|
||||
EVENT3(ChainCondemnAuto, chain, topCondemnedGen, chain->genCount);
|
||||
|
||||
/* Condemn everything in these zones. */
|
||||
if (condemnedSet != ZoneSetEMPTY) {
|
||||
|
|
@ -354,41 +368,6 @@ Res ChainCondemnAuto(double *mortalityReturn, Chain chain, Trace trace)
|
|||
}
|
||||
|
||||
|
||||
/* ChainCondemnAll -- condemn everything in the chain */
|
||||
|
||||
Res ChainCondemnAll(Chain chain, Trace trace)
|
||||
{
|
||||
Ring node, nextNode;
|
||||
Bool haveWhiteSegs = FALSE;
|
||||
Res res;
|
||||
|
||||
/* Condemn every segment in every pool using this chain. */
|
||||
/* Finds the pools by iterating over the PoolGens in gen 0. */
|
||||
RING_FOR(node, &chain->gens[0].locusRing, nextNode) {
|
||||
PoolGen nursery = RING_ELT(PoolGen, genRing, node);
|
||||
Pool pool = nursery->pool;
|
||||
Ring segNode, nextSegNode;
|
||||
|
||||
AVERT(Pool, pool);
|
||||
AVER(PoolHasAttr(pool, AttrGC));
|
||||
RING_FOR(segNode, PoolSegRing(pool), nextSegNode) {
|
||||
Seg seg = SegOfPoolRing(segNode);
|
||||
|
||||
res = TraceAddWhite(trace, seg);
|
||||
if (res != ResOK)
|
||||
goto failBegin;
|
||||
haveWhiteSegs = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return ResOK;
|
||||
|
||||
failBegin:
|
||||
AVER(!haveWhiteSegs); /* Would leave white sets inconsistent. */
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* ChainStartGC -- called to notify start of GC for this chain */
|
||||
|
||||
void ChainStartGC(Chain chain, Trace trace)
|
||||
|
|
@ -416,9 +395,11 @@ void ChainEndGC(Chain chain, Trace trace)
|
|||
Res PoolGenInit(PoolGen gen, Chain chain, Serial nr, Pool pool)
|
||||
{
|
||||
/* Can't check gen, because it's not been initialized. */
|
||||
AVER(gen != NULL);
|
||||
AVERT(Chain, chain);
|
||||
AVER(nr <= chain->genCount);
|
||||
AVERT(Pool, pool);
|
||||
AVER(PoolHasAttr(pool, AttrGC));
|
||||
|
||||
gen->nr = nr;
|
||||
gen->pool = pool;
|
||||
|
|
|
|||
|
|
@ -390,6 +390,7 @@ Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet)
|
|||
Seg seg;
|
||||
Arena arena;
|
||||
Res res;
|
||||
Bool haveWhiteSegs = FALSE;
|
||||
|
||||
AVERT(Trace, trace);
|
||||
AVER(condemnedSet != ZoneSetEMPTY);
|
||||
|
|
@ -415,7 +416,8 @@ Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet)
|
|||
{
|
||||
res = TraceAddWhite(trace, seg);
|
||||
if(res != ResOK)
|
||||
return res;
|
||||
goto failBegin;
|
||||
haveWhiteSegs = TRUE;
|
||||
}
|
||||
} while (SegNext(&seg, arena, seg));
|
||||
}
|
||||
|
|
@ -426,6 +428,10 @@ Res TraceCondemnZones(Trace trace, ZoneSet condemnedSet)
|
|||
AVER(ZoneSetSuper(condemnedSet, trace->white));
|
||||
|
||||
return ResOK;
|
||||
|
||||
failBegin:
|
||||
AVER(!haveWhiteSegs); /* See .whiten.fail. */
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1503,21 +1509,31 @@ static Res traceCondemnAll(Trace trace)
|
|||
{
|
||||
Res res;
|
||||
Arena arena;
|
||||
Ring chainNode, nextChainNode;
|
||||
Ring poolNode, nextPoolNode, chainNode, nextChainNode;
|
||||
Bool haveWhiteSegs = FALSE;
|
||||
|
||||
arena = trace->arena;
|
||||
AVERT(Arena, arena);
|
||||
/* Condemn all the chains. */
|
||||
RING_FOR(chainNode, &arena->chainRing, nextChainNode) {
|
||||
Chain chain = RING_ELT(Chain, chainRing, chainNode);
|
||||
|
||||
AVERT(Chain, chain);
|
||||
res = ChainCondemnAll(chain, trace);
|
||||
if(res != ResOK)
|
||||
goto failBegin;
|
||||
haveWhiteSegs = TRUE;
|
||||
/* Condemn all segments in pools with the GC attribute. */
|
||||
RING_FOR(poolNode, &ArenaGlobals(arena)->poolRing, nextPoolNode) {
|
||||
Pool pool = RING_ELT(Pool, arenaRing, poolNode);
|
||||
AVERT(Pool, pool);
|
||||
|
||||
if (PoolHasAttr(pool, AttrGC)) {
|
||||
Ring segNode, nextSegNode;
|
||||
RING_FOR(segNode, PoolSegRing(pool), nextSegNode) {
|
||||
Seg seg = SegOfPoolRing(segNode);
|
||||
AVERT(Seg, seg);
|
||||
|
||||
res = TraceAddWhite(trace, seg);
|
||||
if (res != ResOK)
|
||||
goto failBegin;
|
||||
haveWhiteSegs = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Notify all the chains. */
|
||||
RING_FOR(chainNode, &arena->chainRing, nextChainNode) {
|
||||
Chain chain = RING_ELT(Chain, chainRing, chainNode);
|
||||
|
|
@ -1527,7 +1543,14 @@ static Res traceCondemnAll(Trace trace)
|
|||
return ResOK;
|
||||
|
||||
failBegin:
|
||||
AVER(!haveWhiteSegs); /* Would leave white sets inconsistent. */
|
||||
/* .whiten.fail: If we successfully whitened one or more segments,
|
||||
* but failed to whiten them all, then the white sets would now be
|
||||
* inconsistent. This can't happen in practice (at time of writing)
|
||||
* because all PoolWhiten methods always succeed. If we ever have a
|
||||
* pool class that fails to whiten a segment, then this assertion
|
||||
* will be triggered. In that case, we'll have to recover here by
|
||||
* blackening the segments again. */
|
||||
AVER(!haveWhiteSegs);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue