vm: debugging mark-sweep
parent
814f6371d6
commit
af855b7fa9
|
@ -40,9 +40,10 @@ void factor_vm::collect_aging()
|
||||||
collector.trace_contexts();
|
collector.trace_contexts();
|
||||||
collector.trace_code_heap_roots(&code->points_to_aging);
|
collector.trace_code_heap_roots(&code->points_to_aging);
|
||||||
collector.cheneys_algorithm();
|
collector.cheneys_algorithm();
|
||||||
|
|
||||||
update_code_heap_for_minor_gc(&code->points_to_aging);
|
update_code_heap_for_minor_gc(&code->points_to_aging);
|
||||||
|
|
||||||
nursery.here = nursery.start;
|
data->reset_generation(&nursery);
|
||||||
code->points_to_nursery.clear();
|
code->points_to_nursery.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,11 +65,43 @@ data_heap *data_heap::grow(cell requested_bytes)
|
||||||
return new data_heap(young_size,aging_size,new_tenured_size);
|
return new data_heap(young_size,aging_size,new_tenured_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Generation> void data_heap::clear_cards(Generation *gen)
|
||||||
|
{
|
||||||
|
cell first_card = addr_to_card(gen->start - start);
|
||||||
|
cell last_card = addr_to_card(gen->end - start);
|
||||||
|
memset(&cards[first_card],0,last_card - first_card);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Generation> void data_heap::clear_decks(Generation *gen)
|
||||||
|
{
|
||||||
|
cell first_deck = addr_to_deck(gen->start - start);
|
||||||
|
cell last_deck = addr_to_deck(gen->end - start);
|
||||||
|
memset(&decks[first_deck],0,last_deck - first_deck);
|
||||||
|
}
|
||||||
|
|
||||||
|
void data_heap::reset_generation(nursery_space *gen)
|
||||||
|
{
|
||||||
|
gen->here = gen->start;
|
||||||
|
}
|
||||||
|
|
||||||
|
void data_heap::reset_generation(aging_space *gen)
|
||||||
|
{
|
||||||
|
gen->here = gen->start;
|
||||||
|
clear_cards(gen);
|
||||||
|
clear_decks(gen);
|
||||||
|
gen->starts.clear_object_start_offsets();
|
||||||
|
}
|
||||||
|
|
||||||
|
void data_heap::reset_generation(tenured_space *gen)
|
||||||
|
{
|
||||||
|
clear_cards(gen);
|
||||||
|
clear_decks(gen);
|
||||||
|
}
|
||||||
|
|
||||||
void factor_vm::set_data_heap(data_heap *data_)
|
void factor_vm::set_data_heap(data_heap *data_)
|
||||||
{
|
{
|
||||||
data = data_;
|
data = data_;
|
||||||
nursery = *data->nursery;
|
nursery = *data->nursery;
|
||||||
nursery.here = nursery.start;
|
|
||||||
init_card_decks();
|
init_card_decks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,31 +26,9 @@ struct data_heap {
|
||||||
data_heap *grow(cell requested_size);
|
data_heap *grow(cell requested_size);
|
||||||
template<typename Generation> void clear_cards(Generation *gen);
|
template<typename Generation> void clear_cards(Generation *gen);
|
||||||
template<typename Generation> void clear_decks(Generation *gen);
|
template<typename Generation> void clear_decks(Generation *gen);
|
||||||
template<typename Generation> void reset_generation(Generation *gen);
|
void reset_generation(nursery_space *gen);
|
||||||
|
void reset_generation(aging_space *gen);
|
||||||
|
void reset_generation(tenured_space *gen);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Generation> void data_heap::clear_cards(Generation *gen)
|
|
||||||
{
|
|
||||||
cell first_card = addr_to_card(gen->start - start);
|
|
||||||
cell last_card = addr_to_card(gen->end - start);
|
|
||||||
memset(&cards[first_card],0,last_card - first_card);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Generation> void data_heap::clear_decks(Generation *gen)
|
|
||||||
{
|
|
||||||
cell first_deck = addr_to_deck(gen->start - start);
|
|
||||||
cell last_deck = addr_to_deck(gen->end - start);
|
|
||||||
memset(&decks[first_deck],0,last_deck - first_deck);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* After garbage collection, any generations which are now empty need to have
|
|
||||||
their allocation pointers and cards reset. */
|
|
||||||
template<typename Generation> void data_heap::reset_generation(Generation *gen)
|
|
||||||
{
|
|
||||||
gen->here = gen->start;
|
|
||||||
clear_cards(gen);
|
|
||||||
clear_decks(gen);
|
|
||||||
gen->starts.clear_object_start_offsets();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,10 +88,12 @@ Makes a free list consisting of one free block, at the very end. */
|
||||||
template<typename Block> void free_list_allocator<Block>::build_free_list(cell size)
|
template<typename Block> void free_list_allocator<Block>::build_free_list(cell size)
|
||||||
{
|
{
|
||||||
clear_free_list();
|
clear_free_list();
|
||||||
|
if(size != this->size)
|
||||||
|
{
|
||||||
free_heap_block *last_block = (free_heap_block *)(start + size);
|
free_heap_block *last_block = (free_heap_block *)(start + size);
|
||||||
last_block->set_free();
|
last_block->make_free(end - (cell)last_block);
|
||||||
last_block->set_size(end - (cell)last_block);
|
|
||||||
add_to_free_list(last_block);
|
add_to_free_list(last_block);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Block> void free_list_allocator<Block>::assert_free_block(free_heap_block *block)
|
template<typename Block> void free_list_allocator<Block>::assert_free_block(free_heap_block *block)
|
||||||
|
@ -147,10 +149,9 @@ template<typename Block> free_heap_block *free_list_allocator<Block>::split_free
|
||||||
{
|
{
|
||||||
/* split the block in two */
|
/* split the block in two */
|
||||||
free_heap_block *split = (free_heap_block *)((cell)block + size);
|
free_heap_block *split = (free_heap_block *)((cell)block + size);
|
||||||
split->set_free();
|
split->make_free(block->size() - size);
|
||||||
split->set_size(block->size() - size);
|
|
||||||
split->next_free = block->next_free;
|
split->next_free = block->next_free;
|
||||||
block->set_size(size);
|
block->make_free(size);
|
||||||
add_to_free_list(split);
|
add_to_free_list(split);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +175,7 @@ template<typename Block> Block *free_list_allocator<Block>::allot(cell size)
|
||||||
template<typename Block> void free_list_allocator<Block>::free(Block *block)
|
template<typename Block> void free_list_allocator<Block>::free(Block *block)
|
||||||
{
|
{
|
||||||
free_heap_block *free_block = (free_heap_block *)block;
|
free_heap_block *free_block = (free_heap_block *)block;
|
||||||
free_block->set_free();
|
free_block->make_free(block->size());
|
||||||
add_to_free_list(free_block);
|
add_to_free_list(free_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +268,8 @@ void free_list_allocator<Block>::sweep()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
((free_heap_block *)scan)->set_free();
|
free_heap_block *free_block = (free_heap_block *)scan;
|
||||||
|
free_block->make_free(size);
|
||||||
prev = scan;
|
prev = scan;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -319,7 +321,8 @@ void free_list_allocator<Block>::sweep(Iterator &iter)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
scan->set_free();
|
free_heap_block *free_block = (free_heap_block *)scan;
|
||||||
|
free_block->make_free(size);
|
||||||
prev = scan;
|
prev = scan;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,12 +108,24 @@ void full_collector::mark_reachable_objects()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct object_start_map_updater {
|
||||||
|
object_start_map *starts;
|
||||||
|
|
||||||
|
object_start_map_updater(object_start_map *starts_) : starts(starts_) {}
|
||||||
|
|
||||||
|
void operator()(object *obj, cell size)
|
||||||
|
{
|
||||||
|
starts->record_object_start_offset(obj);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void factor_vm::collect_full_impl(bool trace_contexts_p)
|
void factor_vm::collect_full_impl(bool trace_contexts_p)
|
||||||
{
|
{
|
||||||
full_collector collector(this);
|
full_collector collector(this);
|
||||||
|
|
||||||
code->clear_mark_bits();
|
code->clear_mark_bits();
|
||||||
data->tenured->clear_mark_bits();
|
data->tenured->clear_mark_bits();
|
||||||
|
data->tenured->clear_mark_stack();
|
||||||
|
|
||||||
collector.trace_roots();
|
collector.trace_roots();
|
||||||
if(trace_contexts_p)
|
if(trace_contexts_p)
|
||||||
|
@ -125,9 +137,14 @@ void factor_vm::collect_full_impl(bool trace_contexts_p)
|
||||||
|
|
||||||
collector.mark_reachable_objects();
|
collector.mark_reachable_objects();
|
||||||
|
|
||||||
data->tenured->sweep();
|
data->tenured->starts.clear_object_start_offsets();
|
||||||
|
object_start_map_updater updater(&data->tenured->starts);
|
||||||
|
data->tenured->sweep(updater);
|
||||||
|
|
||||||
|
data->reset_generation(data->tenured);
|
||||||
data->reset_generation(data->aging);
|
data->reset_generation(data->aging);
|
||||||
nursery.here = nursery.start;
|
data->reset_generation(&nursery);
|
||||||
|
code->clear_remembered_set();
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::collect_growing_heap(cell requested_bytes,
|
void factor_vm::collect_growing_heap(cell requested_bytes,
|
||||||
|
@ -144,8 +161,6 @@ void factor_vm::collect_growing_heap(cell requested_bytes,
|
||||||
compact_code_heap(trace_contexts_p);
|
compact_code_heap(trace_contexts_p);
|
||||||
else
|
else
|
||||||
relocate_code_heap();
|
relocate_code_heap();
|
||||||
|
|
||||||
code->clear_remembered_set();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::collect_full(bool trace_contexts_p, bool compact_code_heap_p)
|
void factor_vm::collect_full(bool trace_contexts_p, bool compact_code_heap_p)
|
||||||
|
@ -156,8 +171,6 @@ void factor_vm::collect_full(bool trace_contexts_p, bool compact_code_heap_p)
|
||||||
compact_code_heap(trace_contexts_p);
|
compact_code_heap(trace_contexts_p);
|
||||||
else
|
else
|
||||||
update_code_heap_words_and_literals();
|
update_code_heap_words_and_literals();
|
||||||
|
|
||||||
code->clear_remembered_set();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,8 +58,6 @@ static const cell data_alignment = 16;
|
||||||
|
|
||||||
#define TYPE_COUNT 15
|
#define TYPE_COUNT 15
|
||||||
|
|
||||||
/* Not real types, but code_block's type can be set to this */
|
|
||||||
|
|
||||||
enum code_block_type
|
enum code_block_type
|
||||||
{
|
{
|
||||||
code_block_unoptimized,
|
code_block_unoptimized,
|
||||||
|
@ -229,30 +227,29 @@ struct heap_block
|
||||||
return header & 1 == 1;
|
return header & 1 == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_free()
|
|
||||||
{
|
|
||||||
header |= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear_free()
|
|
||||||
{
|
|
||||||
header &= ~1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cell size()
|
cell size()
|
||||||
{
|
{
|
||||||
return header >> 3;
|
cell bytes = header >> 3;
|
||||||
|
#ifdef FACTOR_DEBUG
|
||||||
|
assert(bytes > 0);
|
||||||
|
#endif
|
||||||
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_size(cell size)
|
void set_size(cell size)
|
||||||
{
|
{
|
||||||
header = (header & 0x7) | (size << 3);
|
header = ((header & 0x7) | (size << 3));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct free_heap_block : public heap_block
|
struct free_heap_block : public heap_block
|
||||||
{
|
{
|
||||||
free_heap_block *next_free;
|
free_heap_block *next_free;
|
||||||
|
|
||||||
|
void make_free(cell size)
|
||||||
|
{
|
||||||
|
header = (size << 3) | 1;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct code_block : public heap_block
|
struct code_block : public heap_block
|
||||||
|
|
|
@ -55,11 +55,6 @@ template<typename Block> struct mark_bits {
|
||||||
cell line_number = block_line(address);
|
cell line_number = block_line(address);
|
||||||
cell word_index = (line_number >> 6);
|
cell word_index = (line_number >> 6);
|
||||||
cell word_shift = (line_number & 63);
|
cell word_shift = (line_number & 63);
|
||||||
|
|
||||||
#ifdef FACTOR_DEBUG
|
|
||||||
assert(word_index < bits_size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return std::make_pair(word_index,word_shift);
|
return std::make_pair(word_index,word_shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ void factor_vm::collect_nursery()
|
||||||
collector.cheneys_algorithm();
|
collector.cheneys_algorithm();
|
||||||
update_code_heap_for_minor_gc(&code->points_to_nursery);
|
update_code_heap_for_minor_gc(&code->points_to_nursery);
|
||||||
|
|
||||||
nursery.here = nursery.start;
|
data->reset_generation(&nursery);
|
||||||
code->points_to_nursery.clear();
|
code->points_to_nursery.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,11 @@ struct tenured_space : free_list_allocator<object> {
|
||||||
state.clear_mark_bits();
|
state.clear_mark_bits();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clear_mark_stack()
|
||||||
|
{
|
||||||
|
mark_stack.clear();
|
||||||
|
}
|
||||||
|
|
||||||
bool marked_p(object *obj)
|
bool marked_p(object *obj)
|
||||||
{
|
{
|
||||||
return this->state.marked_p(obj);
|
return this->state.marked_p(obj);
|
||||||
|
|
|
@ -26,19 +26,20 @@ void factor_vm::collect_to_tenured()
|
||||||
/* Copy live objects from aging space to tenured space. */
|
/* Copy live objects from aging space to tenured space. */
|
||||||
to_tenured_collector collector(this);
|
to_tenured_collector collector(this);
|
||||||
|
|
||||||
|
data->tenured->clear_mark_stack();
|
||||||
|
|
||||||
collector.trace_roots();
|
collector.trace_roots();
|
||||||
collector.trace_contexts();
|
collector.trace_contexts();
|
||||||
collector.trace_cards(data->tenured,
|
collector.trace_cards(data->tenured,
|
||||||
card_points_to_aging,
|
card_points_to_aging,
|
||||||
dummy_unmarker());
|
simple_unmarker(card_mark_mask));
|
||||||
collector.trace_code_heap_roots(&code->points_to_aging);
|
collector.trace_code_heap_roots(&code->points_to_aging);
|
||||||
collector.tenure_reachable_objects();
|
collector.tenure_reachable_objects();
|
||||||
update_code_heap_for_minor_gc(&code->points_to_aging);
|
update_code_heap_for_minor_gc(&code->points_to_aging);
|
||||||
|
|
||||||
nursery.here = nursery.start;
|
data->reset_generation(&nursery);
|
||||||
data->reset_generation(data->aging);
|
data->reset_generation(data->aging);
|
||||||
code->points_to_nursery.clear();
|
code->clear_remembered_set();
|
||||||
code->points_to_aging.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue