vm: new mark_bits data structure replaces hashtable when compacting code heap

db4
Slava Pestov 2009-10-19 02:21:11 -05:00
parent 464aac14cf
commit ac25b8ebbb
10 changed files with 59 additions and 96 deletions

View File

@ -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);

View File

@ -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<array> 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 {

View File

@ -4,7 +4,7 @@ namespace factor
{
factor_vm *vm;
unordered_map<THREADHANDLE, factor_vm*> thread_vms;
std::map<THREADHANDLE, factor_vm*> thread_vms;
void init_globals()
{

View File

@ -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();
}

View File

@ -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;
}

View File

@ -14,7 +14,6 @@ struct heap {
segment *seg;
heap_free_list free;
mark_bits<heap_block,block_size_increment> *state;
unordered_map<heap_block *, char *> 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<typename Iterator> void free_unmarked(Iterator &iter)
/* After code GC, all live code blocks are marked, so any
which are not marked can be reclaimed. */
template<typename Iterator> void sweep_heap(Iterator &iter)
{
clear_free_list();

View File

@ -78,7 +78,7 @@ static void call_fault_handler(
{
THREADHANDLE thread_id = pthread_from_mach_thread_np(thread);
assert(thread_id);
unordered_map<THREADHANDLE, factor_vm*>::const_iterator vm = thread_vms.find(thread_id);
std::map<THREADHANDLE, factor_vm*>::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);
}

View File

@ -92,11 +92,8 @@ template<typename Block, int Granularity> 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<typename Block, int Granularity> 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;
@ -146,12 +131,11 @@ template<typename Block, int Granularity> struct mark_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;

View File

@ -25,27 +25,10 @@
/* C++ headers */
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#if __GNUC__ == 4
#include <tr1/unordered_map>
namespace factor
{
using std::tr1::unordered_map;
}
#elif __GNUC__ == 3
#include <boost/unordered_map.hpp>
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
{

View File

@ -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<THREADHANDLE, factor_vm *> thread_vms;
extern std::map<THREADHANDLE, factor_vm *> thread_vms;
}