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
parent
6498bc65ce
commit
2705fc67cb
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue