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
compiler at the beginning of bootstrap */
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
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));
points_to_nursery.erase(compiled);
points_to_aging.erase(compiled);
all_blocks.erase(compiled);
allocator->free(compiled);
}
@ -71,29 +72,32 @@ void code_heap::flush_icache()
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)
{
address_finder finder(address);
allocator->iterate(finder);
return finder.found_code_block;
std::set<code_block*>::const_iterator blocki =
all_blocks.upper_bound((code_block*)address);
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 */

View File

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

View File

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