vm: more efficient code heap remembered set
parent
c5979615b7
commit
21f55ab1a3
|
@ -17,11 +17,12 @@ void factor_vm::collect_aging()
|
|||
collector.trace_roots();
|
||||
collector.trace_contexts();
|
||||
collector.trace_cards(data->tenured);
|
||||
collector.trace_code_heap_roots();
|
||||
collector.trace_code_heap_roots(&code->points_to_aging);
|
||||
collector.cheneys_algorithm();
|
||||
update_dirty_code_blocks();
|
||||
update_dirty_code_blocks(&code->points_to_aging);
|
||||
|
||||
nursery.here = nursery.start;
|
||||
code->points_to_nursery.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ code_heap::code_heap(bool secure_gc, cell size) : heap(secure_gc,size) {}
|
|||
|
||||
void code_heap::write_barrier(code_block *compiled)
|
||||
{
|
||||
remembered_set[compiled] = nursery_gen;
|
||||
youngest_referenced_generation = nursery_gen;
|
||||
points_to_nursery.insert(compiled);
|
||||
points_to_aging.insert(compiled);
|
||||
}
|
||||
|
||||
bool code_heap::needs_fixup_p(code_block *compiled)
|
||||
|
@ -18,7 +18,8 @@ bool code_heap::needs_fixup_p(code_block *compiled)
|
|||
|
||||
void code_heap::code_heap_free(code_block *compiled)
|
||||
{
|
||||
remembered_set.erase(compiled);
|
||||
points_to_nursery.erase(compiled);
|
||||
points_to_aging.erase(compiled);
|
||||
needs_fixup.erase(compiled);
|
||||
heap_free(compiled);
|
||||
}
|
||||
|
@ -27,7 +28,6 @@ void code_heap::code_heap_free(code_block *compiled)
|
|||
void factor_vm::init_code_heap(cell size)
|
||||
{
|
||||
code = new code_heap(secure_gc,size);
|
||||
code->youngest_referenced_generation = nursery_gen;
|
||||
}
|
||||
|
||||
bool factor_vm::in_code_heap_p(cell ptr)
|
||||
|
|
|
@ -4,14 +4,12 @@ namespace factor
|
|||
struct code_heap : heap {
|
||||
/* Set of blocks which need full relocation. */
|
||||
unordered_set<code_block *> needs_fixup;
|
||||
|
||||
/* Maps code blocks to the youngest generation containing
|
||||
one of their literals. If this is tenured (0), the code block
|
||||
is not part of the remembered set. */
|
||||
unordered_map<code_block *, cell> remembered_set;
|
||||
|
||||
/* Minimum value in the above map. */
|
||||
cell youngest_referenced_generation;
|
||||
/* Code blocks which may reference objects in the nursery */
|
||||
std::set<code_block *> points_to_nursery;
|
||||
|
||||
/* Code blocks which may reference objects in aging space or the nursery */
|
||||
std::set<code_block *> points_to_aging;
|
||||
|
||||
explicit code_heap(bool secure_gc, cell size);
|
||||
void write_barrier(code_block *compiled);
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace factor
|
|||
template<typename TargetGeneration, typename Policy> struct collector {
|
||||
factor_vm *myvm;
|
||||
data_heap *data;
|
||||
code_heap *code;
|
||||
gc_state *current_gc;
|
||||
TargetGeneration *target;
|
||||
Policy policy;
|
||||
|
@ -11,6 +12,7 @@ template<typename TargetGeneration, typename Policy> struct collector {
|
|||
explicit collector(factor_vm *myvm_, TargetGeneration *target_, Policy policy_) :
|
||||
myvm(myvm_),
|
||||
data(myvm_->data),
|
||||
code(myvm_->code),
|
||||
current_gc(myvm_->current_gc),
|
||||
target(target_),
|
||||
policy(policy_) {}
|
||||
|
|
|
@ -130,24 +130,13 @@ struct copying_collector : collector<TargetGeneration,Policy> {
|
|||
this->trace_handle(&compiled->literals);
|
||||
this->trace_handle(&compiled->relocation);
|
||||
}
|
||||
|
||||
/* Trace literals referenced from all code blocks. Only for aging and nursery collections */
|
||||
void trace_code_heap_roots()
|
||||
|
||||
void trace_code_heap_roots(std::set<code_block *> *remembered_set)
|
||||
{
|
||||
if(this->current_gc->collecting_gen >= this->myvm->code->youngest_referenced_generation)
|
||||
{
|
||||
unordered_map<code_block *,cell> &remembered_set = this->myvm->code->remembered_set;
|
||||
unordered_map<code_block *,cell>::const_iterator iter = remembered_set.begin();
|
||||
unordered_map<code_block *,cell>::const_iterator end = remembered_set.end();
|
||||
|
||||
for(; iter != end; iter++)
|
||||
{
|
||||
if(this->current_gc->collecting_gen >= iter->second)
|
||||
trace_literal_references(iter->first);
|
||||
}
|
||||
|
||||
this->myvm->gc_stats.code_heap_scans++;
|
||||
}
|
||||
std::set<code_block *>::const_iterator iter = remembered_set->begin();
|
||||
std::set<code_block *>::const_iterator end = remembered_set->end();
|
||||
|
||||
for(; iter != end; iter++) trace_literal_references(*iter);
|
||||
}
|
||||
|
||||
void cheneys_algorithm()
|
||||
|
|
|
@ -78,9 +78,7 @@ void full_collector::trace_literal_references(code_block *compiled)
|
|||
collections */
|
||||
void full_collector::mark_code_block(code_block *compiled)
|
||||
{
|
||||
myvm->check_code_address((cell)compiled);
|
||||
|
||||
this->myvm->code->mark_block(compiled);
|
||||
this->code->mark_block(compiled);
|
||||
trace_literal_references(compiled);
|
||||
}
|
||||
|
||||
|
|
29
vm/gc.cpp
29
vm/gc.cpp
|
@ -29,34 +29,17 @@ void factor_vm::free_unmarked_code_blocks()
|
|||
{
|
||||
literal_and_word_reference_updater updater(this);
|
||||
code->free_unmarked(updater);
|
||||
code->remembered_set.clear();
|
||||
code->youngest_referenced_generation = tenured_gen;
|
||||
code->points_to_nursery.clear();
|
||||
code->points_to_aging.clear();
|
||||
}
|
||||
|
||||
void factor_vm::update_dirty_code_blocks()
|
||||
void factor_vm::update_dirty_code_blocks(std::set<code_block *> *remembered_set)
|
||||
{
|
||||
/* The youngest generation that any code block can now reference */
|
||||
cell gen;
|
||||
std::set<code_block *>::iterator iter = remembered_set->begin();
|
||||
std::set<code_block *>::iterator end = remembered_set->end();
|
||||
|
||||
if(current_gc->collecting_accumulation_gen_p())
|
||||
gen = current_gc->collecting_gen;
|
||||
else
|
||||
gen = current_gc->collecting_gen + 1;
|
||||
|
||||
unordered_map<code_block *,cell>::iterator iter = code->remembered_set.begin();
|
||||
unordered_map<code_block *,cell>::iterator end = code->remembered_set.end();
|
||||
|
||||
for(; iter != end; iter++)
|
||||
{
|
||||
if(current_gc->collecting_gen >= iter->second)
|
||||
{
|
||||
check_code_address((cell)iter->first);
|
||||
update_literal_references(iter->first);
|
||||
iter->second = gen;
|
||||
}
|
||||
}
|
||||
|
||||
code->youngest_referenced_generation = gen;
|
||||
for(; iter != end; iter++) update_literal_references(*iter);
|
||||
}
|
||||
|
||||
void factor_vm::record_gc_stats()
|
||||
|
|
|
@ -15,12 +15,12 @@ void factor_vm::collect_nursery()
|
|||
collector.trace_contexts();
|
||||
collector.trace_cards(data->tenured);
|
||||
collector.trace_cards(data->aging);
|
||||
collector.trace_code_heap_roots();
|
||||
collector.trace_code_heap_roots(&code->points_to_nursery);
|
||||
collector.cheneys_algorithm();
|
||||
|
||||
update_dirty_code_blocks();
|
||||
update_dirty_code_blocks(&code->points_to_nursery);
|
||||
|
||||
nursery.here = nursery.start;
|
||||
code->points_to_nursery.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,12 +14,14 @@ void factor_vm::collect_to_tenured()
|
|||
collector.trace_roots();
|
||||
collector.trace_contexts();
|
||||
collector.trace_cards(data->tenured);
|
||||
collector.trace_code_heap_roots();
|
||||
collector.trace_code_heap_roots(&code->points_to_aging);
|
||||
collector.cheneys_algorithm();
|
||||
update_dirty_code_blocks();
|
||||
update_dirty_code_blocks(&code->points_to_aging);
|
||||
|
||||
reset_generation(data->aging);
|
||||
nursery.here = nursery.start;
|
||||
reset_generation(data->aging);
|
||||
code->points_to_nursery.clear();
|
||||
code->points_to_aging.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue