From 0c1e2663029d30242a3f5f55ac28060b27bb94ce Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sat, 24 Oct 2009 23:51:14 -0500 Subject: [PATCH] vm: got data heap compaction working --- vm/compaction.cpp | 67 ++++++++++++++++++++++++++++++++------ vm/free_list_allocator.hpp | 31 ++++++++++++++---- vm/object_start_map.cpp | 1 + vm/slot_visitor.hpp | 9 +++-- 4 files changed, 89 insertions(+), 19 deletions(-) diff --git a/vm/compaction.cpp b/vm/compaction.cpp index d29e8aa20d..05d6a186db 100644 --- a/vm/compaction.cpp +++ b/vm/compaction.cpp @@ -26,21 +26,66 @@ struct code_block_forwarder { } }; +static inline cell tuple_size_with_forwarding(mark_bits *forwarding_map, object *obj) +{ + /* The tuple layout may or may not have been forwarded already. Tricky. */ + object *layout_obj = (object *)UNTAG(((tuple *)obj)->layout); + tuple_layout *layout; + + if(layout_obj < obj) + { + /* It's already been moved up; dereference through forwarding + map to get the size */ + layout = (tuple_layout *)forwarding_map->forward_block(layout_obj); + } + else + { + /* It hasn't been moved up yet; dereference directly */ + layout = (tuple_layout *)layout_obj; + } + + return tuple_size(layout); +} + +struct compaction_sizer { + mark_bits *forwarding_map; + + explicit compaction_sizer(mark_bits *forwarding_map_) : + forwarding_map(forwarding_map_) {} + + cell operator()(object *obj) + { + if(obj->free_p() || obj->h.hi_tag() != TUPLE_TYPE) + return obj->size(); + else + return align(tuple_size_with_forwarding(forwarding_map,obj),data_alignment); + } +}; + struct object_compaction_updater { factor_vm *parent; slot_visitor slot_forwarder; code_block_visitor code_forwarder; + mark_bits *data_forwarding_map; explicit object_compaction_updater(factor_vm *parent_, - slot_visitor slot_forwader_, - code_block_visitor code_forwarder_) : + slot_visitor slot_forwarder_, + code_block_visitor code_forwarder_, + mark_bits *data_forwarding_map_) : parent(parent_), - slot_forwarder(slot_forwader_), - code_forwarder(code_forwarder_) {} + slot_forwarder(slot_forwarder_), + code_forwarder(code_forwarder_), + data_forwarding_map(data_forwarding_map_) {} void operator()(object *obj, cell size) { - slot_forwarder.visit_slots(obj); + cell payload_start; + if(obj->h.hi_tag() == TUPLE_TYPE) + payload_start = tuple_size_with_forwarding(data_forwarding_map,obj); + else + payload_start = obj->binary_payload_start(); + + slot_forwarder.visit_slots(obj,payload_start); code_forwarder.visit_object_code_block(obj); } }; @@ -49,8 +94,8 @@ struct code_block_compaction_updater { factor_vm *parent; slot_visitor slot_forwarder; - explicit code_block_compaction_updater(factor_vm *parent_, slot_visitor slot_forwader_) : - parent(parent_), slot_forwarder(slot_forwader_) {} + explicit code_block_compaction_updater(factor_vm *parent_, slot_visitor slot_forwarder_) : + parent(parent_), slot_forwarder(slot_forwarder_) {} void operator()(code_block *compiled, cell size) { @@ -83,13 +128,15 @@ void factor_vm::compact_full_impl(bool trace_contexts_p) /* Slide everything in tenured space up, and update data and code heap pointers inside objects. */ - object_compaction_updater object_updater(this,slot_forwarder,code_forwarder); - tenured->compact(object_updater); + object_compaction_updater object_updater(this,slot_forwarder,code_forwarder,data_forwarding_map); + compaction_sizer object_sizer(data_forwarding_map); + tenured->compact(object_updater,object_sizer); /* Slide everything in the code heap up, and update data and code heap pointers inside code blocks. */ code_block_compaction_updater code_block_updater(this,slot_forwarder); - code->allocator->compact(code_block_updater); + standard_sizer code_block_sizer; + code->allocator->compact(code_block_updater,code_block_sizer); } } diff --git a/vm/free_list_allocator.hpp b/vm/free_list_allocator.hpp index 01e7ea6116..0f2271beac 100644 --- a/vm/free_list_allocator.hpp +++ b/vm/free_list_allocator.hpp @@ -53,7 +53,8 @@ template struct free_list_allocator { cell occupied(); void sweep(); template void sweep(Iterator &iter); - template void compact(Iterator &iter); + template void compact(Iterator &iter, Sizer &sizer); + template void iterate(Iterator &iter, Sizer &sizer); template void iterate(Iterator &iter); }; @@ -358,31 +359,47 @@ void free_list_allocator::sweep(Iterator &iter) /* The forwarding map must be computed first by calling state.compute_forwarding(). */ template -template -void free_list_allocator::compact(Iterator &iter) +template +void free_list_allocator::compact(Iterator &iter, Sizer &sizer) { heap_compactor compactor(&state,first_block(),iter); - this->iterate(compactor); + this->iterate(compactor,sizer); /* Now update the free list; there will be a single free block at the end */ this->initial_free_list((cell)compactor.address - this->start); } +/* During compaction we have to be careful and measure object sizes differently */ template -template -void free_list_allocator::iterate(Iterator &iter) +template +void free_list_allocator::iterate(Iterator &iter, Sizer &sizer) { Block *scan = first_block(); Block *end = last_block(); while(scan != end) { - cell size = scan->size(); + cell size = sizer(scan); Block *next = (Block *)((cell)scan + size); if(!scan->free_p()) iter(scan,size); scan = next; } } +template struct standard_sizer { + cell operator()(Block *block) + { + return block->size(); + } +}; + +template +template +void free_list_allocator::iterate(Iterator &iter) +{ + standard_sizer sizer; + iterate(iter,sizer); +} + } diff --git a/vm/object_start_map.cpp b/vm/object_start_map.cpp index 5f992e783e..cb4f86c6c3 100644 --- a/vm/object_start_map.cpp +++ b/vm/object_start_map.cpp @@ -8,6 +8,7 @@ object_start_map::object_start_map(cell size_, cell start_) : { object_start_offsets = new card[addr_to_card(size_)]; object_start_offsets_end = object_start_offsets + addr_to_card(size_); + clear_object_start_offsets(); } object_start_map::~object_start_map() diff --git a/vm/slot_visitor.hpp b/vm/slot_visitor.hpp index b564949072..48fb0c1af6 100644 --- a/vm/slot_visitor.hpp +++ b/vm/slot_visitor.hpp @@ -19,10 +19,10 @@ template struct slot_visitor { *handle = RETAG(untagged,TAG(pointer)); } - void visit_slots(object *ptr) + void visit_slots(object *ptr, cell payload_start) { cell *slot = (cell *)ptr; - cell *end = (cell *)((cell)ptr + ptr->binary_payload_start()); + cell *end = (cell *)((cell)ptr + payload_start); if(slot != end) { @@ -31,6 +31,11 @@ template struct slot_visitor { } } + void visit_slots(object *ptr) + { + visit_slots(ptr,ptr->binary_payload_start()); + } + void visit_stack_elements(segment *region, cell *top) { for(cell *ptr = (cell *)region->start; ptr <= top; ptr++)