vm: mark sweep gc for tenured space work in progress

db4
Slava Pestov 2009-10-20 22:20:49 -05:00
parent f0816d72f1
commit 814f6371d6
22 changed files with 420 additions and 251 deletions

View File

@ -25,7 +25,7 @@ void factor_vm::collect_aging()
collector.trace_cards(data->tenured,
card_points_to_aging,
simple_unmarker(card_mark_mask));
collector.cheneys_algorithm();
collector.tenure_reachable_objects();
}
{
/* If collection fails here, do a to_tenured collection. */

View File

@ -15,6 +15,10 @@ struct aging_policy {
{
return !(aging->contains_p(untagged) || tenured->contains_p(untagged));
}
void promoted_object(object *obj) {}
void visited_object(object *obj) {}
};
struct aging_collector : copying_collector<aging_space,aging_policy> {

View File

@ -1,20 +1,29 @@
namespace factor
{
struct aging_space : bump_allocator {
struct aging_space : bump_allocator<object> {
object_start_map starts;
aging_space(cell size, cell start) :
bump_allocator(size,start), starts(size,start) {}
bump_allocator<object>(size,start), starts(size,start) {}
object *allot(cell size)
{
if(here + size > end) return NULL;
object *obj = bump_allocator::allot(size);
object *obj = bump_allocator<object>::allot(size);
starts.record_object_start_offset(obj);
return obj;
}
cell next_object_after(cell scan)
{
cell size = ((object *)scan)->size();
if(scan + size < here)
return scan + size;
else
return 0;
}
};
}

View File

@ -1,7 +1,7 @@
namespace factor
{
struct bump_allocator {
template<typename Block> struct bump_allocator {
/* offset of 'here' and 'end' is hardcoded in compiler backends */
cell here;
cell start;
@ -9,27 +9,18 @@ struct bump_allocator {
cell size;
bump_allocator(cell size_, cell start_) :
here(0), start(start_), end(start_ + size_), size(size_) {}
here(start_), start(start_), end(start_ + size_), size(size_) {}
inline bool contains_p(object *pointer)
inline bool contains_p(Block *block)
{
return ((cell)pointer - start) < size;
return ((cell)block - start) < size;
}
inline object *allot(cell size)
inline Block *allot(cell size)
{
cell h = here;
here = h + align(size,data_alignment);
return (object *)h;
}
cell next_allocated_block_after(cell scan)
{
cell size = ((object *)scan)->size();
if(scan + size < here)
return scan + size;
else
return 0;
return (Block *)h;
}
};

View File

@ -8,7 +8,7 @@ code_heap::code_heap(cell size)
if(size > (1L << (sizeof(cell) * 8 - 6))) fatal_error("Heap too large",size);
seg = new segment(align_page(size),true);
if(!seg) fatal_error("Out of memory in heap allocator",size);
allocator = new free_list_allocator<heap_block>(seg->start,size);
allocator = new free_list_allocator<heap_block>(size,seg->start);
}
code_heap::~code_heap()

View File

@ -40,7 +40,10 @@ template<typename TargetGeneration, typename Policy> struct collector {
object *untagged = parent->untag<object>(pointer);
if(!policy.should_copy_p(untagged))
{
policy.visited_object(untagged);
return;
}
object *forwarding = resolve_forwarding(untagged);
@ -49,7 +52,10 @@ template<typename TargetGeneration, typename Policy> struct collector {
else if(policy.should_copy_p(forwarding))
untagged = promote_object(forwarding);
else
{
untagged = forwarding;
policy.visited_object(untagged);
}
*handle = RETAG(untagged,TAG(pointer));
}
@ -79,6 +85,8 @@ template<typename TargetGeneration, typename Policy> struct collector {
stats->object_count++;
stats->bytes_copied += size;
policy.promoted_object(newpointer);
return newpointer;
}
@ -145,6 +153,141 @@ template<typename TargetGeneration, typename Policy> struct collector {
ctx = ctx->next;
}
}
inline cell first_card_in_deck(cell deck)
{
return deck << (deck_bits - card_bits);
}
inline cell last_card_in_deck(cell deck)
{
return first_card_in_deck(deck + 1);
}
inline cell card_deck_for_address(cell a)
{
return addr_to_deck(a - this->data->start);
}
inline cell card_start_address(cell card)
{
return (card << card_bits) + this->data->start;
}
inline cell card_end_address(cell card)
{
return ((card + 1) << card_bits) + this->data->start;
}
void trace_partial_objects(cell start, cell end, cell card_start, cell card_end)
{
if(card_start < end)
{
start += sizeof(cell);
if(start < card_start) start = card_start;
if(end > card_end) end = card_end;
cell *slot_ptr = (cell *)start;
cell *end_ptr = (cell *)end;
if(slot_ptr != end_ptr)
{
for(; slot_ptr < end_ptr; slot_ptr++)
this->trace_handle(slot_ptr);
}
}
}
template<typename SourceGeneration, typename Unmarker>
void trace_cards(SourceGeneration *gen, card mask, Unmarker unmarker)
{
u64 start_time = current_micros();
card_deck *decks = this->data->decks;
card_deck *cards = this->data->cards;
cell gen_start_card = addr_to_card(gen->start - this->data->start);
cell first_deck = card_deck_for_address(gen->start);
cell last_deck = card_deck_for_address(gen->end);
cell start = 0, binary_start = 0, end = 0;
for(cell deck_index = first_deck; deck_index < last_deck; deck_index++)
{
if(decks[deck_index] & mask)
{
this->parent->gc_stats.decks_scanned++;
cell first_card = first_card_in_deck(deck_index);
cell last_card = last_card_in_deck(deck_index);
for(cell card_index = first_card; card_index < last_card; card_index++)
{
if(cards[card_index] & mask)
{
this->parent->gc_stats.cards_scanned++;
if(end < card_start_address(card_index))
{
start = gen->starts.find_object_containing_card(card_index - gen_start_card);
binary_start = start + this->parent->binary_payload_start((object *)start);
end = start + ((object *)start)->size();
}
#ifdef FACTOR_DEBUG
assert(addr_to_card(start - this->data->start) <= card_index);
assert(start < card_end_address(card_index));
#endif
scan_next_object: {
trace_partial_objects(
start,
binary_start,
card_start_address(card_index),
card_end_address(card_index));
if(end < card_end_address(card_index))
{
start = gen->next_object_after(start);
if(start)
{
binary_start = start + this->parent->binary_payload_start((object *)start);
end = start + ((object *)start)->size();
goto scan_next_object;
}
}
}
unmarker(&cards[card_index]);
if(!start) goto end;
}
}
unmarker(&decks[deck_index]);
}
}
end: this->parent->gc_stats.card_scan_time += (current_micros() - start_time);
}
/* Trace all literals referenced from a code block. Only for aging and nursery collections */
void trace_literal_references(code_block *compiled)
{
this->trace_handle(&compiled->owner);
this->trace_handle(&compiled->literals);
this->trace_handle(&compiled->relocation);
this->parent->gc_stats.code_blocks_scanned++;
}
void trace_code_heap_roots(std::set<code_block *> *remembered_set)
{
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);
}
};
}

View File

@ -18,147 +18,12 @@ struct copying_collector : collector<TargetGeneration,Policy> {
explicit copying_collector(factor_vm *parent_, generation_statistics *stats_, TargetGeneration *target_, Policy policy_) :
collector<TargetGeneration,Policy>(parent_,stats_,target_,policy_), scan(target_->here) {}
inline cell first_card_in_deck(cell deck)
{
return deck << (deck_bits - card_bits);
}
inline cell last_card_in_deck(cell deck)
{
return first_card_in_deck(deck + 1);
}
inline cell card_deck_for_address(cell a)
{
return addr_to_deck(a - this->data->start);
}
inline cell card_start_address(cell card)
{
return (card << card_bits) + this->data->start;
}
inline cell card_end_address(cell card)
{
return ((card + 1) << card_bits) + this->data->start;
}
void trace_partial_objects(cell start, cell end, cell card_start, cell card_end)
{
if(card_start < end)
{
start += sizeof(cell);
if(start < card_start) start = card_start;
if(end > card_end) end = card_end;
cell *slot_ptr = (cell *)start;
cell *end_ptr = (cell *)end;
if(slot_ptr != end_ptr)
{
for(; slot_ptr < end_ptr; slot_ptr++)
this->trace_handle(slot_ptr);
}
}
}
template<typename SourceGeneration, typename Unmarker>
void trace_cards(SourceGeneration *gen, card mask, Unmarker unmarker)
{
u64 start_time = current_micros();
card_deck *decks = this->data->decks;
card_deck *cards = this->data->cards;
cell gen_start_card = addr_to_card(gen->start - this->data->start);
cell first_deck = card_deck_for_address(gen->start);
cell last_deck = card_deck_for_address(gen->end);
cell start = 0, binary_start = 0, end = 0;
for(cell deck_index = first_deck; deck_index < last_deck; deck_index++)
{
if(decks[deck_index] & mask)
{
this->parent->gc_stats.decks_scanned++;
cell first_card = first_card_in_deck(deck_index);
cell last_card = last_card_in_deck(deck_index);
for(cell card_index = first_card; card_index < last_card; card_index++)
{
if(cards[card_index] & mask)
{
this->parent->gc_stats.cards_scanned++;
if(end < card_start_address(card_index))
{
start = gen->starts.find_object_containing_card(card_index - gen_start_card);
binary_start = start + this->parent->binary_payload_start((object *)start);
end = start + ((object *)start)->size();
}
#ifdef FACTOR_DEBUG
assert(addr_to_card(start - this->data->start) <= card_index);
assert(start < card_end_address(card_index));
#endif
scan_next_object: {
trace_partial_objects(
start,
binary_start,
card_start_address(card_index),
card_end_address(card_index));
if(end < card_end_address(card_index))
{
start = gen->next_allocated_block_after(start);
if(start)
{
binary_start = start + this->parent->binary_payload_start((object *)start);
end = start + ((object *)start)->size();
goto scan_next_object;
}
}
}
unmarker(&cards[card_index]);
if(!start) goto end;
}
}
unmarker(&decks[deck_index]);
}
}
end: this->parent->gc_stats.card_scan_time += (current_micros() - start_time);
}
/* Trace all literals referenced from a code block. Only for aging and nursery collections */
void trace_literal_references(code_block *compiled)
{
this->trace_handle(&compiled->owner);
this->trace_handle(&compiled->literals);
this->trace_handle(&compiled->relocation);
this->parent->gc_stats.code_blocks_scanned++;
}
void trace_code_heap_roots(std::set<code_block *> *remembered_set)
{
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()
{
while(scan && scan < this->target->here)
{
this->trace_slots((object *)scan);
scan = this->target->next_allocated_block_after(scan);
scan = this->target->next_object_after(scan);
}
}
};

View File

@ -19,7 +19,7 @@ data_heap::data_heap(cell young_size_, cell aging_size_, cell tenured_size_)
aging_size = aging_size_;
tenured_size = tenured_size_;
cell total_size = young_size + 2 * aging_size + 2 * tenured_size;
cell total_size = young_size + 2 * aging_size + tenured_size;
total_size += deck_size;
@ -29,20 +29,21 @@ data_heap::data_heap(cell young_size_, cell aging_size_, cell tenured_size_)
cards = new card[cards_size];
cards_end = cards + cards_size;
memset(cards,0,cards_size);
cell decks_size = addr_to_deck(total_size);
decks = new card_deck[decks_size];
decks_end = decks + decks_size;
memset(decks,0,decks_size);
start = align(seg->start,deck_size);
tenured = new tenured_space(tenured_size,start);
tenured_semispace = new tenured_space(tenured_size,tenured->end);
aging = new aging_space(aging_size,tenured_semispace->end);
aging = new aging_space(aging_size,tenured->end);
aging_semispace = new aging_space(aging_size,aging->end);
nursery = new bump_allocator(young_size,aging_semispace->end);
nursery = new nursery_space(young_size,aging_semispace->end);
assert(seg->end - nursery->end <= deck_size);
}
@ -54,7 +55,6 @@ data_heap::~data_heap()
delete aging;
delete aging_semispace;
delete tenured;
delete tenured_semispace;
delete[] cards;
delete[] decks;
}
@ -71,8 +71,6 @@ void factor_vm::set_data_heap(data_heap *data_)
nursery = *data->nursery;
nursery.here = nursery.start;
init_card_decks();
data->reset_generation(data->aging);
data->reset_generation(data->tenured);
}
void factor_vm::init_data_heap(cell young_size, cell aging_size, cell tenured_size)
@ -185,8 +183,11 @@ void factor_vm::primitive_data_room()
a.add(tag_fixnum((data->aging->end - data->aging->here) >> 10));
a.add(tag_fixnum((data->aging->size) >> 10));
a.add(tag_fixnum((data->tenured->end - data->tenured->here) >> 10));
a.add(tag_fixnum((data->tenured->size) >> 10));
//XXX
cell used, total_free, max_free;
data->tenured->usage(&used,&total_free,&max_free);
a.add(tag_fixnum(total_free >> 10));
a.add(tag_fixnum(used >> 10));
a.trim();
dpush(a.elements.value());
@ -195,7 +196,7 @@ void factor_vm::primitive_data_room()
/* Disables GC and activates next-object ( -- obj ) primitive */
void factor_vm::begin_scan()
{
heap_scan_ptr = data->tenured->start;
heap_scan_ptr = data->tenured->first_object();
gc_off = true;
}
@ -214,12 +215,14 @@ cell factor_vm::next_object()
if(!gc_off)
general_error(ERROR_HEAP_SCAN,false_object,false_object,NULL);
if(heap_scan_ptr >= data->tenured->here)
if(heap_scan_ptr)
{
cell current = heap_scan_ptr;
heap_scan_ptr = data->tenured->next_object_after(heap_scan_ptr);
return tag_dynamic((object *)current);
}
else
return false_object;
object *obj = (object *)heap_scan_ptr;
heap_scan_ptr += obj->size();
return tag_dynamic(obj);
}
/* Push object at heap scan cursor and advance; pushes f when done */

