From bd7e6b33f8b7bfc927aca45f0f4f4c798ef5d34e Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Tue, 13 Dec 2011 12:28:09 -0800 Subject: [PATCH] vm: erase code blocks from all_blocks during sweep Fixes #437 --- vm/code_heap.cpp | 30 ++++++++++++++++++++++++++++++ vm/code_heap.hpp | 2 ++ vm/free_list_allocator.hpp | 18 +++++++++++++++++- vm/full_collector.cpp | 2 +- 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/vm/code_heap.cpp b/vm/code_heap.cpp index e15b9488b5..5f6967535a 100755 --- a/vm/code_heap.cpp +++ b/vm/code_heap.cpp @@ -72,6 +72,31 @@ void code_heap::flush_icache() factor::flush_icache(seg->start,seg->size); } +struct clear_free_blocks_from_all_blocks_iterator +{ + code_heap *code; + + clear_free_blocks_from_all_blocks_iterator(code_heap *code) : code(code) {} + + void operator()(code_block *free_block, cell size) { + std::set::iterator erase_from = + code->all_blocks.lower_bound(free_block); + std::set::iterator erase_to = + code->all_blocks.lower_bound((code_block*)((char*)free_block + size)); + + code->all_blocks.erase(erase_from, erase_to); + } +}; + +void code_heap::sweep() +{ + clear_free_blocks_from_all_blocks_iterator clearer(this); + allocator->sweep(clearer); +#ifdef FACTOR_DEBUG + verify_all_blocks_set(); +#endif +} + struct all_blocks_set_verifier { std::set *leftovers; @@ -104,6 +129,11 @@ code_block *code_heap::code_block_for_address(cell address) && address - (cell)found_block->entry_point() < found_block->size())) { std::cerr << "invalid block found in all_blocks set!" << std::endl; + std::cerr << "address " << (void*)address + << " block " << (void*)found_block + << " entry point " << (void*)found_block->entry_point() + << " size " << found_block->size() + << " free? " << found_block->free_p(); verify_all_blocks_set(); FACTOR_ASSERT(false); } diff --git a/vm/code_heap.hpp b/vm/code_heap.hpp index 8db96016dd..83b3ae586d 100755 --- a/vm/code_heap.hpp +++ b/vm/code_heap.hpp @@ -48,6 +48,8 @@ struct code_heap { void verify_all_blocks_set(); void initialize_all_blocks_set(); + void sweep(); + code_block *code_block_for_address(cell address); bool safepoint_p(cell addr) diff --git a/vm/free_list_allocator.hpp b/vm/free_list_allocator.hpp index ea7b5b1a5d..7106f7cf13 100644 --- a/vm/free_list_allocator.hpp +++ b/vm/free_list_allocator.hpp @@ -23,6 +23,7 @@ template struct free_list_allocator { cell largest_free_block(); cell free_block_count(); void sweep(); + template void sweep(Iterator &iter); template void compact(Iterator &iter, Fixup fixup, const Block **finger); template void iterate(Iterator &iter, Fixup fixup); template void iterate(Iterator &iter); @@ -124,7 +125,8 @@ template cell free_list_allocator::free_block_count() } template -void free_list_allocator::sweep() +template +void free_list_allocator::sweep(Iterator &iter) { free_blocks.clear_free_list(); @@ -145,12 +147,26 @@ void free_list_allocator::sweep() free_heap_block *free_block = (free_heap_block *)start; free_block->make_free(size); free_blocks.add_to_free_list(free_block); + iter(start, size); start = (Block *)((char *)start + size); } } } +template +struct null_sweep_iterator +{ + void operator()(Block *free_block, cell size) {} +}; + +template +void free_list_allocator::sweep() +{ + null_sweep_iterator none; + sweep(none); +} + template struct heap_compactor { mark_bits *state; char *address; diff --git a/vm/full_collector.cpp b/vm/full_collector.cpp index f53760ceca..fad855301e 100644 --- a/vm/full_collector.cpp +++ b/vm/full_collector.cpp @@ -101,7 +101,7 @@ void factor_vm::collect_sweep_impl() update_code_roots_for_sweep(); if(event) event->started_code_sweep(); - code->allocator->sweep(); + code->sweep(); if(event) event->ended_code_sweep(); }