diff --git a/vm/factor.cpp b/vm/factor.cpp index df27de84fd..24a3e01237 100755 --- a/vm/factor.cpp +++ b/vm/factor.cpp @@ -32,7 +32,7 @@ void factor_vm::default_parameters(vm_parameters *p) p->code_size = 8 * sizeof(cell); p->young_size = sizeof(cell) / 4; p->aging_size = sizeof(cell) / 2; - p->tenured_size = 4 * sizeof(cell); + p->tenured_size = 16 * sizeof(cell); #endif p->max_pic_size = 3; diff --git a/vm/free_list_allocator.hpp b/vm/free_list_allocator.hpp index 822a40f797..d796379799 100644 --- a/vm/free_list_allocator.hpp +++ b/vm/free_list_allocator.hpp @@ -47,6 +47,7 @@ template struct free_list_allocator { void assert_free_block(free_heap_block *block); free_heap_block *find_free_block(cell size); free_heap_block *split_free_block(free_heap_block *block, cell size); + bool can_allot_p(cell size); Block *allot(cell size); void free(Block *block); void usage(cell *used, cell *total_free, cell *max_free); @@ -180,6 +181,27 @@ template free_heap_block *free_list_allocator::split_free return block; } +template bool free_list_allocator::can_allot_p(cell size) +{ + cell attempt = size; + + while(attempt < free_list_count * block_granularity) + { + int index = attempt / block_granularity; + if(free_blocks.small_blocks[index]) return true; + attempt *= 2; + } + + free_heap_block *block = free_blocks.large_blocks; + while(block) + { + if(block->size() >= size) return true; + block = block->next_free; + } + + return false; +} + template Block *free_list_allocator::allot(cell size) { size = align(size,block_granularity); diff --git a/vm/gc.cpp b/vm/gc.cpp index 1851924cd5..4b530172c1 100755 --- a/vm/gc.cpp +++ b/vm/gc.cpp @@ -115,7 +115,7 @@ void factor_vm::primitive_full_gc() gc(collect_full_op, 0, /* requested size */ true, /* trace contexts? */ - false /* compact code heap? */); + true /* compact code heap? */); } void factor_vm::primitive_compact_gc() @@ -231,7 +231,7 @@ object *factor_vm::allot_object(header header, cell size) /* If the object is smaller than the nursery, allocate it in the nursery, after a GC if needed */ - if(nursery.size > size) + if(size < nursery.size) { /* If there is insufficient room, collect the nursery */ if(nursery.here + size > nursery.end) @@ -239,23 +239,21 @@ object *factor_vm::allot_object(header header, cell size) obj = nursery.allot(size); } - /* If the object is bigger than the nursery, allocate it in - tenured space */ else { - /* If tenured space does not have enough room, collect */ - //XXX - //if(data->tenured->here + size > data->tenured->end) - primitive_full_gc(); - - /* If it still won't fit, grow the heap */ - //XXX - //if(data->tenured->here + size > data->tenured->end) + /* If tenured space does not have enough room, collect and compact */ + if(!data->tenured->can_allot_p(size)) { - gc(collect_growing_heap_op, - size, /* requested size */ - true, /* trace contexts? */ - false /* compact code heap? */); + primitive_compact_gc(); + + /* If it still won't fit, grow the heap */ + if(!data->tenured->can_allot_p(size)) + { + gc(collect_growing_heap_op, + size, /* requested size */ + true, /* trace contexts? */ + false /* compact code heap? */); + } } obj = data->tenured->allot(size); diff --git a/vm/image.cpp b/vm/image.cpp index bee351b830..2e4433d3b5 100755 --- a/vm/image.cpp +++ b/vm/image.cpp @@ -16,10 +16,7 @@ void factor_vm::init_objects(image_header *h) void factor_vm::load_data_heap(FILE *file, image_header *h, vm_parameters *p) { - cell good_size = h->data_size + (1 << 20); - - if(good_size > p->tenured_size) - p->tenured_size = good_size; + p->tenured_size = std::max((h->data_size * 3) / 2,p->tenured_size); init_data_heap(p->young_size, p->aging_size,