vm: new GC policy: mark sweep after N megabytes promoted, mark compact if tenured space cannot fit nursery+aging in one contiguous block. N = 32 on 32-bit and 64 on 64-bit

db4
Slava Pestov 2009-10-30 02:26:57 -05:00
parent a1aac42786
commit 5536003cf8
10 changed files with 67 additions and 31 deletions

View File

@ -203,8 +203,8 @@ code_heap_room factor_vm::code_room()
room.size = code->allocator->size;
room.occupied_space = code->allocator->occupied_space();
room.total_free = code->allocator->free_space();
room.contiguous_free = code->allocator->free_blocks.largest_free_block();
room.free_block_count = code->allocator->free_blocks.free_block_count;
room.contiguous_free = code->allocator->largest_free_block();
room.free_block_count = code->allocator->free_block_count();
return room;
}

View File

@ -9,7 +9,10 @@ void factor_vm::init_card_decks()
decks_offset = (cell)data->decks - addr_to_deck(data->start);
}
data_heap::data_heap(cell young_size_, cell aging_size_, cell tenured_size_)
data_heap::data_heap(cell young_size_,
cell aging_size_,
cell tenured_size_,
cell promotion_threshold_)
{
young_size_ = align(young_size_,deck_size);
aging_size_ = align(aging_size_,deck_size);
@ -18,15 +21,12 @@ data_heap::data_heap(cell young_size_, cell aging_size_, cell tenured_size_)
young_size = young_size_;
aging_size = aging_size_;
tenured_size = tenured_size_;
promotion_threshold = promotion_threshold_;
cell total_size = young_size + 2 * aging_size + tenured_size;
total_size += deck_size;
cell total_size = young_size + 2 * aging_size + tenured_size + deck_size;
seg = new segment(total_size,false);
cell cards_size = addr_to_card(total_size);
cards = new card[cards_size];
cards_end = cards + cards_size;
memset(cards,0,cards_size);
@ -62,7 +62,10 @@ data_heap::~data_heap()
data_heap *data_heap::grow(cell requested_bytes)
{
cell new_tenured_size = (tenured_size * 2) + requested_bytes;
return new data_heap(young_size,aging_size,new_tenured_size);
return new data_heap(young_size,
aging_size,
new_tenured_size,
promotion_threshold * 1.25);
}
template<typename Generation> void data_heap::clear_cards(Generation *gen)
@ -105,9 +108,9 @@ void factor_vm::set_data_heap(data_heap *data_)
init_card_decks();
}
void factor_vm::init_data_heap(cell young_size, cell aging_size, cell tenured_size)
void factor_vm::init_data_heap(cell young_size, cell aging_size, cell tenured_size, cell promotion_threshold)
{
set_data_heap(new data_heap(young_size,aging_size,tenured_size));
set_data_heap(new data_heap(young_size,aging_size,tenured_size,promotion_threshold));
}
/* Size of the object pointed to by a tagged pointer */
@ -214,8 +217,8 @@ data_heap_room factor_vm::data_room()
room.tenured_size = data->tenured->size;
room.tenured_occupied = data->tenured->occupied_space();
room.tenured_total_free = data->tenured->free_space();
room.tenured_contiguous_free = data->tenured->free_blocks.largest_free_block();
room.tenured_free_block_count = data->tenured->free_blocks.free_block_count;
room.tenured_contiguous_free = data->tenured->largest_free_block();
room.tenured_free_block_count = data->tenured->free_block_count();
room.cards = data->cards_end - data->cards;
room.decks = data->decks_end - data->decks;
room.mark_stack = data->tenured->mark_stack.capacity();

View File

@ -8,6 +8,8 @@ struct data_heap {
cell aging_size;
cell tenured_size;
cell promotion_threshold;
segment *seg;
nursery_space *nursery;
@ -21,7 +23,7 @@ struct data_heap {
card_deck *decks;
card_deck *decks_end;
explicit data_heap(cell young_size, cell aging_size, cell tenured_size);
explicit data_heap(cell young_size, cell aging_size, cell tenured_size, cell promotion_threshold);
~data_heap();
data_heap *grow(cell requested_size);
template<typename Generation> void clear_cards(Generation *gen);

View File

@ -15,25 +15,14 @@ void factor_vm::default_parameters(vm_parameters *p)
{
p->image_path = NULL;
/* We make a wild guess here that if we're running on ARM, we don't
have a lot of memory. */
#ifdef FACTOR_ARM
p->ds_size = 8 * sizeof(cell);
p->rs_size = 8 * sizeof(cell);
p->code_size = 4;
p->young_size = 1;
p->aging_size = 1;
p->tenured_size = 6;
#else
p->ds_size = 32 * sizeof(cell);
p->rs_size = 32 * sizeof(cell);
p->code_size = 8 * sizeof(cell);
p->young_size = sizeof(cell) / 4;
p->aging_size = sizeof(cell) / 2;
p->tenured_size = 16 * sizeof(cell);
#endif
p->tenured_size = 24 * sizeof(cell);
p->promotion_threshold = 8 * sizeof(cell);
p->max_pic_size = 3;
@ -81,6 +70,7 @@ void factor_vm::init_parameters_from_args(vm_parameters *p, int argc, vm_char **
else if(factor_arg(arg,STRING_LITERAL("-young=%d"),&p->young_size));
else if(factor_arg(arg,STRING_LITERAL("-aging=%d"),&p->aging_size));
else if(factor_arg(arg,STRING_LITERAL("-tenured=%d"),&p->tenured_size));
else if(factor_arg(arg,STRING_LITERAL("-promote=%d"),&p->promotion_threshold));
else if(factor_arg(arg,STRING_LITERAL("-codeheap=%d"),&p->code_size));
else if(factor_arg(arg,STRING_LITERAL("-pic=%d"),&p->max_pic_size));
else if(factor_arg(arg,STRING_LITERAL("-callbacks=%d"),&p->callback_size));
@ -114,6 +104,7 @@ void factor_vm::init_factor(vm_parameters *p)
p->young_size <<= 20;
p->aging_size <<= 20;
p->tenured_size <<= 20;
p->promotion_threshold <<= 20;
p->code_size <<= 20;
/* Disable GC during init as a sanity check */

View File

@ -46,6 +46,10 @@ free_heap_block *free_list::find_free_block(cell size)
{
free_heap_block *block = blocks.back();
blocks.pop_back();
free_block_count--;
free_space -= block->size();
return block;
}
}

View File

@ -5,6 +5,7 @@ template<typename Block> struct free_list_allocator {
cell size;
cell start;
cell end;
cell high_water_mark;
free_list free_blocks;
mark_bits<Block> state;
@ -20,6 +21,8 @@ template<typename Block> struct free_list_allocator {
void free(Block *block);
cell occupied_space();
cell free_space();
cell largest_free_block();
cell free_block_count();
void sweep();
template<typename Iterator> void sweep(Iterator &iter);
template<typename Iterator, typename Sizer> void compact(Iterator &iter, Sizer &sizer);
@ -29,7 +32,10 @@ template<typename Block> struct free_list_allocator {
template<typename Block>
free_list_allocator<Block>::free_list_allocator(cell size_, cell start_) :
size(size_), start(start_), end(start_ + size_), state(mark_bits<Block>(size_,start_))
size(size_),
start(start_),
end(start_ + size_),
state(mark_bits<Block>(size_,start_))
{
initial_free_list(0);
}
@ -37,6 +43,7 @@ free_list_allocator<Block>::free_list_allocator(cell size_, cell start_) :
template<typename Block> void free_list_allocator<Block>::initial_free_list(cell occupied)
{
free_blocks.initial_free_list(start,end,occupied);
high_water_mark = free_blocks.free_space;
}
template<typename Block> bool free_list_allocator<Block>::contains_p(Block *block)
@ -109,6 +116,16 @@ template<typename Block> cell free_list_allocator<Block>::occupied_space()
return size - free_blocks.free_space;
}
template<typename Block> cell free_list_allocator<Block>::largest_free_block()
{
return free_blocks.largest_free_block();
}
template<typename Block> cell free_list_allocator<Block>::free_block_count()
{
return free_blocks.free_block_count;
}
template<typename Block>
void free_list_allocator<Block>::sweep()
{
@ -158,6 +175,8 @@ void free_list_allocator<Block>::sweep()
if(prev && prev->free_p())
free_blocks.add_to_free_list((free_heap_block *)prev);
high_water_mark = free_blocks.free_space;
}
template<typename Block>
@ -211,6 +230,8 @@ void free_list_allocator<Block>::sweep(Iterator &iter)
if(prev && prev->free_p())
free_blocks.add_to_free_list((free_heap_block *)prev);
high_water_mark = free_blocks.free_space;
}
template<typename Block, typename Iterator> struct heap_compactor {

View File

@ -152,6 +152,19 @@ void factor_vm::gc(gc_op op, cell requested_bytes, bool trace_contexts_p)
start_gc_again();
}
if(current_gc->op == collect_aging_op
|| current_gc->op == collect_to_tenured_op
|| current_gc->op == collect_full_op)
{
if(data->tenured->largest_free_block() <= data->nursery->size + data->aging->size)
current_gc->op = collect_compact_op;
if(data->tenured->high_water_mark - data->tenured->free_space() >= data->promotion_threshold)
current_gc->op = collect_full_op;
}
current_gc->event->op = current_gc->op;
switch(current_gc->op)
{
case collect_nursery_op:
@ -316,7 +329,7 @@ void factor_vm::primitive_disable_gc_events()
{
if(gc_events)
{
byte_array *data = byte_array_from_values(&gc_events->first(),gc_events->size());
byte_array *data = byte_array_from_values(&gc_events->front(),gc_events->size());
dpush(tag<byte_array>(data));
delete gc_events;

View File

@ -20,7 +20,8 @@ void factor_vm::load_data_heap(FILE *file, image_header *h, vm_parameters *p)
init_data_heap(p->young_size,
p->aging_size,
p->tenured_size);
p->tenured_size,
p->promotion_threshold);
fixnum bytes_read = fread((void*)data->tenured->start,1,h->data_size,file);

View File

@ -33,6 +33,7 @@ struct vm_parameters {
const vm_char *executable_path;
cell ds_size, rs_size;
cell young_size, aging_size, tenured_size;
cell promotion_threshold;
cell code_size;
bool fep;
bool console;

View File

@ -218,7 +218,7 @@ struct factor_vm
//data heap
void init_card_decks();
void set_data_heap(data_heap *data_);
void init_data_heap(cell young_size, cell aging_size, cell tenured_size);
void init_data_heap(cell young_size, cell aging_size, cell tenured_size, cell promotion_threshold);
void primitive_size();
data_heap_room data_room();
void primitive_data_room();