vm: remove promotion strategy, clean up compaction code
parent
7cbaf3e0a3
commit
5ae40e26ee
|
@ -39,7 +39,7 @@ template<typename TargetGeneration, typename Policy> struct collector_workhorse
|
|||
return newpointer;
|
||||
}
|
||||
|
||||
object *visit_object(object *obj)
|
||||
object *operator()(object *obj)
|
||||
{
|
||||
if(!policy.should_copy_p(obj))
|
||||
{
|
||||
|
|
|
@ -2,27 +2,15 @@
|
|||
|
||||
namespace factor {
|
||||
|
||||
struct object_slot_forwarder {
|
||||
mark_bits<object> *forwarding_map;
|
||||
template<typename Block> struct forwarder {
|
||||
mark_bits<Block> *forwarding_map;
|
||||
|
||||
explicit object_slot_forwarder(mark_bits<object> *forwarding_map_) :
|
||||
explicit forwarder(mark_bits<Block> *forwarding_map_) :
|
||||
forwarding_map(forwarding_map_) {}
|
||||
|
||||
object *visit_object(object *obj)
|
||||
Block *operator()(Block *block)
|
||||
{
|
||||
return forwarding_map->forward_block(obj);
|
||||
}
|
||||
};
|
||||
|
||||
struct code_block_forwarder {
|
||||
mark_bits<code_block> *forwarding_map;
|
||||
|
||||
explicit code_block_forwarder(mark_bits<code_block> *forwarding_map_) :
|
||||
forwarding_map(forwarding_map_) {}
|
||||
|
||||
code_block *operator()(code_block *compiled)
|
||||
{
|
||||
return forwarding_map->forward_block(compiled);
|
||||
return forwarding_map->forward_block(block);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -56,7 +44,7 @@ struct compaction_sizer {
|
|||
cell operator()(object *obj)
|
||||
{
|
||||
if(!forwarding_map->marked_p(obj))
|
||||
return forwarding_map->unmarked_space_starting_at(obj);
|
||||
return forwarding_map->unmarked_block_size(obj);
|
||||
else if(obj->h.hi_tag() == TUPLE_TYPE)
|
||||
return align(tuple_size_with_forwarding(forwarding_map,obj),data_alignment);
|
||||
else
|
||||
|
@ -66,14 +54,14 @@ struct compaction_sizer {
|
|||
|
||||
struct object_compaction_updater {
|
||||
factor_vm *parent;
|
||||
slot_visitor<object_slot_forwarder> slot_forwarder;
|
||||
code_block_visitor<code_block_forwarder> code_forwarder;
|
||||
slot_visitor<forwarder<object> > slot_forwarder;
|
||||
code_block_visitor<forwarder<code_block> > code_forwarder;
|
||||
mark_bits<object> *data_forwarding_map;
|
||||
object_start_map *starts;
|
||||
|
||||
explicit object_compaction_updater(factor_vm *parent_,
|
||||
slot_visitor<object_slot_forwarder> slot_forwarder_,
|
||||
code_block_visitor<code_block_forwarder> code_forwarder_,
|
||||
slot_visitor<forwarder<object> > slot_forwarder_,
|
||||
code_block_visitor<forwarder<code_block> > code_forwarder_,
|
||||
mark_bits<object> *data_forwarding_map_) :
|
||||
parent(parent_),
|
||||
slot_forwarder(slot_forwarder_),
|
||||
|
@ -125,9 +113,8 @@ void factor_vm::collect_compact_impl(bool trace_contexts_p)
|
|||
data_forwarding_map->compute_forwarding();
|
||||
code_forwarding_map->compute_forwarding();
|
||||
|
||||
/* Update root pointers */
|
||||
slot_visitor<object_slot_forwarder> slot_forwarder(this,object_slot_forwarder(data_forwarding_map));
|
||||
code_block_visitor<code_block_forwarder> code_forwarder(this,code_block_forwarder(code_forwarding_map));
|
||||
slot_visitor<forwarder<object> > slot_forwarder(this,forwarder<object>(data_forwarding_map));
|
||||
code_block_visitor<forwarder<code_block> > code_forwarder(this,forwarder<code_block>(code_forwarding_map));
|
||||
|
||||
/* Object start offsets get recomputed by the object_compaction_updater */
|
||||
data->tenured->starts.clear_object_start_offsets();
|
||||
|
@ -140,7 +127,7 @@ void factor_vm::collect_compact_impl(bool trace_contexts_p)
|
|||
|
||||
/* Slide everything in the code heap up, and update data and code heap
|
||||
pointers inside code blocks. */
|
||||
code_block_compaction_updater<slot_visitor<object_slot_forwarder> > code_block_updater(this,slot_forwarder);
|
||||
code_block_compaction_updater<slot_visitor<forwarder<object> > > code_block_updater(this,slot_forwarder);
|
||||
standard_sizer<code_block> code_block_sizer;
|
||||
code->allocator->compact(code_block_updater,code_block_sizer);
|
||||
|
||||
|
@ -156,14 +143,14 @@ void factor_vm::collect_compact_impl(bool trace_contexts_p)
|
|||
}
|
||||
|
||||
struct object_code_block_updater {
|
||||
code_block_visitor<code_block_forwarder> *forwarder;
|
||||
code_block_visitor<forwarder<code_block> > *visitor;
|
||||
|
||||
explicit object_code_block_updater(code_block_visitor<code_block_forwarder> *forwarder_) :
|
||||
forwarder(forwarder_) {}
|
||||
explicit object_code_block_updater(code_block_visitor<forwarder<code_block> > *visitor_) :
|
||||
visitor(visitor_) {}
|
||||
|
||||
void operator()(cell obj)
|
||||
{
|
||||
forwarder->visit_object_code_block(tagged<object>(obj).untagged());
|
||||
visitor->visit_object_code_block(tagged<object>(obj).untagged());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -180,7 +167,7 @@ void factor_vm::collect_compact_code_impl()
|
|||
code_forwarding_map->compute_forwarding();
|
||||
|
||||
/* Update root pointers */
|
||||
code_block_visitor<code_block_forwarder> code_forwarder(this,code_block_forwarder(code_forwarding_map));
|
||||
code_block_visitor<forwarder<code_block> > code_forwarder(this,forwarder<code_block>(code_forwarding_map));
|
||||
|
||||
/* Slide everything in the code heap up, and update code heap
|
||||
pointers inside code blocks. */
|
||||
|
|
|
@ -11,8 +11,7 @@ void factor_vm::init_card_decks()
|
|||
|
||||
data_heap::data_heap(cell young_size_,
|
||||
cell aging_size_,
|
||||
cell tenured_size_,
|
||||
cell promotion_threshold_)
|
||||
cell tenured_size_)
|
||||
{
|
||||
young_size_ = align(young_size_,deck_size);
|
||||
aging_size_ = align(aging_size_,deck_size);
|
||||
|
@ -21,7 +20,6 @@ data_heap::data_heap(cell young_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 + deck_size;
|
||||
seg = new segment(total_size,false);
|
||||
|
@ -64,8 +62,7 @@ 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,
|
||||
promotion_threshold * 1.25);
|
||||
new_tenured_size);
|
||||
}
|
||||
|
||||
template<typename Generation> void data_heap::clear_cards(Generation *gen)
|
||||
|
@ -108,9 +105,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, cell promotion_threshold)
|
||||
void factor_vm::init_data_heap(cell young_size, cell aging_size, cell tenured_size)
|
||||
{
|
||||
set_data_heap(new data_heap(young_size,aging_size,tenured_size,promotion_threshold));
|
||||
set_data_heap(new data_heap(young_size,aging_size,tenured_size));
|
||||
}
|
||||
|
||||
/* Size of the object pointed to by a tagged pointer */
|
||||
|
|
|
@ -8,8 +8,6 @@ struct data_heap {
|
|||
cell aging_size;
|
||||
cell tenured_size;
|
||||
|
||||
cell promotion_threshold;
|
||||
|
||||
segment *seg;
|
||||
|
||||
nursery_space *nursery;
|
||||
|
@ -23,7 +21,7 @@ struct data_heap {
|
|||
card_deck *decks;
|
||||
card_deck *decks_end;
|
||||
|
||||
explicit data_heap(cell young_size, cell aging_size, cell tenured_size, cell promotion_threshold);
|
||||
explicit data_heap(cell young_size, cell aging_size, cell tenured_size);
|
||||
~data_heap();
|
||||
data_heap *grow(cell requested_size);
|
||||
template<typename Generation> void clear_cards(Generation *gen);
|
||||
|
|
|
@ -22,7 +22,6 @@ void factor_vm::default_parameters(vm_parameters *p)
|
|||
p->young_size = sizeof(cell) / 4;
|
||||
p->aging_size = sizeof(cell) / 2;
|
||||
p->tenured_size = 24 * sizeof(cell);
|
||||
p->promotion_threshold = 8 * sizeof(cell);
|
||||
|
||||
p->max_pic_size = 3;
|
||||
|
||||
|
@ -70,7 +69,6 @@ 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));
|
||||
|
@ -104,7 +102,6 @@ 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 */
|
||||
|
|
|
@ -5,7 +5,6 @@ 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;
|
||||
|
||||
|
@ -43,7 +42,6 @@ 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)
|
||||
|
@ -131,52 +129,27 @@ void free_list_allocator<Block>::sweep()
|
|||
{
|
||||
free_blocks.clear_free_list();
|
||||
|
||||
Block *prev = NULL;
|
||||
Block *scan = this->first_block();
|
||||
Block *start = this->first_block();
|
||||
Block *end = this->last_block();
|
||||
|
||||
while(scan != end)
|
||||
while(start != end)
|
||||
{
|
||||
cell size = scan->size();
|
||||
/* find next unmarked block */
|
||||
start = state.next_unmarked_block_after(start);
|
||||
|
||||
if(start != end)
|
||||
{
|
||||
/* find size */
|
||||
cell size = state.unmarked_block_size(start);
|
||||
assert(size > 0);
|
||||
|
||||
if(scan->free_p())
|
||||
{
|
||||
if(prev && prev->free_p())
|
||||
{
|
||||
free_heap_block *free_prev = (free_heap_block *)prev;
|
||||
free_prev->make_free(free_prev->size() + size);
|
||||
}
|
||||
else
|
||||
prev = scan;
|
||||
}
|
||||
else if(this->state.marked_p(scan))
|
||||
{
|
||||
if(prev && prev->free_p())
|
||||
free_blocks.add_to_free_list((free_heap_block *)prev);
|
||||
prev = scan;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(prev && prev->free_p())
|
||||
{
|
||||
free_heap_block *free_prev = (free_heap_block *)prev;
|
||||
free_prev->make_free(free_prev->size() + size);
|
||||
}
|
||||
else
|
||||
{
|
||||
free_heap_block *free_block = (free_heap_block *)scan;
|
||||
free_block->make_free(size);
|
||||
prev = scan;
|
||||
}
|
||||
}
|
||||
free_heap_block *free_block = (free_heap_block *)start;
|
||||
free_block->make_free(size);
|
||||
free_blocks.add_to_free_list(free_block);
|
||||
|
||||
scan = (Block *)((cell)scan + size);
|
||||
start = (Block *)((char *)start + size);
|
||||
}
|
||||
}
|
||||
|
||||
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>
|
||||
|
@ -230,8 +203,6 @@ 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 {
|
||||
|
|
|
@ -20,8 +20,7 @@ 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->promotion_threshold);
|
||||
p->tenured_size);
|
||||
|
||||
fixnum bytes_read = fread((void*)data->tenured->start,1,h->data_size,file);
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@ 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;
|
||||
|
|
|
@ -60,8 +60,8 @@ template<typename Block> struct mark_bits {
|
|||
|
||||
bool bitmap_elt(u64 *bits, Block *address)
|
||||
{
|
||||
std::pair<cell,cell> pair = bitmap_deref(address);
|
||||
return (bits[pair.first] & ((u64)1 << pair.second)) != 0;
|
||||
std::pair<cell,cell> position = bitmap_deref(address);
|
||||
return (bits[position.first] & ((u64)1 << position.second)) != 0;
|
||||
}
|
||||
|
||||
Block *next_block_after(Block *block)
|
||||
|
@ -142,12 +142,12 @@ template<typename Block> struct mark_bits {
|
|||
#ifdef FACTOR_DEBUG
|
||||
assert(marked_p(original));
|
||||
#endif
|
||||
std::pair<cell,cell> pair = bitmap_deref(original);
|
||||
std::pair<cell,cell> position = bitmap_deref(original);
|
||||
|
||||
cell approx_popcount = forwarding[pair.first];
|
||||
u64 mask = ((u64)1 << pair.second) - 1;
|
||||
cell approx_popcount = forwarding[position.first];
|
||||
u64 mask = ((u64)1 << position.second) - 1;
|
||||
|
||||
cell new_line_number = approx_popcount + popcount(marked[pair.first] & mask);
|
||||
cell new_line_number = approx_popcount + popcount(marked[position.first] & mask);
|
||||
Block *new_block = line_block(new_line_number);
|
||||
#ifdef FACTOR_DEBUG
|
||||
assert(new_block <= original);
|
||||
|
@ -155,18 +155,78 @@ template<typename Block> struct mark_bits {
|
|||
return new_block;
|
||||
}
|
||||
|
||||
/* Find the next allocated block without calling size() on unmarked
|
||||
objects. */
|
||||
cell unmarked_space_starting_at(Block *original)
|
||||
cell rightmost_clear_bit(u64 x)
|
||||
{
|
||||
char *start = (char *)original;
|
||||
char *scan = start;
|
||||
cell n = 0;
|
||||
while(x & 1)
|
||||
{
|
||||
n++;
|
||||
x >>= 1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
Block *next_unmarked_block_after_slow(Block *original)
|
||||
{
|
||||
char *scan = (char *)original;
|
||||
char *end = (char *)(this->start + this->size);
|
||||
|
||||
while(scan != end && marked_p((Block *)scan))
|
||||
scan += block_granularity;
|
||||
|
||||
return (Block *)scan;
|
||||
}
|
||||
|
||||
Block *next_unmarked_block_after_fast(Block *original)
|
||||
{
|
||||
std::pair<cell,cell> position = bitmap_deref(original);
|
||||
cell bit_index = position.second;
|
||||
|
||||
for(cell index = position.first; index < bits_size; index++)
|
||||
{
|
||||
u64 mask = ((s64)marked[index] >> bit_index);
|
||||
if(~mask)
|
||||
{
|
||||
/* Found an unmarked block on this page.
|
||||
Stop, it's hammer time */
|
||||
cell clear_bit = rightmost_clear_bit(mask);
|
||||
return line_block(index * 64 + bit_index + clear_bit);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No unmarked blocks on this page.
|
||||
Keep looking */
|
||||
bit_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* No unmarked blocks were found */
|
||||
return (Block *)(this->start + this->size);
|
||||
}
|
||||
|
||||
Block *next_unmarked_block_after(Block *original)
|
||||
{
|
||||
Block *first_result = next_unmarked_block_after_slow(original);
|
||||
Block *second_result = next_unmarked_block_after_fast(original);
|
||||
assert(first_result == second_result);
|
||||
return second_result;
|
||||
}
|
||||
|
||||
Block *next_marked_block_after(Block *original)
|
||||
{
|
||||
char *scan = (char *)original;
|
||||
char *end = (char *)(this->start + this->size);
|
||||
|
||||
while(scan != end && !marked_p((Block *)scan))
|
||||
scan += block_granularity;
|
||||
|
||||
return scan - start;
|
||||
return (Block *)scan;
|
||||
}
|
||||
|
||||
cell unmarked_block_size(Block *original)
|
||||
{
|
||||
Block *next_marked = next_marked_block_after(original);
|
||||
return ((char *)next_marked - (char *)original);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ template<typename Visitor> struct slot_visitor {
|
|||
if(immediate_p(pointer)) return;
|
||||
|
||||
object *untagged = untag<object>(pointer);
|
||||
untagged = visitor.visit_object(untagged);
|
||||
untagged = visitor(untagged);
|
||||
*handle = RETAG(untagged,TAG(pointer));
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ template<typename Visitor> struct slot_visitor {
|
|||
cell *handle = (cell *)(*iter);
|
||||
|
||||
if(*handle)
|
||||
*handle = (cell)visitor.visit_object(*(object **)handle);
|
||||
*handle = (cell)visitor(*(object **)handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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, cell promotion_threshold);
|
||||
void init_data_heap(cell young_size, cell aging_size, cell tenured_size);
|
||||
void primitive_size();
|
||||
data_heap_room data_room();
|
||||
void primitive_data_room();
|
||||
|
@ -351,8 +351,8 @@ struct factor_vm
|
|||
void primitive_uninitialized_byte_array();
|
||||
void primitive_resize_byte_array();
|
||||
|
||||
template<typename T> byte_array *byte_array_from_value(T *value);
|
||||
template<typename T> byte_array *byte_array_from_values(T *values, cell len);
|
||||
template<typename Type> byte_array *byte_array_from_value(Type *value);
|
||||
template<typename Type> byte_array *byte_array_from_values(Type *values, cell len);
|
||||
|
||||
//tuples
|
||||
void primitive_tuple();
|
||||
|
|
Loading…
Reference in New Issue