View File

@ -10,11 +10,10 @@ struct data_heap {
segment *seg;
bump_allocator *nursery;
nursery_space *nursery;
aging_space *aging;
aging_space *aging_semispace;
tenured_space *tenured;
tenured_space *tenured_semispace;
card *cards;
card *cards_end;
@ -49,7 +48,6 @@ 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();

View File

@ -209,19 +209,21 @@ void factor_vm::dump_memory(cell from, cell to)
dump_cell(from);
}
void factor_vm::dump_zone(const char *name, bump_allocator *z)
template<typename Generation>
void factor_vm::dump_generation(const char *name, Generation *gen)
{
print_string(name); print_string(": ");
print_string("Start="); print_cell(z->start);
print_string(", size="); print_cell(z->size);
print_string(", here="); print_cell(z->here - z->start); nl();
print_string("Start="); print_cell(gen->start);
print_string(", size="); print_cell(gen->size);
print_string(", end="); print_cell(gen->end);
nl();
}
void factor_vm::dump_generations()
{
dump_zone("Nursery",&nursery);
dump_zone("Aging",data->aging);
dump_zone("Tenured",data->tenured);
dump_generation("Nursery",&nursery);
dump_generation("Aging",data->aging);
dump_generation("Tenured",data->tenured);
print_string("Cards: base=");
print_cell((cell)data->cards);

View File

@ -9,29 +9,17 @@ struct free_list {
};
template<typename Block> struct free_list_allocator {
cell start;
cell size;
cell start;
cell end;
free_list free_blocks;
mark_bits<Block> state;
explicit free_list_allocator(cell start, cell size);
inline Block *first_block()
{
return (Block *)start;
}
inline Block *last_block()
{
return (Block *)end;
}
Block *next_block_after(heap_block *block)
{
return (Block *)((cell)block + block->size());
}
explicit free_list_allocator(cell size, cell start);
bool contains_p(Block *block);
Block *first_block();
Block *last_block();
Block *next_block_after(Block *block);
void clear_free_list();
void add_to_free_list(free_heap_block *block);
void build_free_list(cell size);
@ -42,35 +30,42 @@ template<typename Block> struct free_list_allocator {
void free(Block *block);
void usage(cell *used, cell *total_free, cell *max_free);
cell occupied();
void sweep();
template<typename Iterator> void sweep(Iterator &iter);
template<typename Iterator> void compact(Iterator &iter);
template<typename Iterator> void iterate(Iterator &iter)
{
Block *scan = first_block();
Block *end = last_block();
while(scan != end)
{
cell size = scan->size();
Block *next = (Block *)((cell)scan + size);
if(!scan->free_p()) iter(scan,size);
scan = next;
}
}
template<typename Iterator> void iterate(Iterator &iter);
};
template<typename Block>
free_list_allocator<Block>::free_list_allocator(cell size_, cell start_) :
size(size_), start(start_), end(start_ + size_), state(mark_bits<Block>(size_,start_))
{
clear_free_list();
}
template<typename Block> void free_list_allocator<Block>::clear_free_list()
{
memset(&free_blocks,0,sizeof(free_list));
}
template<typename Block>
free_list_allocator<Block>::free_list_allocator(cell start_, cell size_) :
start(start_), size(size_), end(start_ + size_), state(mark_bits<Block>(start_,size_))
template<typename Block> bool free_list_allocator<Block>::contains_p(Block *block)
{
clear_free_list();
return ((cell)block - start) < size;
}
template<typename Block> Block *free_list_allocator<Block>::first_block()
{
return (Block *)start;
}
template<typename Block> Block *free_list_allocator<Block>::last_block()
{
return (Block *)end;
}
template<typename Block> Block *free_list_allocator<Block>::next_block_after(Block *block)
{
return (Block *)((cell)block + block->size());
}
template<typename Block> void free_list_allocator<Block>::add_to_free_list(free_heap_block *block)
@ -234,8 +229,56 @@ template<typename Block> cell free_list_allocator<Block>::occupied()
return size;
}
/* After code GC, all live code blocks are marked, so any
which are not marked can be reclaimed. */
template<typename Block>
void free_list_allocator<Block>::sweep()
{
this->clear_free_list();
Block *prev = NULL;
Block *scan = this->first_block();
Block *end = this->last_block();
while(scan != end)
{
cell size = scan->size();
if(scan->free_p())
{
if(prev && prev->free_p())
{
free_heap_block *free_prev = (free_heap_block *)prev;
free_prev->set_size(free_prev->size() + size);
}
else
prev = scan;
}
else if(this->state.marked_p(scan))
{
if(prev && prev->free_p())
this->add_to_free_list((free_heap_block *)prev);
prev = scan;
}
else
{
if(prev && prev->free_p())
{
free_heap_block *free_prev = (free_heap_block *)prev;
free_prev->set_size(free_prev->size() + size);
}
else
{
((free_heap_block *)scan)->set_free();
prev = scan;
}
}
scan = (Block *)((cell)scan + size);
}
if(prev && prev->free_p())
this->add_to_free_list((free_heap_block *)prev);
}
template<typename Block>
template<typename Iterator>
void free_list_allocator<Block>::sweep(Iterator &iter)
@ -302,4 +345,20 @@ void free_list_allocator<Block>::compact(Iterator &iter)
this->build_free_list((cell)compactor.address - this->start);
}
template<typename Block>
template<typename Iterator>
void free_list_allocator<Block>::iterate(Iterator &iter)
{
Block *scan = first_block();
Block *end = last_block();
while(scan != end)
{
cell size = scan->size();
Block *next = (Block *)((cell)scan + size);
if(!scan->free_p()) iter(scan,size);
scan = next;
}
}
}

