diff --git a/vm/code_heap.cpp b/vm/code_heap.cpp index 020c8c2ba8..756dfdbff6 100755 --- a/vm/code_heap.cpp +++ b/vm/code_heap.cpp @@ -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 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 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; } diff --git a/vm/heap.cpp b/vm/heap.cpp index c2a44e42a4..2132ba1a20 100644 --- a/vm/heap.cpp +++ b/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) diff --git a/vm/heap.hpp b/vm/heap.hpp index ba00b9ba6c..1cdca5180c 100644 --- a/vm/heap.hpp +++ b/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 void sweep_heap(Iterator &iter) + template void sweep_heap(Iterator &iter); + template void compact_heap(Iterator &iter); + + template 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 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 void heap::compact_heap(Iterator &iter) +{ + heap_compacter 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); +} + } diff --git a/vm/image.cpp b/vm/image.cpp index c6d1ad7aca..c96da6b703 100755 --- a/vm/image.cpp +++ b/vm/image.cpp @@ -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); } diff --git a/vm/mark_bits.hpp b/vm/mark_bits.hpp index f123701816..ad3eda89df 100644 --- a/vm/mark_bits.hpp +++ b/vm/mark_bits.hpp @@ -159,4 +159,23 @@ template struct mark_bits { } }; +template struct heap_compacter { + mark_bits *state; + char *address; + Iterator &iter; + + explicit heap_compacter(mark_bits *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; + } + } +}; + } diff --git a/vm/quotations.cpp b/vm/quotations.cpp index 9c2c85215d..d75d1c680c 100755 --- a/vm/quotations.cpp +++ b/vm/quotations.cpp @@ -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(); } diff --git a/vm/vm.hpp b/vm/vm.hpp index 7742ea8d60..05a918c5e9 100755 --- a/vm/vm.hpp +++ b/vm/vm.hpp @@ -524,17 +524,19 @@ struct factor_vm void primitive_strip_stack_traces(); /* Apply a function to every code block */ - template void iterate_code_heap(Iterator &iter) - { - heap_block *scan = code->first_block(); - heap_block *end = code->last_block(); - - while(scan != end) + template 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 void iterate_code_heap(Iterator &iter_) + { + code_heap_iterator iter(iter_); + code->iterate_heap(iter); } //callbacks