vm: move compaction algorithm to mark_bits.hpp since it doesn't rely on properties of heaps per se
parent
ac25b8ebbb
commit
4ddd63d83e
|
@ -59,7 +59,7 @@ struct word_updater {
|
|||
factor_vm *parent;
|
||||
|
||||
explicit word_updater(factor_vm *parent_) : parent(parent_) {}
|
||||
void operator()(code_block *compiled)
|
||||
void operator()(code_block *compiled, cell size)
|
||||
{
|
||||
parent->update_word_references(compiled);
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ struct word_and_literal_code_heap_updater {
|
|||
|
||||
word_and_literal_code_heap_updater(factor_vm *parent_) : parent(parent_) {}
|
||||
|
||||
void operator()(heap_block *block)
|
||||
void operator()(heap_block *block, cell size)
|
||||
{
|
||||
parent->update_code_block_words_and_literals((code_block *)block);
|
||||
}
|
||||
|
@ -99,16 +99,17 @@ struct code_heap_relocator {
|
|||
|
||||
code_heap_relocator(factor_vm *parent_) : parent(parent_) {}
|
||||
|
||||
void operator()(heap_block *block)
|
||||
void operator()(code_block *block, cell size)
|
||||
{
|
||||
parent->relocate_code_block((code_block *)block);
|
||||
parent->relocate_code_block(block);
|
||||
}
|
||||
};
|
||||
|
||||
void factor_vm::relocate_code_heap()
|
||||
{
|
||||
code_heap_relocator relocator(this);
|
||||
code->sweep_heap(relocator);
|
||||
code_heap_iterator<code_heap_relocator> iter(relocator);
|
||||
code->sweep_heap(iter);
|
||||
}
|
||||
|
||||
void factor_vm::primitive_modify_code_heap()
|
||||
|
@ -275,7 +276,10 @@ 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)
|
||||
{
|
||||
code->compact_heap();
|
||||
/* Figure out where blocks are going to go */
|
||||
code->state->compute_forwarding();
|
||||
|
||||
/* Update references to the code heap from the data heap */
|
||||
forward_object_xts();
|
||||
if(trace_contexts_p)
|
||||
{
|
||||
|
@ -283,14 +287,17 @@ void factor_vm::compact_code_heap(bool trace_contexts_p)
|
|||
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);
|
||||
iterate_code_heap(relocator);
|
||||
code_heap_iterator<code_heap_relocator> iter(relocator);
|
||||
code->compact_heap(iter);
|
||||
}
|
||||
|
||||
struct stack_trace_stripper {
|
||||
explicit stack_trace_stripper() {}
|
||||
|
||||
void operator()(code_block *compiled)
|
||||
void operator()(code_block *compiled, cell size)
|
||||
{
|
||||
compiled->owner = false_object;
|
||||
}
|
||||
|
|
29
vm/heap.cpp
29
vm/heap.cpp
|
@ -189,35 +189,6 @@ cell heap::heap_size()
|
|||
return (cell)scan - (cell)first_block();
|
||||
}
|
||||
|
||||
void heap::compact_heap()
|
||||
{
|
||||
state->compute_forwarding();
|
||||
|
||||
heap_block *scan = first_block();
|
||||
heap_block *end = last_block();
|
||||
|
||||
char *address = (char *)scan;
|
||||
|
||||
/* Slide blocks up while building the forwarding hashtable. */
|
||||
while(scan != end)
|
||||
{
|
||||
heap_block *next = scan->next();
|
||||
|
||||
if(state->is_marked_p(scan))
|
||||
{
|
||||
cell size = scan->size();
|
||||
memmove(address,scan,size);
|
||||
address += size;
|
||||
}
|
||||
|
||||
scan = next;
|
||||
}
|
||||
|
||||
/* Now update the free list; there will be a single free block at
|
||||
the end */
|
||||
build_free_list((cell)address - seg->start);
|
||||
}
|
||||
|
||||
heap_block *heap::free_allocated(heap_block *prev, heap_block *scan)
|
||||
{
|
||||
if(secure_gc)
|
||||
|
|
85
vm/heap.hpp
85
vm/heap.hpp
|
@ -29,7 +29,6 @@ struct heap {
|
|||
}
|
||||
|
||||
void clear_free_list();
|
||||
void new_heap(cell size);
|
||||
void add_to_free_list(free_heap_block *block);
|
||||
void build_free_list(cell size);
|
||||
void assert_free_block(free_heap_block *block);
|
||||
|
@ -44,41 +43,69 @@ struct heap {
|
|||
|
||||
heap_block *free_allocated(heap_block *prev, heap_block *scan);
|
||||
|
||||
/* 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)
|
||||
template<typename Iterator> void sweep_heap(Iterator &iter);
|
||||
template<typename Iterator> void compact_heap(Iterator &iter);
|
||||
|
||||
template<typename Iterator> void iterate_heap(Iterator &iter)
|
||||
{
|
||||
clear_free_list();
|
||||
|
||||
heap_block *prev = NULL;
|
||||
heap_block *scan = first_block();
|
||||
heap_block *end = last_block();
|
||||
|
||||
|
||||
while(scan != end)
|
||||
{
|
||||
if(scan->type() == FREE_BLOCK_TYPE)
|
||||
{
|
||||
if(prev && prev->type() == FREE_BLOCK_TYPE)
|
||||
prev->set_size(prev->size() + scan->size());
|
||||
else
|
||||
prev = scan;
|
||||
}
|
||||
else if(state->is_marked_p(scan))
|
||||
{
|
||||
if(prev && prev->type() == FREE_BLOCK_TYPE)
|
||||
add_to_free_list((free_heap_block *)prev);
|
||||
prev = scan;
|
||||
iter(scan);
|
||||
}
|
||||
else
|
||||
prev = free_allocated(prev,scan);
|
||||
|
||||
scan = scan->next();
|
||||
heap_block *next = scan->next();
|
||||
if(scan->type() != FREE_BLOCK_TYPE) iter(scan,scan->size());
|
||||
scan = next;
|
||||
}
|
||||
|
||||
if(prev && prev->type() == FREE_BLOCK_TYPE)
|
||||
add_to_free_list((free_heap_block *)prev);
|
||||
}
|
||||
};
|
||||
|
||||
/* After code GC, all live code blocks are marked, so any
|
||||
which are not marked can be reclaimed. */
|
||||
template<typename Iterator> void heap::sweep_heap(Iterator &iter)
|
||||
{
|
||||
this->clear_free_list();
|
||||
|
||||
heap_block *prev = NULL;
|
||||
heap_block *scan = this->first_block();
|
||||
heap_block *end = this->last_block();
|
||||
|
||||
while(scan != end)
|
||||
{
|
||||
if(scan->type() == FREE_BLOCK_TYPE)
|
||||
{
|
||||
if(prev && prev->type() == FREE_BLOCK_TYPE)
|
||||
prev->set_size(prev->size() + scan->size());
|
||||
else
|
||||
prev = scan;
|
||||
}
|
||||
else if(this->state->is_marked_p(scan))
|
||||
{
|
||||
if(prev && prev->type() == FREE_BLOCK_TYPE)
|
||||
this->add_to_free_list((free_heap_block *)prev);
|
||||
prev = scan;
|
||||
iter(scan,scan->size());
|
||||
}
|
||||
else
|
||||
prev = this->free_allocated(prev,scan);
|
||||
|
||||
scan = scan->next();
|
||||
}
|
||||
|
||||
if(prev && prev->type() == FREE_BLOCK_TYPE)
|
||||
this->add_to_free_list((free_heap_block *)prev);
|
||||
}
|
||||
|
||||
/* The forwarding map must be computed first by calling
|
||||
state->compute_forwarding(). */
|
||||
template<typename Iterator> void heap::compact_heap(Iterator &iter)
|
||||
{
|
||||
heap_compacter<heap_block,block_size_increment,Iterator> compacter(state,first_block(),iter);
|
||||
this->iterate_heap(compacter);
|
||||
|
||||
/* Now update the free list; there will be a single free block at
|
||||
the end */
|
||||
this->build_free_list((cell)compacter.address - this->seg->start);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -225,7 +225,7 @@ struct code_block_fixupper {
|
|||
code_block_fixupper(factor_vm *parent_, cell data_relocation_base_) :
|
||||
parent(parent_), data_relocation_base(data_relocation_base_) { }
|
||||
|
||||
void operator()(code_block *compiled)
|
||||
void operator()(code_block *compiled, cell size)
|
||||
{
|
||||
parent->fixup_code_block(compiled,data_relocation_base);
|
||||
}
|
||||
|
|
|
@ -159,4 +159,23 @@ template<typename Block, int Granularity> struct mark_bits {
|
|||
}
|
||||
};
|
||||
|
||||
template<typename Block, int Granularity, typename Iterator> struct heap_compacter {
|
||||
mark_bits<Block,Granularity> *state;
|
||||
char *address;
|
||||
Iterator &iter;
|
||||
|
||||
explicit heap_compacter(mark_bits<Block,Granularity> *state_, Block *address_, Iterator &iter_) :
|
||||
state(state_), address((char *)address_), iter(iter_) {}
|
||||
|
||||
void operator()(Block *block, cell size)
|
||||
{
|
||||
if(this->state->is_marked_p(block))
|
||||
{
|
||||
memmove(address,block,size);
|
||||
iter((Block *)address,size);
|
||||
address += size;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -283,7 +283,6 @@ void quotation_jit::iterate_quotation()
|
|||
|
||||
void factor_vm::set_quot_xt(quotation *quot, code_block *code)
|
||||
{
|
||||
assert(code->type() == QUOTATION_TYPE);
|
||||
quot->code = code;
|
||||
quot->xt = code->xt();
|
||||
}
|
||||
|
|
20
vm/vm.hpp
20
vm/vm.hpp
|
@ -524,17 +524,19 @@ struct factor_vm
|
|||
void primitive_strip_stack_traces();
|
||||
|
||||
/* Apply a function to every code block */
|
||||
template<typename Iterator> void iterate_code_heap(Iterator &iter)
|
||||
{
|
||||
heap_block *scan = code->first_block();
|
||||
heap_block *end = code->last_block();
|
||||
|
||||
while(scan != end)
|
||||
template<typename Iterator> struct code_heap_iterator {
|
||||
Iterator &iter;
|
||||
explicit code_heap_iterator(Iterator &iter_) : iter(iter_) {}
|
||||
void operator()(heap_block *block, cell size)
|
||||
{
|
||||
if(scan->type() != FREE_BLOCK_TYPE)
|
||||
iter((code_block *)scan);
|
||||
scan = scan->next();
|
||||
iter((code_block *)block,size);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Iterator> void iterate_code_heap(Iterator &iter_)
|
||||
{
|
||||
code_heap_iterator<Iterator> iter(iter_);
|
||||
code->iterate_heap(iter);
|
||||
}
|
||||
|
||||
//callbacks
|
||||
|
|
Loading…
Reference in New Issue