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.size = code->allocator->size;
|
||||||
room.occupied_space = code->allocator->occupied_space();
|
room.occupied_space = code->allocator->occupied_space();
|
||||||
room.total_free = code->allocator->free_space();
|
room.total_free = code->allocator->free_space();
|
||||||
room.contiguous_free = code->allocator->free_blocks.largest_free_block();
|
room.contiguous_free = code->allocator->largest_free_block();
|
||||||
room.free_block_count = code->allocator->free_blocks.free_block_count;
|
room.free_block_count = code->allocator->free_block_count();
|
||||||
|
|
||||||
return room;
|
return room;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,10 @@ void factor_vm::init_card_decks()
|
||||||
decks_offset = (cell)data->decks - addr_to_deck(data->start);
|
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);
|
young_size_ = align(young_size_,deck_size);
|
||||||
aging_size_ = align(aging_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_;
|
young_size = young_size_;
|
||||||
aging_size = aging_size_;
|
aging_size = aging_size_;
|
||||||
tenured_size = tenured_size_;
|
tenured_size = tenured_size_;
|
||||||
|
promotion_threshold = promotion_threshold_;
|
||||||
|
|
||||||
cell total_size = young_size + 2 * aging_size + tenured_size;
|
cell total_size = young_size + 2 * aging_size + tenured_size + deck_size;
|
||||||
|
|
||||||
total_size += deck_size;
|
|
||||||
|
|
||||||
seg = new segment(total_size,false);
|
seg = new segment(total_size,false);
|
||||||
|
|
||||||
cell cards_size = addr_to_card(total_size);
|
cell cards_size = addr_to_card(total_size);
|
||||||
|
|
||||||
cards = new card[cards_size];
|
cards = new card[cards_size];
|
||||||
cards_end = cards + cards_size;
|
cards_end = cards + cards_size;
|
||||||
memset(cards,0,cards_size);
|
memset(cards,0,cards_size);
|
||||||
|
@ -62,7 +62,10 @@ data_heap::~data_heap()
|
||||||
data_heap *data_heap::grow(cell requested_bytes)
|
data_heap *data_heap::grow(cell requested_bytes)
|
||||||
{
|
{
|
||||||
cell new_tenured_size = (tenured_size * 2) + 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)
|
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();
|
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 */
|
/* 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_size = data->tenured->size;
|
||||||
room.tenured_occupied = data->tenured->occupied_space();
|
room.tenured_occupied = data->tenured->occupied_space();
|
||||||
room.tenured_total_free = data->tenured->free_space();
|
room.tenured_total_free = data->tenured->free_space();
|
||||||
room.tenured_contiguous_free = data->tenured->free_blocks.largest_free_block();
|
room.tenured_contiguous_free = data->tenured->largest_free_block();
|
||||||
room.tenured_free_block_count = data->tenured->free_blocks.free_block_count;
|
room.tenured_free_block_count = data->tenured->free_block_count();
|
||||||
room.cards = data->cards_end - data->cards;
|
room.cards = data->cards_end - data->cards;
|
||||||
room.decks = data->decks_end - data->decks;
|
room.decks = data->decks_end - data->decks;
|
||||||
room.mark_stack = data->tenured->mark_stack.capacity();
|
room.mark_stack = data->tenured->mark_stack.capacity();
|
||||||
|
|
|
@ -8,6 +8,8 @@ struct data_heap {
|
||||||
cell aging_size;
|
cell aging_size;
|
||||||
cell tenured_size;
|
cell tenured_size;
|
||||||
|
|
||||||
|
cell promotion_threshold;
|
||||||
|
|
||||||
segment *seg;
|
segment *seg;
|
||||||
|
|
||||||
nursery_space *nursery;
|
nursery_space *nursery;
|
||||||
|
@ -21,7 +23,7 @@ struct data_heap {
|
||||||
card_deck *decks;
|
card_deck *decks;
|
||||||
card_deck *decks_end;
|
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();
|
||||||
data_heap *grow(cell requested_size);
|
data_heap *grow(cell requested_size);
|
||||||
template<typename Generation> void clear_cards(Generation *gen);
|
template<typename Generation> void clear_cards(Generation *gen);
|
||||||
|
|
|
@ -15,25 +15,14 @@ void factor_vm::default_parameters(vm_parameters *p)
|
||||||
{
|
{
|
||||||
p->image_path = NULL;
|
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->ds_size = 32 * sizeof(cell);
|
||||||
p->rs_size = 32 * sizeof(cell);
|
p->rs_size = 32 * sizeof(cell);
|
||||||
|
|
||||||
p->code_size = 8 * sizeof(cell);
|
p->code_size = 8 * sizeof(cell);
|
||||||
p->young_size = sizeof(cell) / 4;
|
p->young_size = sizeof(cell) / 4;
|
||||||
p->aging_size = sizeof(cell) / 2;
|
p->aging_size = sizeof(cell) / 2;
|
||||||
p->tenured_size = 16 * sizeof(cell);
|
p->tenured_size = 24 * sizeof(cell);
|
||||||
#endif
|
p->promotion_threshold = 8 * sizeof(cell);
|
||||||
|
|
||||||
p->max_pic_size = 3;
|
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("-young=%d"),&p->young_size));
|
||||||
else if(factor_arg(arg,STRING_LITERAL("-aging=%d"),&p->aging_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("-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("-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("-pic=%d"),&p->max_pic_size));
|
||||||
else if(factor_arg(arg,STRING_LITERAL("-callbacks=%d"),&p->callback_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->young_size <<= 20;
|
||||||
p->aging_size <<= 20;
|
p->aging_size <<= 20;
|
||||||
p->tenured_size <<= 20;
|
p->tenured_size <<= 20;
|
||||||
|
p->promotion_threshold <<= 20;
|
||||||
p->code_size <<= 20;
|
p->code_size <<= 20;
|
||||||
|
|
||||||
/* Disable GC during init as a sanity check */
|
/* 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();
|
free_heap_block *block = blocks.back();
|
||||||
blocks.pop_back();
|
blocks.pop_back();
|
||||||
|
|
||||||
|
free_block_count--;
|
||||||
|
free_space -= block->size();
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ template<typename Block> struct free_list_allocator {
|
||||||
cell size;
|
cell size;
|
||||||
cell start;
|
cell start;
|
||||||
cell end;
|
cell end;
|
||||||
|
cell high_water_mark;
|
||||||
free_list free_blocks;
|
free_list free_blocks;
|
||||||
mark_bits<Block> state;
|
mark_bits<Block> state;
|
||||||
|
|
||||||
|
@ -20,6 +21,8 @@ template<typename Block> struct free_list_allocator {
|
||||||
void free(Block *block);
|
void free(Block *block);
|
||||||
cell occupied_space();
|
cell occupied_space();
|
||||||
cell free_space();
|
cell free_space();
|
||||||
|
cell largest_free_block();
|
||||||
|
cell free_block_count();
|
||||||
void sweep();
|
void sweep();
|
||||||
template<typename Iterator> void sweep(Iterator &iter);
|
template<typename Iterator> void sweep(Iterator &iter);
|
||||||
template<typename Iterator, typename Sizer> void compact(Iterator &iter, Sizer &sizer);
|
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>
|
template<typename Block>
|
||||||
free_list_allocator<Block>::free_list_allocator(cell size_, cell start_) :
|
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);
|
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)
|
template<typename Block> void free_list_allocator<Block>::initial_free_list(cell occupied)
|
||||||
{
|
{
|
||||||
free_blocks.initial_free_list(start,end,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)
|
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;
|
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>
|
template<typename Block>
|
||||||
void free_list_allocator<Block>::sweep()
|
void free_list_allocator<Block>::sweep()
|
||||||
{
|
{
|
||||||
|
@ -158,6 +175,8 @@ void free_list_allocator<Block>::sweep()
|
||||||
|
|
||||||
if(prev && prev->free_p())
|
if(prev && prev->free_p())
|
||||||
free_blocks.add_to_free_list((free_heap_block *)prev);
|
free_blocks.add_to_free_list((free_heap_block *)prev);
|
||||||
|
|
||||||
|
high_water_mark = free_blocks.free_space;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Block>
|
template<typename Block>
|
||||||
|
@ -211,6 +230,8 @@ void free_list_allocator<Block>::sweep(Iterator &iter)
|
||||||
|
|
||||||
if(prev && prev->free_p())
|
if(prev && prev->free_p())
|
||||||
free_blocks.add_to_free_list((free_heap_block *)prev);
|
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 {
|
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();
|
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)
|
switch(current_gc->op)
|
||||||
{
|
{
|
||||||
case collect_nursery_op:
|
case collect_nursery_op:
|
||||||
|
@ -316,7 +329,7 @@ void factor_vm::primitive_disable_gc_events()
|
||||||
{
|
{
|
||||||
if(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));
|
dpush(tag<byte_array>(data));
|
||||||
|
|
||||||
delete gc_events;
|
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,
|
init_data_heap(p->young_size,
|
||||||
p->aging_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);
|
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;
|
const vm_char *executable_path;
|
||||||
cell ds_size, rs_size;
|
cell ds_size, rs_size;
|
||||||
cell young_size, aging_size, tenured_size;
|
cell young_size, aging_size, tenured_size;
|
||||||
|
cell promotion_threshold;
|
||||||
cell code_size;
|
cell code_size;
|
||||||
bool fep;
|
bool fep;
|
||||||
bool console;
|
bool console;
|
||||||
|
|
|
@ -218,7 +218,7 @@ struct factor_vm
|
||||||
//data heap
|
//data heap
|
||||||
void init_card_decks();
|
void init_card_decks();
|
||||||
void set_data_heap(data_heap *data_);
|
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();
|
void primitive_size();
|
||||||
data_heap_room data_room();
|
data_heap_room data_room();
|
||||||
void primitive_data_room();
|
void primitive_data_room();
|
||||||
|
|
Loading…
Reference in New Issue