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
parent
a1aac42786
commit
5536003cf8
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
15
vm/gc.cpp
15
vm/gc.cpp
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue