Make Gen-0 size semi-independent of Gen-1 minimum size.

This commit is contained in:
Jesse D. McDonald 2010-04-10 03:14:58 -05:00
parent 7f55142d72
commit 632ac19adf
2 changed files with 37 additions and 19 deletions

43
gc.c
View File

@ -387,10 +387,10 @@ static inline size_t gc_align(size_t nbytes)
return ((nbytes + GC_ALIGNMENT - 1) & ~(GC_ALIGNMENT - 1));
}
void gc_init(size_t min_size, size_t max_size)
void gc_init(size_t gen0_size, size_t gen1_min_size, size_t gen1_max_size)
{
gc_gen0_init(min_size);
gc_gen1_init(min_size, max_size);
gc_gen0_init(gen0_size);
gc_gen1_init(gen1_min_size, gen1_max_size);
gc_weak_box_list = NIL;
gc_will_list = NIL;
@ -426,10 +426,10 @@ static void gc_poison_region(void *start, size_t size, value_t tag)
/* These private variables are exported ONLY for use by is_gen0_object(). */
char *gc_gen0_range;
size_t gc_gen0_size;
char *gc_gen0_range_end;
static size_t gc_gen0_size;
static char *gc_gen0_free_ptr;
static char *gc_gen0_range_end;
/* Used to signal that Gen-0 pass has been obviated by Gen-1 collection. */
static jmp_buf gc_gen0_end_ctx;
@ -455,6 +455,10 @@ static void collect_gen0_garbage(void)
{
if (gc_enabled)
{
#ifndef NDEBUG
size_t initial_gen1_free_space;
#endif
#ifndef NO_STATS
size_t initial_free_space;
#ifndef NO_TIMING_STATS
@ -469,6 +473,10 @@ static void collect_gen0_garbage(void)
assert(!gc_in_gen0_collection);
assert(!gc_in_gen1_collection);
#ifndef NDEBUG
initial_gen1_free_space = gc_gen1_free_space();
#endif
/* If we trigger a Gen-1 collection at any point then we are done. */
/* Full collection will pull in any current Gen-0 objects. */
if (setjmp(gc_gen0_end_ctx) == 0)
@ -548,6 +556,8 @@ static void collect_gen0_garbage(void)
/* 4. Reset Gen-0 range to 'empty' state. */
gc_gen0_free_ptr = gc_gen0_range;
//debug(("Finished Gen-0 collection; added %d bytes to Gen-1 heap.\n", initial_gen1_free_space - gc_gen1_free_space()));
#ifndef NO_STATS
#ifndef NO_TIMING_STATS
{
@ -644,7 +654,9 @@ static inline bool gc_object_left_behind(value_t v)
static void gc_gen1_init(size_t min_size, size_t max_size)
{
release_assert(min_size <= ((max_size+1)/2));
release_assert(gc_gen0_size > 0);
release_assert(max_size >= gc_gen0_size);
release_assert(min_size <= (max_size - gc_gen0_size));
gc_gen1_ranges[0] = (char*)malloc(max_size);
gc_gen1_ranges[1] = (char*)malloc(max_size);
@ -656,7 +668,7 @@ static void gc_gen1_init(size_t min_size, size_t max_size)
gc_gen1_min_size = min_size;
gc_gen1_max_size = max_size;
gc_gen1_soft_limit = 2*min_size;
gc_gen1_soft_limit = min_size + gc_gen0_size;
gc_gen1_range_end = gc_gen1_free_ptr + gc_gen1_soft_limit;
gc_gen1_max_blocks = ((size_t)2 << 30) / GC_DIRTY_BLOCK_SIZE;
@ -670,7 +682,8 @@ static void gc_gen1_init(size_t min_size, size_t max_size)
static void gc_gen1_clear_dirty_bits(void)
{
memset(gc_gen1_dirty_bits, 0, sizeof(uint32_t) * ((gc_gen1_max_blocks + 31) / 32));
const size_t block_groups = (gc_gen1_max_blocks + 31) / 32;
memset(gc_gen1_dirty_bits, 0, sizeof(uint32_t) * block_groups);
}
static void *gc_alloc_gen1(size_t nbytes)
@ -679,11 +692,12 @@ static void *gc_alloc_gen1(size_t nbytes)
min_free = nbytes = gc_align(nbytes);
/* Ensure there is always enough room for a full collection. */
if (!gc_in_gen1_collection)
min_free += gc_gen0_size;
if (gc_gen1_free_space() < min_free)
collect_gen1_garbage(nbytes);
collect_gen1_garbage(min_free);
assert(nbytes <= gc_gen1_free_space());
@ -1030,9 +1044,12 @@ static size_t gc_gen1_block_of(void *obj)
void _gc_mark_updated_gen1_object(value_t v)
{
const size_t block = gc_gen1_block_of(_get_object(v));
assert(is_object(v) && !is_gen0_object(v) && gc_gen1_block_starts[block]);
gc_gen1_dirty_bits[block / 32] |= (1UL << (block % 32));
assert(is_object(v));
{
const size_t block = gc_gen1_block_of(_get_object(v));
assert(is_object(v) && !is_gen0_object(v) && gc_gen1_block_starts[block]);
gc_gen1_dirty_bits[block / 32] |= (1UL << (block % 32));
}
}
static void _out_of_memory(void) __attribute__ ((noreturn));
@ -1120,7 +1137,7 @@ static void collect_gen1_garbage(size_t min_free)
gc_gen0_free_ptr = gc_gen0_range;
collected_garbage = true;
//debug(("Finished collection with %d bytes to spare (out of %d bytes).\n", gc_gen1_free_space(), gc_gen1_soft_limit));
//debug(("Finished Gen-1 collection; active set is %d bytes.\n", gc_gen1_free_ptr - gc_gen1_ranges[gc_gen1_current_range]));
gc_in_gen1_collection = false;
gc_enabled = true;

13
gc.h
View File

@ -388,7 +388,7 @@ static inline builtin_fn_t *_get_builtin_fn(value_t v)
return ((builtin_fn_object_t*)_get_object(v))->fn;
}
void gc_init(size_t min_size, size_t max_size);
void gc_init(size_t gen0_size, size_t gen1_min_size, size_t gen1_max_size);
void clear_gc_stats(void);
void register_gc_root(gc_root_t *root, value_t v);
void unregister_gc_root(gc_root_t *root);
@ -414,18 +414,19 @@ static inline bool is_gen0_object(value_t v)
{
/* These private variables are exported ONLY for use by this inline function. */
extern char *gc_gen0_range;
extern size_t gc_gen0_size;
extern char *gc_gen0_range_end;
const char const *obj = (const char*)_get_object(v);
return is_object(v)
&& (obj >= (char*)gc_gen0_range)
&& ((obj - (char*)gc_gen0_range) < gc_gen0_size);
return (obj < gc_gen0_range_end)
&& (obj >= gc_gen0_range)
&& is_object(v);
}
/* Don't call this directly; use the WRITE_BARRIER macro. */
static inline void _gc_write_barrier(value_t v)
{
if (is_object(v) && !is_gen0_object(v))
assert(is_object(v));
if (!is_gen0_object(v))
{
_gc_mark_updated_gen1_object(v);
}