From ac25b8ebbbd7d2c40882480a38bda89b6e531deb Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Mon, 19 Oct 2009 02:21:11 -0500 Subject: [PATCH] vm: new mark_bits data structure replaces hashtable when compacting code heap --- vm/code_block.cpp | 2 +- vm/code_heap.cpp | 47 ++++++++++++++++++++++++++++++++++++++----- vm/factor.cpp | 2 +- vm/full_collector.cpp | 44 ++-------------------------------------- vm/heap.cpp | 2 -- vm/heap.hpp | 7 +++---- vm/mach_signal.cpp | 2 +- vm/mark_bits.hpp | 24 ++++------------------ vm/master.hpp | 19 +---------------- vm/vm.hpp | 6 ++++-- 10 files changed, 59 insertions(+), 96 deletions(-) diff --git a/vm/code_block.cpp b/vm/code_block.cpp index 1f77148b5c..d2337d71de 100755 --- a/vm/code_block.cpp +++ b/vm/code_block.cpp @@ -379,7 +379,7 @@ struct literal_and_word_references_updater { } }; -void factor_vm::update_code_block_for_full_gc(code_block *compiled) +void factor_vm::update_code_block_words_and_literals(code_block *compiled) { if(code->needs_fixup_p(compiled)) relocate_code_block(compiled); diff --git a/vm/code_heap.cpp b/vm/code_heap.cpp index b058248bee..020c8c2ba8 100755 --- a/vm/code_heap.cpp +++ b/vm/code_heap.cpp @@ -73,6 +73,44 @@ void factor_vm::update_code_heap_words() iterate_code_heap(updater); } +/* After a full GC that did not grow the heap, we have to update references +to literals and other words. */ +struct word_and_literal_code_heap_updater { + factor_vm *parent; + + word_and_literal_code_heap_updater(factor_vm *parent_) : parent(parent_) {} + + void operator()(heap_block *block) + { + parent->update_code_block_words_and_literals((code_block *)block); + } +}; + +void factor_vm::update_code_heap_words_and_literals() +{ + word_and_literal_code_heap_updater updater(this); + code->sweep_heap(updater); +} + +/* After growing the heap, we have to perform a full relocation to update +references to card and deck arrays. */ +struct code_heap_relocator { + factor_vm *parent; + + code_heap_relocator(factor_vm *parent_) : parent(parent_) {} + + void operator()(heap_block *block) + { + parent->relocate_code_block((code_block *)block); + } +}; + +void factor_vm::relocate_code_heap() +{ + code_heap_relocator relocator(this); + code->sweep_heap(relocator); +} + void factor_vm::primitive_modify_code_heap() { gc_root alist(dpop(),this); @@ -139,11 +177,7 @@ void factor_vm::primitive_code_room() code_block *code_heap::forward_code_block(code_block *compiled) { - code_block *block1 = (code_block *)state->forward_block(compiled); - code_block *block2 = (code_block *)forwarding[compiled]; - printf("%lx %lx\n",block1,block2); - assert(block1 == block2); - return block2; + return (code_block *)state->forward_block(compiled); } struct callframe_forwarder { @@ -248,6 +282,9 @@ void factor_vm::compact_code_heap(bool trace_contexts_p) forward_context_xts(); forward_callback_xts(); } + + code_heap_relocator relocator(this); + iterate_code_heap(relocator); } struct stack_trace_stripper { diff --git a/vm/factor.cpp b/vm/factor.cpp index 5548ebd610..f2b0d4c92a 100755 --- a/vm/factor.cpp +++ b/vm/factor.cpp @@ -4,7 +4,7 @@ namespace factor { factor_vm *vm; -unordered_map thread_vms; +std::map thread_vms; void init_globals() { diff --git a/vm/full_collector.cpp b/vm/full_collector.cpp index f9db1c8653..61827fba41 100644 --- a/vm/full_collector.cpp +++ b/vm/full_collector.cpp @@ -104,32 +104,6 @@ void full_collector::cheneys_algorithm() } } -/* After growing the heap, we have to perform a full relocation to update -references to card and deck arrays. */ -struct big_code_heap_updater { - factor_vm *parent; - - big_code_heap_updater(factor_vm *parent_) : parent(parent_) {} - - void operator()(heap_block *block) - { - parent->relocate_code_block((code_block *)block); - } -}; - -/* After a full GC that did not grow the heap, we have to update references -to literals and other words. */ -struct small_code_heap_updater { - factor_vm *parent; - - small_code_heap_updater(factor_vm *parent_) : parent(parent_) {} - - void operator()(heap_block *block) - { - parent->update_code_block_for_full_gc((code_block *)block); - } -}; - void factor_vm::collect_full_impl(bool trace_contexts_p) { full_collector collector(this); @@ -161,16 +135,9 @@ void factor_vm::collect_growing_heap(cell requested_bytes, delete old; if(compact_code_heap_p) - { compact_code_heap(trace_contexts_p); - big_code_heap_updater updater(this); - iterate_code_heap(updater); - } else - { - big_code_heap_updater updater(this); - code->free_unmarked(updater); - } + relocate_code_heap(); code->clear_remembered_set(); } @@ -183,16 +150,9 @@ void factor_vm::collect_full(bool trace_contexts_p, bool compact_code_heap_p) collect_full_impl(trace_contexts_p); if(compact_code_heap_p) - { compact_code_heap(trace_contexts_p); - big_code_heap_updater updater(this); - iterate_code_heap(updater); - } else - { - small_code_heap_updater updater(this); - code->free_unmarked(updater); - } + update_code_heap_words_and_literals(); code->clear_remembered_set(); } diff --git a/vm/heap.cpp b/vm/heap.cpp index 8cbf914130..c2a44e42a4 100644 --- a/vm/heap.cpp +++ b/vm/heap.cpp @@ -191,7 +191,6 @@ cell heap::heap_size() void heap::compact_heap() { - forwarding.clear(); state->compute_forwarding(); heap_block *scan = first_block(); @@ -208,7 +207,6 @@ void heap::compact_heap() { cell size = scan->size(); memmove(address,scan,size); - forwarding[scan] = address; address += size; } diff --git a/vm/heap.hpp b/vm/heap.hpp index 8575dac2a1..ba00b9ba6c 100644 --- a/vm/heap.hpp +++ b/vm/heap.hpp @@ -14,7 +14,6 @@ struct heap { segment *seg; heap_free_list free; mark_bits *state; - unordered_map forwarding; explicit heap(bool secure_gc_, cell size, bool executable_p); ~heap(); @@ -45,9 +44,9 @@ struct heap { heap_block *free_allocated(heap_block *prev, heap_block *scan); - /* After code GC, all referenced code blocks have status set to B_MARKED, so any - which are allocated and not marked can be reclaimed. */ - template void free_unmarked(Iterator &iter) + /* After code GC, all live code blocks are marked, so any + which are not marked can be reclaimed. */ + template void sweep_heap(Iterator &iter) { clear_free_list(); diff --git a/vm/mach_signal.cpp b/vm/mach_signal.cpp index 2d76b12c38..d733e6b3bc 100644 --- a/vm/mach_signal.cpp +++ b/vm/mach_signal.cpp @@ -78,7 +78,7 @@ static void call_fault_handler( { THREADHANDLE thread_id = pthread_from_mach_thread_np(thread); assert(thread_id); - unordered_map::const_iterator vm = thread_vms.find(thread_id); + std::map::const_iterator vm = thread_vms.find(thread_id); if (vm != thread_vms.end()) vm->second->call_fault_handler(exception,code,exc_state,thread_state,float_state); } diff --git a/vm/mark_bits.hpp b/vm/mark_bits.hpp index b13f6889bd..f123701816 100644 --- a/vm/mark_bits.hpp +++ b/vm/mark_bits.hpp @@ -92,11 +92,8 @@ template struct mark_bits { { bits[start.first] |= ~start_mask; - if(end.first != 0) - { - for(cell index = start.first + 1; index < end.first - 1; index++) - bits[index] = (u64)-1; - } + for(cell index = start.first + 1; index < end.first; index++) + bits[index] = (u64)-1; bits[end.first] |= end_mask; } @@ -122,21 +119,9 @@ template struct mark_bits { set_bitmap_range(allocated,address); } - cell popcount1(u64 x) - { - cell accum = 0; - while(x > 0) - { - accum += (x & 1); - x >>= 1; - } - return accum; - } - /* From http://chessprogramming.wikispaces.com/Population+Count */ cell popcount(u64 x) { - cell old = x; u64 k1 = 0x5555555555555555ll; u64 k2 = 0x3333333333333333ll; u64 k4 = 0x0f0f0f0f0f0f0f0fll; @@ -145,13 +130,12 @@ template struct mark_bits { x = (x & k2) + ((x >> 2) & k2); // put count of each 4 bits into those 4 bits x = (x + (x >> 4)) & k4 ; // put count of each 8 bits into those 8 bits x = (x * kf) >> 56; // returns 8 most significant bits of x + (x<<8) + (x<<16) + (x<<24) + ... - - assert(x == popcount1(old)); + return (cell)x; } /* The eventual destination of a block after compaction is just the number - of marked blocks before it. */ + of marked blocks before it. Live blocks must be marked on entry. */ void compute_forwarding() { cell accum = 0; diff --git a/vm/master.hpp b/vm/master.hpp index 847980fac6..b0e73a4b29 100755 --- a/vm/master.hpp +++ b/vm/master.hpp @@ -25,27 +25,10 @@ /* C++ headers */ #include +#include #include #include -#if __GNUC__ == 4 - #include - - namespace factor - { - using std::tr1::unordered_map; - } -#elif __GNUC__ == 3 - #include - - namespace factor - { - using boost::unordered_map; - } -#else - #error Factor requires GCC 3.x or later -#endif - /* Forward-declare this since it comes up in function prototypes */ namespace factor { diff --git a/vm/vm.hpp b/vm/vm.hpp index a5cb2562d1..7742ea8d60 100755 --- a/vm/vm.hpp +++ b/vm/vm.hpp @@ -494,7 +494,7 @@ struct factor_vm void update_literal_references(code_block *compiled); void relocate_code_block_step(relocation_entry rel, cell index, code_block *compiled); void update_word_references(code_block *compiled); - void update_code_block_for_full_gc(code_block *compiled); + void update_code_block_words_and_literals(code_block *compiled); void check_code_address(cell address); void relocate_code_block(code_block *compiled); void fixup_labels(array *labels, code_block *compiled); @@ -513,6 +513,8 @@ struct factor_vm bool in_code_heap_p(cell ptr); void jit_compile_word(cell word_, cell def_, bool relocate); void update_code_heap_words(); + void update_code_heap_words_and_literals(); + void relocate_code_heap(); void primitive_modify_code_heap(); void primitive_code_room(); void forward_object_xts(); @@ -711,6 +713,6 @@ struct factor_vm }; -extern unordered_map thread_vms; +extern std::map thread_vms; }