vm: number of generations is not configurable anymore, split up begin_gc() and end_gc() into collect_{nursery,aging,aging_again,tenured}()
parent
d10e27149c
commit
b50d3f3fb0
229
vm/data_gc.cpp
229
vm/data_gc.cpp
|
@ -74,7 +74,7 @@ template<typename Strategy> void factor_vm::trace_card_deck(card_deck *deck, cel
|
||||||
decks_scanned++;
|
decks_scanned++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy all newspace objects referenced from marked cards to the destination */
|
/* Trace all objects referenced from marked cards */
|
||||||
template<typename Strategy> void factor_vm::trace_generation_cards(cell gen, Strategy &strategy)
|
template<typename Strategy> void factor_vm::trace_generation_cards(cell gen, Strategy &strategy)
|
||||||
{
|
{
|
||||||
card_deck *first_deck = addr_to_deck(data->generations[gen].start);
|
card_deck *first_deck = addr_to_deck(data->generations[gen].start);
|
||||||
|
@ -95,7 +95,7 @@ template<typename Strategy> void factor_vm::trace_generation_cards(cell gen, Str
|
||||||
unmask = card_points_to_nursery;
|
unmask = card_points_to_nursery;
|
||||||
/* after the collection, all cards in aging space can be
|
/* after the collection, all cards in aging space can be
|
||||||
cleared */
|
cleared */
|
||||||
else if(data->have_aging_p() && gen == data->aging())
|
else if(gen == data->aging())
|
||||||
unmask = card_mark_mask;
|
unmask = card_mark_mask;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -106,7 +106,7 @@ template<typename Strategy> void factor_vm::trace_generation_cards(cell gen, Str
|
||||||
/* if we are collecting aging space into tenured space, we care about
|
/* if we are collecting aging space into tenured space, we care about
|
||||||
all old->nursery and old->aging pointers. no old->aging pointers can
|
all old->nursery and old->aging pointers. no old->aging pointers can
|
||||||
remain */
|
remain */
|
||||||
else if(data->have_aging_p() && current_gc->collecting_gen == data->aging())
|
else if(current_gc->collecting_aging_p())
|
||||||
{
|
{
|
||||||
if(current_gc->collecting_aging_again)
|
if(current_gc->collecting_aging_again)
|
||||||
{
|
{
|
||||||
|
@ -147,7 +147,7 @@ template<typename Strategy> void factor_vm::trace_cards(Strategy &strategy)
|
||||||
u64 start = current_micros();
|
u64 start = current_micros();
|
||||||
|
|
||||||
cell i;
|
cell i;
|
||||||
for(i = current_gc->collecting_gen + 1; i < data->gen_count; i++)
|
for(i = current_gc->collecting_gen + 1; i < gen_count; i++)
|
||||||
trace_generation_cards(i,strategy);
|
trace_generation_cards(i,strategy);
|
||||||
|
|
||||||
card_scan_time += (current_micros() - start);
|
card_scan_time += (current_micros() - start);
|
||||||
|
@ -284,8 +284,7 @@ template<typename Strategy> void factor_vm::trace_contexts(Strategy &strategy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy all literals referenced from a code block to newspace. Only for
|
/* Trace all literals referenced from a code block. Only for aging and nursery collections */
|
||||||
aging and nursery collections */
|
|
||||||
template<typename Strategy> void factor_vm::trace_literal_references(code_block *compiled, Strategy &strategy)
|
template<typename Strategy> void factor_vm::trace_literal_references(code_block *compiled, Strategy &strategy)
|
||||||
{
|
{
|
||||||
if(current_gc->collecting_gen >= compiled->last_scan)
|
if(current_gc->collecting_gen >= compiled->last_scan)
|
||||||
|
@ -317,8 +316,7 @@ template<typename Strategy> struct literal_reference_tracer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Copy literals referenced from all code blocks to newspace. Only for
|
/* Trace literals referenced from all code blocks. Only for aging and nursery collections */
|
||||||
aging and nursery collections */
|
|
||||||
template<typename Strategy> void factor_vm::trace_code_heap_roots(Strategy &strategy)
|
template<typename Strategy> void factor_vm::trace_code_heap_roots(Strategy &strategy)
|
||||||
{
|
{
|
||||||
if(current_gc->collecting_gen >= code->last_code_heap_scan)
|
if(current_gc->collecting_gen >= code->last_code_heap_scan)
|
||||||
|
@ -379,44 +377,11 @@ void factor_vm::update_dirty_code_blocks()
|
||||||
dirty_code_blocks.clear();
|
dirty_code_blocks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare to start copying reachable objects into an unused zone */
|
|
||||||
void factor_vm::begin_gc(cell requested_bytes)
|
|
||||||
{
|
|
||||||
if(current_gc->growing_data_heap)
|
|
||||||
{
|
|
||||||
assert(current_gc->collecting_tenured_p());
|
|
||||||
|
|
||||||
current_gc->old_data_heap = data;
|
|
||||||
set_data_heap(grow_data_heap(current_gc->old_data_heap,requested_bytes));
|
|
||||||
current_gc->newspace = &data->generations[data->tenured()];
|
|
||||||
}
|
|
||||||
else if(current_gc->collecting_accumulation_gen_p())
|
|
||||||
{
|
|
||||||
/* when collecting one of these generations, rotate it
|
|
||||||
with the semispace */
|
|
||||||
zone z = data->generations[current_gc->collecting_gen];
|
|
||||||
data->generations[current_gc->collecting_gen] = data->semispaces[current_gc->collecting_gen];
|
|
||||||
data->semispaces[current_gc->collecting_gen] = z;
|
|
||||||
reset_generation(current_gc->collecting_gen);
|
|
||||||
current_gc->newspace = &data->generations[current_gc->collecting_gen];
|
|
||||||
clear_cards(current_gc->collecting_gen,current_gc->collecting_gen);
|
|
||||||
clear_decks(current_gc->collecting_gen,current_gc->collecting_gen);
|
|
||||||
clear_allot_markers(current_gc->collecting_gen,current_gc->collecting_gen);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* when collecting a younger generation, we copy
|
|
||||||
reachable objects to the next oldest generation,
|
|
||||||
so we set the newspace so the next generation. */
|
|
||||||
current_gc->newspace = &data->generations[current_gc->collecting_gen + 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Strategy>
|
template<typename Strategy>
|
||||||
copying_collector<Strategy>::copying_collector(factor_vm *myvm_)
|
copying_collector<Strategy>::copying_collector(factor_vm *myvm_, zone *newspace_)
|
||||||
: myvm(myvm_), current_gc(myvm_->current_gc)
|
: myvm(myvm_), current_gc(myvm_->current_gc), newspace(newspace_)
|
||||||
{
|
{
|
||||||
scan = current_gc->newspace->here;
|
scan = newspace->here;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Strategy> Strategy ©ing_collector<Strategy>::strategy()
|
template<typename Strategy> Strategy ©ing_collector<Strategy>::strategy()
|
||||||
|
@ -427,10 +392,10 @@ template<typename Strategy> Strategy ©ing_collector<Strategy>::strategy()
|
||||||
/* Given a pointer to oldspace, copy it to newspace */
|
/* Given a pointer to oldspace, copy it to newspace */
|
||||||
template<typename Strategy> object *copying_collector<Strategy>::copy_untagged_object_impl(object *pointer, cell size)
|
template<typename Strategy> object *copying_collector<Strategy>::copy_untagged_object_impl(object *pointer, cell size)
|
||||||
{
|
{
|
||||||
if(current_gc->newspace->here + size >= current_gc->newspace->end)
|
if(newspace->here + size >= newspace->end)
|
||||||
longjmp(current_gc->gc_unwind,1);
|
longjmp(current_gc->gc_unwind,1);
|
||||||
|
|
||||||
object *newpointer = myvm->allot_zone(current_gc->newspace,size);
|
object *newpointer = myvm->allot_zone(newspace,size);
|
||||||
|
|
||||||
gc_stats *s = &myvm->stats[current_gc->collecting_gen];
|
gc_stats *s = &myvm->stats[current_gc->collecting_gen];
|
||||||
s->object_count++;
|
s->object_count++;
|
||||||
|
@ -488,7 +453,7 @@ template<typename Strategy> bool copying_collector<Strategy>::should_copy_p(obje
|
||||||
return strategy().should_copy_p(pointer);
|
return strategy().should_copy_p(pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Strategy> cell copying_collector<Strategy>::copy_next(cell scan)
|
template<typename Strategy> cell copying_collector<Strategy>::trace_next(cell scan)
|
||||||
{
|
{
|
||||||
cell *obj = (cell *)scan;
|
cell *obj = (cell *)scan;
|
||||||
cell *end = (cell *)(scan + myvm->binary_payload_start((object *)scan));
|
cell *end = (cell *)(scan + myvm->binary_payload_start((object *)scan));
|
||||||
|
@ -506,16 +471,17 @@ template<typename Strategy> cell copying_collector<Strategy>::copy_next(cell sca
|
||||||
|
|
||||||
template<typename Strategy> void copying_collector<Strategy>::go()
|
template<typename Strategy> void copying_collector<Strategy>::go()
|
||||||
{
|
{
|
||||||
strategy().copy_reachable_objects(scan,¤t_gc->newspace->here);
|
strategy().copy_reachable_objects(scan,&newspace->here);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct nursery_collector : copying_collector<nursery_collector>
|
struct nursery_collector : copying_collector<nursery_collector>
|
||||||
{
|
{
|
||||||
explicit nursery_collector(factor_vm *myvm_) : copying_collector<nursery_collector>(myvm_) {}
|
explicit nursery_collector(factor_vm *myvm_, zone *newspace_) :
|
||||||
|
copying_collector<nursery_collector>(myvm_,newspace_) {}
|
||||||
|
|
||||||
bool should_copy_p(object *untagged)
|
bool should_copy_p(object *untagged)
|
||||||
{
|
{
|
||||||
if(myvm->current_gc->newspace->contains_p(untagged))
|
if(newspace->contains_p(untagged))
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
return myvm->nursery.contains_p(untagged);
|
return myvm->nursery.contains_p(untagged);
|
||||||
|
@ -523,29 +489,18 @@ struct nursery_collector : copying_collector<nursery_collector>
|
||||||
|
|
||||||
void copy_reachable_objects(cell scan, cell *end)
|
void copy_reachable_objects(cell scan, cell *end)
|
||||||
{
|
{
|
||||||
while(scan < *end) scan = copy_next(scan);
|
while(scan < *end) scan = trace_next(scan);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void factor_vm::collect_nursery()
|
|
||||||
{
|
|
||||||
nursery_collector collector(this);
|
|
||||||
|
|
||||||
trace_roots(collector);
|
|
||||||
trace_contexts(collector);
|
|
||||||
trace_cards(collector);
|
|
||||||
trace_code_heap_roots(collector);
|
|
||||||
collector.go();
|
|
||||||
update_dirty_code_blocks();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct aging_collector : copying_collector<aging_collector>
|
struct aging_collector : copying_collector<aging_collector>
|
||||||
{
|
{
|
||||||
explicit aging_collector(factor_vm *myvm_) : copying_collector<aging_collector>(myvm_) {}
|
explicit aging_collector(factor_vm *myvm_, zone *newspace_) :
|
||||||
|
copying_collector<aging_collector>(myvm_,newspace_) {}
|
||||||
|
|
||||||
bool should_copy_p(object *untagged)
|
bool should_copy_p(object *untagged)
|
||||||
{
|
{
|
||||||
if(myvm->current_gc->newspace->contains_p(untagged))
|
if(newspace->contains_p(untagged))
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
return !myvm->data->generations[myvm->data->tenured()].contains_p(untagged);
|
return !myvm->data->generations[myvm->data->tenured()].contains_p(untagged);
|
||||||
|
@ -553,29 +508,34 @@ struct aging_collector : copying_collector<aging_collector>
|
||||||
|
|
||||||
void copy_reachable_objects(cell scan, cell *end)
|
void copy_reachable_objects(cell scan, cell *end)
|
||||||
{
|
{
|
||||||
while(scan < *end) scan = copy_next(scan);
|
while(scan < *end) scan = trace_next(scan);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void factor_vm::collect_aging()
|
struct aging_again_collector : copying_collector<aging_again_collector>
|
||||||
{
|
{
|
||||||
aging_collector collector(this);
|
explicit aging_again_collector(factor_vm *myvm_, zone *newspace_) :
|
||||||
|
copying_collector<aging_again_collector>(myvm_,newspace_) {}
|
||||||
trace_roots(collector);
|
|
||||||
trace_contexts(collector);
|
|
||||||
trace_cards(collector);
|
|
||||||
trace_code_heap_roots(collector);
|
|
||||||
collector.go();
|
|
||||||
update_dirty_code_blocks();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct tenured_collector : copying_collector<tenured_collector>
|
|
||||||
{
|
|
||||||
explicit tenured_collector(factor_vm *myvm_) : copying_collector<tenured_collector>(myvm_) {}
|
|
||||||
|
|
||||||
bool should_copy_p(object *untagged)
|
bool should_copy_p(object *untagged)
|
||||||
{
|
{
|
||||||
return !myvm->current_gc->newspace->contains_p(untagged);
|
return !newspace->contains_p(untagged);
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_reachable_objects(cell scan, cell *end)
|
||||||
|
{
|
||||||
|
while(scan < *end) scan = trace_next(scan);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tenured_collector : copying_collector<tenured_collector>
|
||||||
|
{
|
||||||
|
explicit tenured_collector(factor_vm *myvm_, zone *newspace_) :
|
||||||
|
copying_collector<tenured_collector>(myvm_,newspace_) {}
|
||||||
|
|
||||||
|
bool should_copy_p(object *untagged)
|
||||||
|
{
|
||||||
|
return !newspace->contains_p(untagged);
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy_reachable_objects(cell scan, cell *end)
|
void copy_reachable_objects(cell scan, cell *end)
|
||||||
|
@ -583,22 +543,83 @@ struct tenured_collector : copying_collector<tenured_collector>
|
||||||
while(scan < *end)
|
while(scan < *end)
|
||||||
{
|
{
|
||||||
myvm->mark_object_code_block(myvm->untag<object>(scan),*this);
|
myvm->mark_object_code_block(myvm->untag<object>(scan),*this);
|
||||||
scan = copy_next(scan);
|
scan = trace_next(scan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void factor_vm::collect_tenured(bool trace_contexts_)
|
void factor_vm::collect_nursery()
|
||||||
{
|
{
|
||||||
tenured_collector collector(this);
|
nursery_collector collector(this,&data->generations[data->aging()]);
|
||||||
|
|
||||||
|
trace_roots(collector);
|
||||||
|
trace_contexts(collector);
|
||||||
|
trace_cards(collector);
|
||||||
|
trace_code_heap_roots(collector);
|
||||||
|
collector.go();
|
||||||
|
update_dirty_code_blocks();
|
||||||
|
|
||||||
|
nursery.here = nursery.start;
|
||||||
|
}
|
||||||
|
|
||||||
|
void factor_vm::collect_aging()
|
||||||
|
{
|
||||||
|
std::swap(data->generations[data->aging()],data->semispaces[data->aging()]);
|
||||||
|
reset_generations(data->aging(),data->aging());
|
||||||
|
|
||||||
|
aging_collector collector(this,&data->generations[data->aging()]);
|
||||||
|
|
||||||
|
trace_roots(collector);
|
||||||
|
trace_contexts(collector);
|
||||||
|
trace_cards(collector);
|
||||||
|
trace_code_heap_roots(collector);
|
||||||
|
collector.go();
|
||||||
|
update_dirty_code_blocks();
|
||||||
|
|
||||||
|
reset_generations(data->nursery(),data->nursery());
|
||||||
|
}
|
||||||
|
|
||||||
|
void factor_vm::collect_aging_again()
|
||||||
|
{
|
||||||
|
aging_again_collector collector(this,&data->generations[data->tenured()]);
|
||||||
|
|
||||||
|
trace_roots(collector);
|
||||||
|
trace_contexts(collector);
|
||||||
|
trace_cards(collector);
|
||||||
|
trace_code_heap_roots(collector);
|
||||||
|
collector.go();
|
||||||
|
update_dirty_code_blocks();
|
||||||
|
|
||||||
|
reset_generations(data->nursery(),data->aging());
|
||||||
|
}
|
||||||
|
|
||||||
|
void factor_vm::collect_tenured(cell requested_bytes, bool trace_contexts_)
|
||||||
|
{
|
||||||
|
if(current_gc->growing_data_heap)
|
||||||
|
{
|
||||||
|
current_gc->old_data_heap = data;
|
||||||
|
set_data_heap(grow_data_heap(current_gc->old_data_heap,requested_bytes));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::swap(data->generations[data->tenured()],data->semispaces[data->tenured()]);
|
||||||
|
reset_generations(data->tenured(),data->tenured());
|
||||||
|
}
|
||||||
|
|
||||||
|
tenured_collector collector(this,&data->generations[data->tenured()]);
|
||||||
|
|
||||||
trace_roots(collector);
|
trace_roots(collector);
|
||||||
if(trace_contexts_) trace_contexts(collector);
|
if(trace_contexts_) trace_contexts(collector);
|
||||||
collector.go();
|
collector.go();
|
||||||
free_unmarked_code_blocks();
|
free_unmarked_code_blocks();
|
||||||
|
|
||||||
|
reset_generations(data->nursery(),data->aging());
|
||||||
|
|
||||||
|
if(current_gc->growing_data_heap)
|
||||||
|
delete current_gc->old_data_heap;
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::end_gc()
|
void factor_vm::record_gc_stats()
|
||||||
{
|
{
|
||||||
gc_stats *s = &stats[current_gc->collecting_gen];
|
gc_stats *s = &stats[current_gc->collecting_gen];
|
||||||
|
|
||||||
|
@ -607,24 +628,6 @@ void factor_vm::end_gc()
|
||||||
s->gc_time += gc_elapsed;
|
s->gc_time += gc_elapsed;
|
||||||
if(s->max_gc_time < gc_elapsed)
|
if(s->max_gc_time < gc_elapsed)
|
||||||
s->max_gc_time = gc_elapsed;
|
s->max_gc_time = gc_elapsed;
|
||||||
|
|
||||||
if(current_gc->growing_data_heap)
|
|
||||||
delete current_gc->old_data_heap;
|
|
||||||
|
|
||||||
if(current_gc->collecting_nursery_p())
|
|
||||||
{
|
|
||||||
nursery.here = nursery.start;
|
|
||||||
}
|
|
||||||
else if(current_gc->collecting_accumulation_gen_p())
|
|
||||||
{
|
|
||||||
reset_generations(data->nursery(),current_gc->collecting_gen - 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* all generations up to and including the one
|
|
||||||
collected are now empty */
|
|
||||||
reset_generations(data->nursery(),current_gc->collecting_gen);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Collect gen and all younger generations.
|
/* Collect gen and all younger generations.
|
||||||
|
@ -657,8 +660,7 @@ void factor_vm::garbage_collection(cell collecting_gen_, bool growing_data_heap_
|
||||||
}
|
}
|
||||||
/* we try collecting aging space twice before going on to
|
/* we try collecting aging space twice before going on to
|
||||||
collect tenured */
|
collect tenured */
|
||||||
else if(data->have_aging_p()
|
else if(current_gc->collecting_aging_p()
|
||||||
&& current_gc->collecting_gen == data->aging()
|
|
||||||
&& !current_gc->collecting_aging_again)
|
&& !current_gc->collecting_aging_again)
|
||||||
{
|
{
|
||||||
current_gc->collecting_aging_again = true;
|
current_gc->collecting_aging_again = true;
|
||||||
|
@ -670,16 +672,19 @@ void factor_vm::garbage_collection(cell collecting_gen_, bool growing_data_heap_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
begin_gc(requested_bytes);
|
|
||||||
|
|
||||||
if(current_gc->collecting_nursery_p())
|
if(current_gc->collecting_nursery_p())
|
||||||
collect_nursery();
|
collect_nursery();
|
||||||
else if(current_gc->collecting_aging_p())
|
else if(current_gc->collecting_aging_p())
|
||||||
collect_aging();
|
{
|
||||||
|
if(current_gc->collecting_aging_again)
|
||||||
|
collect_aging_again();
|
||||||
|
else
|
||||||
|
collect_aging();
|
||||||
|
}
|
||||||
else if(current_gc->collecting_tenured_p())
|
else if(current_gc->collecting_tenured_p())
|
||||||
collect_tenured(trace_contexts_);
|
collect_tenured(requested_bytes,trace_contexts_);
|
||||||
|
|
||||||
end_gc();
|
record_gc_stats();
|
||||||
|
|
||||||
delete current_gc;
|
delete current_gc;
|
||||||
current_gc = NULL;
|
current_gc = NULL;
|
||||||
|
@ -702,7 +707,7 @@ void factor_vm::primitive_gc_stats()
|
||||||
cell i;
|
cell i;
|
||||||
u64 total_gc_time = 0;
|
u64 total_gc_time = 0;
|
||||||
|
|
||||||
for(i = 0; i < max_gen_count; i++)
|
for(i = 0; i < gen_count; i++)
|
||||||
{
|
{
|
||||||
gc_stats *s = &stats[i];
|
gc_stats *s = &stats[i];
|
||||||
result.add(allot_cell(s->collections));
|
result.add(allot_cell(s->collections));
|
||||||
|
@ -727,7 +732,7 @@ void factor_vm::primitive_gc_stats()
|
||||||
|
|
||||||
void factor_vm::clear_gc_stats()
|
void factor_vm::clear_gc_stats()
|
||||||
{
|
{
|
||||||
for(cell i = 0; i < max_gen_count; i++)
|
for(cell i = 0; i < gen_count; i++)
|
||||||
memset(&stats[i],0,sizeof(gc_stats));
|
memset(&stats[i],0,sizeof(gc_stats));
|
||||||
|
|
||||||
cards_scanned = 0;
|
cards_scanned = 0;
|
||||||
|
|
|
@ -14,9 +14,6 @@ struct gc_state {
|
||||||
/* The data heap we're collecting */
|
/* The data heap we're collecting */
|
||||||
data_heap *data;
|
data_heap *data;
|
||||||
|
|
||||||
/* New objects are copied here */
|
|
||||||
zone *newspace;
|
|
||||||
|
|
||||||
/* sometimes we grow the heap */
|
/* sometimes we grow the heap */
|
||||||
bool growing_data_heap;
|
bool growing_data_heap;
|
||||||
data_heap *old_data_heap;
|
data_heap *old_data_heap;
|
||||||
|
@ -46,7 +43,7 @@ struct gc_state {
|
||||||
|
|
||||||
inline bool collecting_aging_p()
|
inline bool collecting_aging_p()
|
||||||
{
|
{
|
||||||
return data->have_aging_p() && collecting_gen == data->aging();
|
return collecting_gen == data->aging();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool collecting_tenured_p()
|
inline bool collecting_tenured_p()
|
||||||
|
@ -56,22 +53,21 @@ struct gc_state {
|
||||||
|
|
||||||
inline bool collecting_accumulation_gen_p()
|
inline bool collecting_accumulation_gen_p()
|
||||||
{
|
{
|
||||||
return ((data->have_aging_p()
|
return ((collecting_aging_p() && !collecting_aging_again)
|
||||||
&& collecting_gen == data->aging()
|
|| collecting_tenured_p());
|
||||||
&& !collecting_aging_again)
|
|
||||||
|| collecting_gen == data->tenured());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Strategy> struct copying_collector {
|
template<typename Strategy> struct copying_collector {
|
||||||
factor_vm *myvm;
|
factor_vm *myvm;
|
||||||
gc_state *current_gc;
|
gc_state *current_gc;
|
||||||
|
zone *newspace;
|
||||||
cell scan;
|
cell scan;
|
||||||
|
|
||||||
explicit copying_collector(factor_vm *myvm_);
|
explicit copying_collector(factor_vm *myvm_, zone *newspace);
|
||||||
Strategy &strategy();
|
Strategy &strategy();
|
||||||
object *copy_untagged_object_impl(object *pointer, cell size);
|
object *copy_untagged_object_impl(object *pointer, cell size);
|
||||||
cell copy_next(cell scan);
|
cell trace_next(cell scan);
|
||||||
object *copy_object_impl(object *untagged);
|
object *copy_object_impl(object *untagged);
|
||||||
object *resolve_forwarding(object *untagged);
|
object *resolve_forwarding(object *untagged);
|
||||||
cell copy_object(cell pointer);
|
cell copy_object(cell pointer);
|
||||||
|
|
|
@ -11,7 +11,7 @@ void factor_vm::init_card_decks()
|
||||||
decks_offset = (cell)data->decks - (start >> deck_bits);
|
decks_offset = (cell)data->decks - (start >> deck_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
data_heap::data_heap(factor_vm *myvm, cell gen_count_, cell young_size_, cell aging_size_, cell tenured_size_)
|
data_heap::data_heap(factor_vm *myvm, cell young_size_, cell aging_size_, cell tenured_size_)
|
||||||
{
|
{
|
||||||
young_size_ = align(young_size_,deck_size);
|
young_size_ = align(young_size_,deck_size);
|
||||||
aging_size_ = align(aging_size_,deck_size);
|
aging_size_ = align(aging_size_,deck_size);
|
||||||
|
@ -20,18 +20,8 @@ data_heap::data_heap(factor_vm *myvm, cell gen_count_, cell young_size_, cell ag
|
||||||
young_size = young_size_;
|
young_size = young_size_;
|
||||||
aging_size = aging_size_;
|
aging_size = aging_size_;
|
||||||
tenured_size = tenured_size_;
|
tenured_size = tenured_size_;
|
||||||
gen_count = gen_count_;
|
|
||||||
|
|
||||||
cell total_size;
|
cell total_size = young_size + 2 * aging_size + 2 * tenured_size;
|
||||||
if(gen_count == 2)
|
|
||||||
total_size = young_size + 2 * tenured_size;
|
|
||||||
else if(gen_count == 3)
|
|
||||||
total_size = young_size + 2 * aging_size + 2 * tenured_size;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
total_size = 0;
|
|
||||||
fatal_error("Invalid number of generations",gen_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
total_size += deck_size;
|
total_size += deck_size;
|
||||||
|
|
||||||
|
@ -56,17 +46,11 @@ data_heap::data_heap(factor_vm *myvm, cell gen_count_, cell young_size_, cell ag
|
||||||
alloter = generations[tenured()].init_zone(tenured_size,alloter);
|
alloter = generations[tenured()].init_zone(tenured_size,alloter);
|
||||||
alloter = semispaces[tenured()].init_zone(tenured_size,alloter);
|
alloter = semispaces[tenured()].init_zone(tenured_size,alloter);
|
||||||
|
|
||||||
if(gen_count == 3)
|
alloter = generations[aging()].init_zone(aging_size,alloter);
|
||||||
{
|
alloter = semispaces[aging()].init_zone(aging_size,alloter);
|
||||||
alloter = generations[aging()].init_zone(aging_size,alloter);
|
|
||||||
alloter = semispaces[aging()].init_zone(aging_size,alloter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(gen_count >= 2)
|
alloter = generations[nursery()].init_zone(young_size,alloter);
|
||||||
{
|
alloter = semispaces[nursery()].init_zone(0,alloter);
|
||||||
alloter = generations[nursery()].init_zone(young_size,alloter);
|
|
||||||
alloter = semispaces[nursery()].init_zone(0,alloter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(seg->end - alloter > deck_size)
|
if(seg->end - alloter > deck_size)
|
||||||
myvm->critical_error("Bug in alloc_data_heap",alloter);
|
myvm->critical_error("Bug in alloc_data_heap",alloter);
|
||||||
|
@ -77,7 +61,6 @@ data_heap *factor_vm::grow_data_heap(data_heap *data, cell requested_bytes)
|
||||||
cell new_tenured_size = (data->tenured_size * 2) + requested_bytes;
|
cell new_tenured_size = (data->tenured_size * 2) + requested_bytes;
|
||||||
|
|
||||||
return new data_heap(this,
|
return new data_heap(this,
|
||||||
data->gen_count,
|
|
||||||
data->young_size,
|
data->young_size,
|
||||||
data->aging_size,
|
data->aging_size,
|
||||||
new_tenured_size);
|
new_tenured_size);
|
||||||
|
@ -149,9 +132,9 @@ void factor_vm::set_data_heap(data_heap *data_)
|
||||||
clear_allot_markers(data->nursery(),data->tenured());
|
clear_allot_markers(data->nursery(),data->tenured());
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::init_data_heap(cell gens,cell young_size,cell aging_size,cell tenured_size,bool secure_gc_)
|
void factor_vm::init_data_heap(cell young_size, cell aging_size, cell tenured_size, bool secure_gc_)
|
||||||
{
|
{
|
||||||
set_data_heap(new data_heap(this,gens,young_size,aging_size,tenured_size));
|
set_data_heap(new data_heap(this,young_size,aging_size,tenured_size));
|
||||||
secure_gc = secure_gc_;
|
secure_gc = secure_gc_;
|
||||||
init_data_gc();
|
init_data_gc();
|
||||||
}
|
}
|
||||||
|
@ -257,7 +240,7 @@ void factor_vm::primitive_data_room()
|
||||||
growable_array a(this);
|
growable_array a(this);
|
||||||
|
|
||||||
cell gen;
|
cell gen;
|
||||||
for(gen = 0; gen < data->gen_count; gen++)
|
for(gen = 0; gen < gen_count; gen++)
|
||||||
{
|
{
|
||||||
zone *z = (gen == data->nursery() ? &nursery : &data->generations[gen]);
|
zone *z = (gen == data->nursery() ? &nursery : &data->generations[gen]);
|
||||||
a.add(tag_fixnum((z->end - z->here) >> 10));
|
a.add(tag_fixnum((z->end - z->here) >> 10));
|
||||||
|
|
|
@ -31,8 +31,6 @@ struct data_heap {
|
||||||
cell aging_size;
|
cell aging_size;
|
||||||
cell tenured_size;
|
cell tenured_size;
|
||||||
|
|
||||||
cell gen_count;
|
|
||||||
|
|
||||||
zone *generations;
|
zone *generations;
|
||||||
zone *semispaces;
|
zone *semispaces;
|
||||||
|
|
||||||
|
@ -49,17 +47,15 @@ struct data_heap {
|
||||||
cell nursery() { return 0; }
|
cell nursery() { return 0; }
|
||||||
|
|
||||||
/* where objects hang around */
|
/* where objects hang around */
|
||||||
cell aging() { return gen_count - 2; }
|
cell aging() { return 1; }
|
||||||
|
|
||||||
/* the oldest generation */
|
/* the oldest generation */
|
||||||
cell tenured() { return gen_count - 1; }
|
cell tenured() { return 2; }
|
||||||
|
|
||||||
bool have_aging_p() { return gen_count > 2; }
|
explicit data_heap(factor_vm *myvm, cell young_size, cell aging_size, cell tenured_size);
|
||||||
|
|
||||||
explicit data_heap(factor_vm *myvm, cell gen_count, cell young_size, cell aging_size, cell tenured_size);
|
|
||||||
~data_heap();
|
~data_heap();
|
||||||
};
|
};
|
||||||
|
|
||||||
static const cell max_gen_count = 3;
|
static const cell gen_count = 3;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -225,13 +225,13 @@ void factor_vm::dump_generations()
|
||||||
print_string("Nursery: ");
|
print_string("Nursery: ");
|
||||||
dump_zone(&nursery);
|
dump_zone(&nursery);
|
||||||
|
|
||||||
for(i = 1; i < data->gen_count; i++)
|
for(i = 1; i < gen_count; i++)
|
||||||
{
|
{
|
||||||
print_string("Generation "); print_cell(i); print_string(": ");
|
print_string("Generation "); print_cell(i); print_string(": ");
|
||||||
dump_zone(&data->generations[i]);
|
dump_zone(&data->generations[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < data->gen_count; i++)
|
for(i = 0; i < gen_count; i++)
|
||||||
{
|
{
|
||||||
print_string("Semispace "); print_cell(i); print_string(": ");
|
print_string("Semispace "); print_cell(i); print_string(": ");
|
||||||
dump_zone(&data->semispaces[i]);
|
dump_zone(&data->semispaces[i]);
|
||||||
|
|
|
@ -21,7 +21,6 @@ void factor_vm::default_parameters(vm_parameters *p)
|
||||||
p->ds_size = 8 * sizeof(cell);
|
p->ds_size = 8 * sizeof(cell);
|
||||||
p->rs_size = 8 * sizeof(cell);
|
p->rs_size = 8 * sizeof(cell);
|
||||||
|
|
||||||
p->gen_count = 2;
|
|
||||||
p->code_size = 4;
|
p->code_size = 4;
|
||||||
p->young_size = 1;
|
p->young_size = 1;
|
||||||
p->aging_size = 1;
|
p->aging_size = 1;
|
||||||
|
@ -30,7 +29,6 @@ void factor_vm::default_parameters(vm_parameters *p)
|
||||||
p->ds_size = 32 * sizeof(cell);
|
p->ds_size = 32 * sizeof(cell);
|
||||||
p->rs_size = 32 * sizeof(cell);
|
p->rs_size = 32 * sizeof(cell);
|
||||||
|
|
||||||
p->gen_count = 3;
|
|
||||||
p->code_size = 8 * sizeof(cell);
|
p->code_size = 8 * sizeof(cell);
|
||||||
p->young_size = sizeof(cell) / 4;
|
p->young_size = sizeof(cell) / 4;
|
||||||
p->aging_size = sizeof(cell) / 2;
|
p->aging_size = sizeof(cell) / 2;
|
||||||
|
@ -78,7 +76,6 @@ void factor_vm::init_parameters_from_args(vm_parameters *p, int argc, vm_char **
|
||||||
{
|
{
|
||||||
if(factor_arg(argv[i],STRING_LITERAL("-datastack=%d"),&p->ds_size));
|
if(factor_arg(argv[i],STRING_LITERAL("-datastack=%d"),&p->ds_size));
|
||||||
else if(factor_arg(argv[i],STRING_LITERAL("-retainstack=%d"),&p->rs_size));
|
else if(factor_arg(argv[i],STRING_LITERAL("-retainstack=%d"),&p->rs_size));
|
||||||
else if(factor_arg(argv[i],STRING_LITERAL("-generations=%d"),&p->gen_count));
|
|
||||||
else if(factor_arg(argv[i],STRING_LITERAL("-young=%d"),&p->young_size));
|
else if(factor_arg(argv[i],STRING_LITERAL("-young=%d"),&p->young_size));
|
||||||
else if(factor_arg(argv[i],STRING_LITERAL("-aging=%d"),&p->aging_size));
|
else if(factor_arg(argv[i],STRING_LITERAL("-aging=%d"),&p->aging_size));
|
||||||
else if(factor_arg(argv[i],STRING_LITERAL("-tenured=%d"),&p->tenured_size));
|
else if(factor_arg(argv[i],STRING_LITERAL("-tenured=%d"),&p->tenured_size));
|
||||||
|
|
|
@ -21,8 +21,7 @@ void factor_vm::load_data_heap(FILE *file, image_header *h, vm_parameters *p)
|
||||||
if(good_size > p->tenured_size)
|
if(good_size > p->tenured_size)
|
||||||
p->tenured_size = good_size;
|
p->tenured_size = good_size;
|
||||||
|
|
||||||
init_data_heap(p->gen_count,
|
init_data_heap(p->young_size,
|
||||||
p->young_size,
|
|
||||||
p->aging_size,
|
p->aging_size,
|
||||||
p->tenured_size,
|
p->tenured_size,
|
||||||
p->secure_gc);
|
p->secure_gc);
|
||||||
|
|
|
@ -32,7 +32,7 @@ struct vm_parameters {
|
||||||
const vm_char *image_path;
|
const vm_char *image_path;
|
||||||
const vm_char *executable_path;
|
const vm_char *executable_path;
|
||||||
cell ds_size, rs_size;
|
cell ds_size, rs_size;
|
||||||
cell gen_count, young_size, aging_size, tenured_size;
|
cell young_size, aging_size, tenured_size;
|
||||||
cell code_size;
|
cell code_size;
|
||||||
bool secure_gc;
|
bool secure_gc;
|
||||||
bool fep;
|
bool fep;
|
||||||
|
|
|
@ -24,8 +24,9 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
/* C++ headers */
|
/* C++ headers */
|
||||||
#include <vector>
|
#include <algorithm>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#if __GNUC__ == 4
|
#if __GNUC__ == 4
|
||||||
#include <tr1/unordered_map>
|
#include <tr1/unordered_map>
|
||||||
|
|
10
vm/vm.hpp
10
vm/vm.hpp
|
@ -157,7 +157,7 @@ struct factor_vm
|
||||||
void reset_generation(cell i);
|
void reset_generation(cell i);
|
||||||
void reset_generations(cell from, cell to);
|
void reset_generations(cell from, cell to);
|
||||||
void set_data_heap(data_heap *data_);
|
void set_data_heap(data_heap *data_);
|
||||||
void init_data_heap(cell gens,cell young_size,cell aging_size,cell tenured_size,bool secure_gc_);
|
void init_data_heap(cell young_size, cell aging_size, cell tenured_size, bool secure_gc_);
|
||||||
cell untagged_object_size(object *pointer);
|
cell untagged_object_size(object *pointer);
|
||||||
cell unaligned_object_size(object *pointer);
|
cell unaligned_object_size(object *pointer);
|
||||||
void primitive_size();
|
void primitive_size();
|
||||||
|
@ -231,7 +231,7 @@ struct factor_vm
|
||||||
/* used during garbage collection only */
|
/* used during garbage collection only */
|
||||||
gc_state *current_gc;
|
gc_state *current_gc;
|
||||||
/* statistics */
|
/* statistics */
|
||||||
gc_stats stats[max_gen_count];
|
gc_stats stats[gen_count];
|
||||||
u64 cards_scanned;
|
u64 cards_scanned;
|
||||||
u64 decks_scanned;
|
u64 decks_scanned;
|
||||||
u64 card_scan_time;
|
u64 card_scan_time;
|
||||||
|
@ -255,11 +255,11 @@ struct factor_vm
|
||||||
template<typename Strategy> void mark_object_code_block(object *object, Strategy &strategy);
|
template<typename Strategy> void mark_object_code_block(object *object, Strategy &strategy);
|
||||||
void free_unmarked_code_blocks();
|
void free_unmarked_code_blocks();
|
||||||
void update_dirty_code_blocks();
|
void update_dirty_code_blocks();
|
||||||
void begin_gc(cell requested_bytes);
|
|
||||||
void collect_nursery();
|
void collect_nursery();
|
||||||
void collect_aging();
|
void collect_aging();
|
||||||
void collect_tenured(bool trace_contexts_);
|
void collect_aging_again();
|
||||||
void end_gc();
|
void collect_tenured(cell requested_bytes, bool trace_contexts_);
|
||||||
|
void record_gc_stats();
|
||||||
void garbage_collection(cell gen, bool growing_data_heap, bool trace_contexts, cell requested_bytes);
|
void garbage_collection(cell gen, bool growing_data_heap, bool trace_contexts, cell requested_bytes);
|
||||||
void gc();
|
void gc();
|
||||||
void primitive_gc();
|
void primitive_gc();
|
||||||
|
|
Loading…
Reference in New Issue