From 60f3cb669a2f19bedf2b8340fd8afcc7cf29d35f Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Sat, 24 Oct 2009 04:18:33 -0500 Subject: [PATCH] vm: data heap compaction work in progress --- Makefile | 1 + vm/code_block_visitor.hpp | 23 +++++----- vm/code_heap.cpp | 61 ------------------------- vm/collector.hpp | 2 +- vm/compaction.cpp | 96 +++++++++++++++++++++++++++++++++++++++ vm/compaction.hpp | 4 ++ vm/full_collector.cpp | 12 ++--- vm/gc.cpp | 6 +-- vm/master.hpp | 1 + vm/slot_visitor.hpp | 4 +- vm/vm.hpp | 11 ++--- 11 files changed, 130 insertions(+), 91 deletions(-) create mode 100644 vm/compaction.cpp create mode 100644 vm/compaction.hpp diff --git a/Makefile b/Makefile index 78f59a38bb..030a278543 100755 --- a/Makefile +++ b/Makefile @@ -41,6 +41,7 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \ vm/callstack.o \ vm/code_block.o \ vm/code_heap.o \ + vm/compaction.o \ vm/contexts.o \ vm/data_heap.o \ vm/debug.o \ diff --git a/vm/code_block_visitor.hpp b/vm/code_block_visitor.hpp index 12146a940e..9683c39db5 100644 --- a/vm/code_block_visitor.hpp +++ b/vm/code_block_visitor.hpp @@ -2,15 +2,17 @@ namespace factor { template struct call_frame_code_block_visitor { + factor_vm *parent; Visitor visitor; - explicit call_frame_code_block_visitor(Visitor visitor_) : visitor(visitor_) {} + explicit call_frame_code_block_visitor(factor_vm *parent_, Visitor visitor_) : + parent(parent_), visitor(visitor_) {} void operator()(stack_frame *frame) { cell offset = (cell)FRAME_RETURN_ADDRESS(frame,parent) - (cell)frame->xt; - code_block *new_block = visitor.visit_code_block(parent->frame_code(frame)); + code_block *new_block = visitor(parent->frame_code(frame)); frame->xt = new_block->xt(); FRAME_RETURN_ADDRESS(frame,parent) = (void *)((cell)frame->xt + offset); @@ -25,24 +27,24 @@ template void factor_vm::visit_object_code_block(object *obj, { word *w = (word *)obj; if(w->code) - w->code = visitor.visit_code_block(w->code); + w->code = visitor(w->code); if(w->profiling) - w->code = visitor.visit_code_block(w->profiling); + w->code = visitor(w->profiling); - update_word_xt(obj); + update_word_xt(w); break; } case QUOTATION_TYPE: { quotation *q = (quotation *)obj; if(q->code) - set_quot_xt(visitor.visit_code_block(q->code)); + set_quot_xt(q,visitor(q->code)); break; } case CALLSTACK_TYPE: { callstack *stack = (callstack *)obj; - call_frame_code_block_visitor call_frame_visitor(visitor); + call_frame_code_block_visitor call_frame_visitor(this,visitor); iterate_callstack_object(stack,call_frame_visitor); break; } @@ -51,8 +53,7 @@ template void factor_vm::visit_object_code_block(object *obj, template void factor_vm::visit_context_code_blocks(Visitor visitor) { - callstack *stack = (callstack *)obj; - call_frame_code_block_visitor call_frame_visitor(visitor); + call_frame_code_block_visitor call_frame_visitor(this,visitor); iterate_active_frames(call_frame_visitor); } @@ -65,14 +66,14 @@ template struct callback_code_block_visitor { void operator()(callback *stub) { - stub->compiled = visitor.visit_code_block(stub->compiled); + stub->compiled = visitor(stub->compiled); callbacks->update(stub); } }; template void factor_vm::visit_callback_code_blocks(Visitor visitor) { - callback_code_block_visitor callback_visitor(callbacks,visitor); + callback_code_block_visitor callback_visitor(callbacks,visitor); callbacks->iterate(callback_visitor); } diff --git a/vm/code_heap.cpp b/vm/code_heap.cpp index c837ec7615..ef257bb935 100755 --- a/vm/code_heap.cpp +++ b/vm/code_heap.cpp @@ -205,67 +205,6 @@ void factor_vm::primitive_code_room() dpush(tag_fixnum(max_free / 1024)); } -struct code_block_forwarder { - mark_bits *forwarding_map; - - explicit code_block_forwarder(mark_bits *forwarding_map_) : - forwarding_map(forwarding_map_) {} - - code_block *operator()(code_block *compiled) - { - return (code_block *)forwarding_map->forward_block(compiled); - } -}; - -void factor_vm::forward_object_xts() -{ - code_block_forwarder forwarder(&code->allocator->state); - - begin_scan(); - - cell obj; - - while(to_boolean(obj = next_object())) - visit_object_code_block(untag(obj),forwarder); - - end_scan(); -} - -void factor_vm::forward_context_xts() -{ - code_block_forwarder forwarder(&code->allocator->state); - visit_context_code_blocks(forwarder); -} - -void factor_vm::forward_callback_xts() -{ - code_block_forwarder forwarder(&code->allocator->state); - visit_callback_code_blocks(forwarder); -} - -/* Move all free space to the end of the code heap. Live blocks must be marked -on entry to this function. XTs in code blocks must be updated after this -function returns. */ -void factor_vm::compact_code_heap(bool trace_contexts_p) -{ - /* Figure out where blocks are going to go */ - code->allocator->state.compute_forwarding(); - - /* Update references to the code heap from the data heap */ - forward_object_xts(); - if(trace_contexts_p) - { - forward_context_xts(); - forward_callback_xts(); - } - - /* Move code blocks and update references amongst them (this requires - that the data heap is up to date since relocation looks up object XTs) */ - code_heap_relocator relocator(this); - code_heap_iterator iter(relocator); - code->allocator->compact(iter); -} - struct stack_trace_stripper { explicit stack_trace_stripper() {} diff --git a/vm/collector.hpp b/vm/collector.hpp index 6f6a5e31cd..86ae963774 100644 --- a/vm/collector.hpp +++ b/vm/collector.hpp @@ -44,7 +44,7 @@ template struct collector_workhorse return newpointer; } - object *visit_handle(object *obj) + object *visit_object(object *obj) { if(!policy.should_copy_p(obj)) { diff --git a/vm/compaction.cpp b/vm/compaction.cpp new file mode 100644 index 0000000000..b0ced6fcb0 --- /dev/null +++ b/vm/compaction.cpp @@ -0,0 +1,96 @@ +#include "master.hpp" + +namespace factor { + +struct object_slot_forwarder { + mark_bits *forwarding_map; + + explicit object_slot_forwarder(mark_bits *forwarding_map_) : + forwarding_map(forwarding_map_) {} + + object *visit_object(object *obj) + { + return forwarding_map->forward_block(obj); + } +}; + +struct code_block_forwarder { + mark_bits *forwarding_map; + + explicit code_block_forwarder(mark_bits *forwarding_map_) : + forwarding_map(forwarding_map_) {} + + code_block *operator()(code_block *compiled) + { + return (code_block *)forwarding_map->forward_block(compiled); + } +}; + +struct object_compaction_updater { + factor_vm *parent; + slot_visitor slot_forwarder; + code_block_forwarder code_forwarder; + + explicit object_compaction_updater(factor_vm *parent_, + slot_visitor slot_forwader_, + code_block_forwarder code_forwarder_) : + parent(parent_), + slot_forwarder(slot_forwader_), + code_forwarder(code_forwarder_) {} + + void operator()(object *obj, cell size) + { + slot_forwarder.visit_slots(obj); + parent->visit_object_code_block(obj,code_forwarder); + } +}; + +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_) {} + + void operator()(code_block *compiled, cell size) + { + slot_forwarder.visit_literal_references(compiled); + parent->relocate_code_block(compiled); + } +}; + +void factor_vm::compact_full_impl(bool trace_contexts_p) +{ + tenured_space *tenured = data->tenured; + mark_bits *data_forwarding_map = &tenured->state; + mark_bits *code_forwarding_map = &code->allocator->state; + + /* Figure out where blocks are going to go */ + data_forwarding_map->compute_forwarding(); + code_forwarding_map->compute_forwarding(); + + /* Update root pointers */ + slot_visitor slot_forwarder(this,object_slot_forwarder(data_forwarding_map)); + code_block_forwarder code_forwarder(code_forwarding_map); + + slot_forwarder.visit_roots(); + if(trace_contexts_p) + { + slot_forwarder.visit_contexts(); + visit_context_code_blocks(code_forwarder); + visit_callback_code_blocks(code_forwarder); + } + + /* 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); + + /* 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_heap_iterator iter(code_block_updater); + code->allocator->compact(iter); +} + +} diff --git a/vm/compaction.hpp b/vm/compaction.hpp new file mode 100644 index 0000000000..412ef35bb4 --- /dev/null +++ b/vm/compaction.hpp @@ -0,0 +1,4 @@ +namespace factor +{ + +} diff --git a/vm/full_collector.cpp b/vm/full_collector.cpp index fbffe5b33e..531b76bf31 100644 --- a/vm/full_collector.cpp +++ b/vm/full_collector.cpp @@ -85,7 +85,7 @@ void factor_vm::collect_full_impl(bool trace_contexts_p) void factor_vm::collect_growing_heap(cell requested_bytes, bool trace_contexts_p, - bool compact_code_heap_p) + bool compact_p) { /* Grow the data heap and copy all live objects to the new heap. */ data_heap *old = data; @@ -93,18 +93,18 @@ void factor_vm::collect_growing_heap(cell requested_bytes, collect_full_impl(trace_contexts_p); delete old; - if(compact_code_heap_p) - compact_code_heap(trace_contexts_p); + if(compact_p) + compact_full_impl(trace_contexts_p); else relocate_code_heap(); } -void factor_vm::collect_full(bool trace_contexts_p, bool compact_code_heap_p) +void factor_vm::collect_full(bool trace_contexts_p, bool compact_p) { collect_full_impl(trace_contexts_p); - if(compact_code_heap_p) - compact_code_heap(trace_contexts_p); + if(compact_p) + compact_full_impl(trace_contexts_p); else update_code_heap_words_and_literals(); } diff --git a/vm/gc.cpp b/vm/gc.cpp index 6b3ec80481..1851924cd5 100755 --- a/vm/gc.cpp +++ b/vm/gc.cpp @@ -28,7 +28,7 @@ void factor_vm::record_gc_stats(generation_statistics *stats) void factor_vm::gc(gc_op op, cell requested_bytes, bool trace_contexts_p, - bool compact_code_heap_p) + bool compact_p) { assert(!gc_off); assert(!current_gc); @@ -83,11 +83,11 @@ void factor_vm::gc(gc_op op, record_gc_stats(&gc_stats.aging_stats); break; case collect_full_op: - collect_full(trace_contexts_p,compact_code_heap_p); + collect_full(trace_contexts_p,compact_p); record_gc_stats(&gc_stats.full_stats); break; case collect_growing_heap_op: - collect_growing_heap(requested_bytes,trace_contexts_p,compact_code_heap_p); + collect_growing_heap(requested_bytes,trace_contexts_p,compact_p); record_gc_stats(&gc_stats.full_stats); break; default: diff --git a/vm/master.hpp b/vm/master.hpp index dc01429c30..1947c0ad50 100755 --- a/vm/master.hpp +++ b/vm/master.hpp @@ -79,6 +79,7 @@ namespace factor #include "aging_collector.hpp" #include "to_tenured_collector.hpp" #include "code_block_visitor.hpp" +#include "compaction.hpp" #include "full_collector.hpp" #include "callstack.hpp" #include "generic_arrays.hpp" diff --git a/vm/slot_visitor.hpp b/vm/slot_visitor.hpp index a62fdd87ec..6e0f6839e2 100644 --- a/vm/slot_visitor.hpp +++ b/vm/slot_visitor.hpp @@ -15,7 +15,7 @@ template struct slot_visitor { if(immediate_p(pointer)) return; object *untagged = untag(pointer); - untagged = visitor.visit_handle(untagged); + untagged = visitor.visit_object(untagged); *handle = RETAG(untagged,TAG(pointer)); } @@ -56,7 +56,7 @@ template struct slot_visitor { cell *handle = (cell *)(*iter); if(*handle) - *handle = (cell)visitor.visit_handle(*(object **)handle); + *handle = (cell)visitor.visit_object(*(object **)handle); } } diff --git a/vm/vm.hpp b/vm/vm.hpp index 674f934bba..b596b7a50c 100755 --- a/vm/vm.hpp +++ b/vm/vm.hpp @@ -249,10 +249,11 @@ struct factor_vm void collect_aging(); void collect_to_tenured(); void collect_full_impl(bool trace_contexts_p); - void collect_growing_heap(cell requested_bytes, bool trace_contexts_p, bool compact_code_heap_p); - void collect_full(bool trace_contexts_p, bool compact_code_heap_p); + void compact_full_impl(bool trace_contexts_p); + void collect_growing_heap(cell requested_bytes, bool trace_contexts_p, bool compact_p); + void collect_full(bool trace_contexts_p, bool compact_p); void record_gc_stats(generation_statistics *stats); - void gc(gc_op op, cell requested_bytes, bool trace_contexts_p, bool compact_code_heap_p); + void gc(gc_op op, cell requested_bytes, bool trace_contexts_p, bool compact_p); void primitive_minor_gc(); void primitive_full_gc(); void primitive_compact_gc(); @@ -506,10 +507,6 @@ struct factor_vm void relocate_code_heap(); void primitive_modify_code_heap(); void primitive_code_room(); - void forward_object_xts(); - void forward_context_xts(); - void forward_callback_xts(); - void compact_code_heap(bool trace_contexts_p); void primitive_strip_stack_traces(); /* Apply a function to every code block */