View File

@ -4,7 +4,7 @@ namespace factor
{
full_collector::full_collector(factor_vm *parent_) :
copying_collector<tenured_space,full_policy>(
collector<tenured_space,full_policy>(
parent_,
&parent_->gc_stats.full_stats,
parent_->data->tenured,
@ -89,18 +89,22 @@ void full_collector::trace_literal_references(code_block *compiled)
collections */
void full_collector::mark_code_block(code_block *compiled)
{
this->code->set_marked_p(compiled);
trace_literal_references(compiled);
if(!this->code->marked_p(compiled))
{
this->code->set_marked_p(compiled);
trace_literal_references(compiled);
}
}
void full_collector::cheneys_algorithm()
void full_collector::mark_reachable_objects()
{
while(scan && scan < target->here)
std::vector<object *> *mark_stack = &this->target->mark_stack;
while(!mark_stack->empty())
{
object *obj = (object *)scan;
object *obj = mark_stack->back();
mark_stack->pop_back();
this->trace_slots(obj);
this->mark_object_code_block(obj);
scan = target->next_allocated_block_after(scan);
}
}
@ -109,6 +113,7 @@ void factor_vm::collect_full_impl(bool trace_contexts_p)
full_collector collector(this);
code->clear_mark_bits();
data->tenured->clear_mark_bits();
collector.trace_roots();
if(trace_contexts_p)
@ -118,8 +123,9 @@ void factor_vm::collect_full_impl(bool trace_contexts_p)
collector.trace_callbacks();
}
collector.cheneys_algorithm();
collector.mark_reachable_objects();
data->tenured->sweep();
data->reset_generation(data->aging);
nursery.here = nursery.start;
}
@ -144,9 +150,6 @@ void factor_vm::collect_growing_heap(cell requested_bytes,
void factor_vm::collect_full(bool trace_contexts_p, bool compact_code_heap_p)
{
/* Copy all live objects to the tenured semispace. */
std::swap(data->tenured,data->tenured_semispace);
data->reset_generation(data->tenured);
collect_full_impl(trace_contexts_p);
if(compact_code_heap_p)

View File

@ -11,9 +11,20 @@ struct full_policy {
{
return !tenured->contains_p(untagged);
}
void promoted_object(object *obj)
{
tenured->mark_and_push(obj);
}
void visited_object(object *obj)
{
if(!tenured->marked_p(obj))
tenured->mark_and_push(obj);
}
};
struct full_collector : copying_collector<tenured_space,full_policy> {
struct full_collector : collector<tenured_space,full_policy> {
bool trace_contexts_p;
full_collector(factor_vm *parent_);
@ -22,7 +33,7 @@ struct full_collector : copying_collector<tenured_space,full_policy> {
void trace_callbacks();
void trace_literal_references(code_block *compiled);
void mark_code_block(code_block *compiled);
void cheneys_algorithm();
void mark_reachable_objects();
};
}

View File

@ -235,11 +235,13 @@ object *factor_vm::allot_object(header header, cell size)
else
{
/* If tenured space does not have enough room, collect */
if(data->tenured->here + size > data->tenured->end)
//XXX
//if(data->tenured->here + size > data->tenured->end)
primitive_full_gc();
/* If it still won't fit, grow the heap */
if(data->tenured->here + size > data->tenured->end)
//XXX
//if(data->tenured->here + size > data->tenured->end)
{
gc(collect_growing_heap_op,
size, /* requested size */

View File

@ -39,7 +39,7 @@ void factor_vm::load_data_heap(FILE *file, image_header *h, vm_parameters *p)
fatal_error("load_data_heap failed",0);
}
data->tenured->here = data->tenured->start + h->data_size;
data->tenured->build_free_list(h->data_size);
}
void factor_vm::load_code_heap(FILE *file, image_header *h, vm_parameters *p)
@ -203,7 +203,7 @@ void factor_vm::relocate_data(cell data_relocation_base, cell code_relocation_ba
{
relocate_object((object *)obj,data_relocation_base,code_relocation_base);
data->tenured->starts.record_object_start_offset((object *)obj);
obj = data->tenured->next_allocated_block_after(obj);
obj = data->tenured->next_object_after(obj);
}
}
@ -289,7 +289,7 @@ bool factor_vm::save_image(const vm_char *filename)
h.magic = image_magic;
h.version = image_version;
h.data_relocation_base = data->tenured->start;
h.data_size = data->tenured->here - data->tenured->start;
h.data_size = data->tenured->occupied();
h.code_relocation_base = code->seg->start;
h.code_size = code->allocator->occupied();

View File

@ -53,6 +53,7 @@ namespace factor
#include "free_list_allocator.hpp"
#include "write_barrier.hpp"
#include "object_start_map.hpp"
#include "nursery_space.hpp"
#include "aging_space.hpp"
#include "tenured_space.hpp"
#include "data_heap.hpp"

View File

@ -6,10 +6,14 @@ struct nursery_policy {
nursery_policy(factor_vm *parent_) : parent(parent_) {}
bool should_copy_p(object *untagged)
bool should_copy_p(object *obj)
{
return parent->nursery.contains_p(untagged);
return parent->nursery.contains_p(obj);
}
void promoted_object(object *obj) {}
void visited_object(object *obj) {}
};
struct nursery_collector : copying_collector<aging_space,nursery_policy> {

9
vm/nursery_space.hpp Normal file
View File

@ -0,0 +1,9 @@
namespace factor
{
struct nursery_space : bump_allocator<object>
{
nursery_space(cell size, cell start) : bump_allocator<object>(size,start) {}
};
}

View File

@ -1,19 +1,65 @@
namespace factor
{
struct tenured_space : bump_allocator {
struct tenured_space : free_list_allocator<object> {
object_start_map starts;
std::vector<object *> mark_stack;
tenured_space(cell size, cell start) :
bump_allocator(size,start), starts(size,start) {}
free_list_allocator<object>(size,start), starts(size,start) {}
object *allot(cell size)
{
if(here + size > end) return NULL;
object *obj = free_list_allocator<object>::allot(size);
if(obj)
{
starts.record_object_start_offset(obj);
return obj;
}
else
return NULL;
}
object *obj = bump_allocator::allot(size);
starts.record_object_start_offset(obj);
return obj;
object *first_allocated_block_after(object *block)
{
while(block != this->last_block() && block->free_p())
{
free_heap_block *free_block = (free_heap_block *)block;
block = (object *)((cell)free_block + free_block->size());
}
if(block == this->last_block())
return NULL;
else
return block;
}
cell first_object()
{
return (cell)first_allocated_block_after(this->first_block());
}
cell next_object_after(cell scan)
{
cell size = ((object *)scan)->size();
object *next = (object *)(scan + size);
return (cell)first_allocated_block_after(next);
}
void clear_mark_bits()
{
state.clear_mark_bits();
}
bool marked_p(object *obj)
{
return this->state.marked_p(obj);
}
void mark_and_push(object *obj)
{
this->state.set_marked_p(obj);
this->mark_stack.push_back(obj);
}
};

View File

@ -4,12 +4,23 @@ namespace factor
{
to_tenured_collector::to_tenured_collector(factor_vm *myvm_) :
copying_collector<tenured_space,to_tenured_policy>(
collector<tenured_space,to_tenured_policy>(
myvm_,
&myvm_->gc_stats.aging_stats,
myvm_->data->tenured,
to_tenured_policy(myvm_)) {}
void to_tenured_collector::tenure_reachable_objects()
{
std::vector<object *> *mark_stack = &this->target->mark_stack;
while(!mark_stack->empty())
{
object *obj = mark_stack->back();
mark_stack->pop_back();
this->trace_slots(obj);
}
}
void factor_vm::collect_to_tenured()
{
/* Copy live objects from aging space to tenured space. */
@ -21,7 +32,7 @@ void factor_vm::collect_to_tenured()
card_points_to_aging,
dummy_unmarker());
collector.trace_code_heap_roots(&code->points_to_aging);
collector.cheneys_algorithm();
collector.tenure_reachable_objects();
update_code_heap_for_minor_gc(&code->points_to_aging);
nursery.here = nursery.start;

View File

@ -11,10 +11,18 @@ struct to_tenured_policy {
{
return !tenured->contains_p(untagged);
}
void promoted_object(object *obj)
{
tenured->mark_stack.push_back(obj);
}
void visited_object(object *obj) {}
};
struct to_tenured_collector : copying_collector<tenured_space,to_tenured_policy> {
struct to_tenured_collector : collector<tenured_space,to_tenured_policy> {
to_tenured_collector(factor_vm *myvm_);
void tenure_reachable_objects();
};
}

View File

@ -11,7 +11,7 @@ struct factor_vm
context *ctx;
/* New objects are allocated here */
bump_allocator nursery;
nursery_space nursery;
/* Add this to a shifted address to compute write barrier offsets */
cell cards_offset;
@ -308,7 +308,7 @@ struct factor_vm
void print_callstack();
void dump_cell(cell x);
void dump_memory(cell from, cell to);
void dump_zone(const char *name, bump_allocator *z);
template<typename Generation> void dump_generation(const char *name, Generation *gen);
void dump_generations();
void dump_objects(cell type);
void find_data_references_step(cell *scan);