Make Gen-0 size semi-independent of Gen-1 minimum size.
This commit is contained in:
parent
7f55142d72
commit
632ac19adf
37
gc.c
37
gc.c
|
|
@ -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)
|
||||
{
|
||||
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
13
gc.h
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue