vm: keep a set of all code_blocks in the code_heap

This way looking up code blocks by return address is an O(log n) set lookup rather than an O(n) linear scan.
db4
Joe Groff 2011-11-17 14:29:01 -08:00
parent 6498bc65ce
commit 2705fc67cb
4 changed files with 34 additions and 21 deletions

View File

@ -436,6 +436,7 @@ code_block *factor_vm::add_code_block(code_block_type type, cell code_, cell lab
method returns, except when compiling words with the non-optimizing method returns, except when compiling words with the non-optimizing
compiler at the beginning of bootstrap */ compiler at the beginning of bootstrap */
this->code->uninitialized_blocks.insert(std::make_pair(compiled,literals.value())); this->code->uninitialized_blocks.insert(std::make_pair(compiled,literals.value()));
this->code->all_blocks.insert(compiled);
/* next time we do a minor GC, we have to trace this code block, since /* next time we do a minor GC, we have to trace this code block, since
the fields of the code_block struct might point into nursery or aging */ the fields of the code_block struct might point into nursery or aging */

View File

@ -63,6 +63,7 @@ void code_heap::free(code_block *compiled)
assert(!uninitialized_p(compiled)); assert(!uninitialized_p(compiled));
points_to_nursery.erase(compiled); points_to_nursery.erase(compiled);
points_to_aging.erase(compiled); points_to_aging.erase(compiled);
all_blocks.erase(compiled);
allocator->free(compiled); allocator->free(compiled);
} }
@ -71,29 +72,32 @@ void code_heap::flush_icache()
factor::flush_icache(seg->start,seg->size); factor::flush_icache(seg->start,seg->size);
} }
struct address_finder {
cell address;
code_block *found_code_block;
address_finder(cell address)
: address(address), found_code_block(NULL) {}
void operator()(code_block *block, cell size)
{
if ((cell)block->entry_point() <= address
&& address - (cell)block->entry_point() < block->size())
{
assert(found_code_block == NULL);
found_code_block = block;
}
}
};
code_block *code_heap::code_block_for_address(cell address) code_block *code_heap::code_block_for_address(cell address)
{ {
address_finder finder(address); std::set<code_block*>::const_iterator blocki =
allocator->iterate(finder); all_blocks.upper_bound((code_block*)address);
return finder.found_code_block; assert(blocki != all_blocks.begin());
--blocki;
code_block* found_block = *blocki;
assert((cell)found_block->entry_point() <= address
&& address - (cell)found_block->entry_point() < found_block->size());
return found_block;
}
void code_heap::update_all_blocks_map(mark_bits<code_block> *code_forwarding_map)
{
std::cout << "updating block map" << std::endl;
std::set<code_block *> new_all_blocks;
for (std::set<code_block *>::const_iterator oldi = all_blocks.begin();
oldi != all_blocks.end();
++oldi)
{
code_block *new_block = code_forwarding_map->forward_block(*oldi);
std::cout << "compact " << (void*)*oldi << " -> " << (void*)new_block << std::endl;
new_all_blocks.insert(new_block);
}
std::cout << "updated" << std::endl;
all_blocks.swap(new_all_blocks);
} }
/* Allocate a code heap during startup */ /* Allocate a code heap during startup */

View File

@ -7,6 +7,8 @@ namespace factor
const cell seh_area_size = 0; const cell seh_area_size = 0;
#endif #endif
struct compaction_fixup;
struct code_heap { struct code_heap {
/* The actual memory area */ /* The actual memory area */
segment *seg; segment *seg;
@ -20,6 +22,8 @@ struct code_heap {
/* Memory allocator */ /* Memory allocator */
free_list_allocator<code_block> *allocator; free_list_allocator<code_block> *allocator;
std::set<code_block *> all_blocks;
/* Keys are blocks which need to be initialized by initialize_code_block(). /* Keys are blocks which need to be initialized by initialize_code_block().
Values are literal tables. Literal table arrays are GC roots until the Values are literal tables. Literal table arrays are GC roots until the
time the block is initialized, after which point they are discarded. */ time the block is initialized, after which point they are discarded. */
@ -43,6 +47,7 @@ struct code_heap {
void flush_icache(); void flush_icache();
void guard_safepoint(); void guard_safepoint();
void unguard_safepoint(); void unguard_safepoint();
void update_all_blocks_map(mark_bits<code_block> *code_forwarding_map);
code_block *code_block_for_address(cell address); code_block *code_block_for_address(cell address);
@ -51,6 +56,7 @@ struct code_heap {
cell page_mask = ~(getpagesize() - 1); cell page_mask = ~(getpagesize() - 1);
return (addr & page_mask) == (cell)safepoint_page; return (addr & page_mask) == (cell)safepoint_page;
} }
}; };
struct code_heap_room { struct code_heap_room {

View File

@ -185,6 +185,8 @@ void factor_vm::update_code_roots_for_compaction()
else else
root->valid = false; root->valid = false;
} }
code->update_all_blocks_map(state);
} }
/* Compact data and code heaps */ /* Compact data and code heaps */