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. */
{
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> {
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;
+ }
};
}
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;
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;
}
};
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()
object *untagged = parent->untag<object>(pointer);
if(!policy.should_copy_p(untagged))
+ {
+ policy.visited_object(untagged);
return;
+ }
object *forwarding = resolve_forwarding(untagged);
else if(policy.should_copy_p(forwarding))
untagged = promote_object(forwarding);
else
+ {
untagged = forwarding;
+ policy.visited_object(untagged);
+ }
*handle = RETAG(untagged,TAG(pointer));
}
stats->object_count++;
stats->bytes_copied += size;
+ policy.promoted_object(newpointer);
+
return newpointer;
}
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);
+ }
};
}
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);
}
}
};
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;
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);
}
delete aging;
delete aging_semispace;
delete tenured;
- delete tenured_semispace;
delete[] cards;
delete[] decks;
}
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)
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());
/* 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;
}
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 */
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;
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();
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);
};
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);
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)
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)
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;
+ }
+}
+
}
{
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,
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);
}
}
full_collector collector(this);
code->clear_mark_bits();
+ data->tenured->clear_mark_bits();
collector.trace_roots();
if(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;
}
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)
{
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_);
void trace_callbacks();
void trace_literal_references(code_block *compiled);
void mark_code_block(code_block *compiled);
- void cheneys_algorithm();
+ void mark_reachable_objects();
};
}
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 */
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)
{
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);
}
}
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();
#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"
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> {
--- /dev/null
+namespace factor
+{
+
+struct nursery_space : bump_allocator<object>
+{
+ nursery_space(cell size, cell start) : bump_allocator<object>(size,start) {}
+};
+
+}
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 *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();
+ }
- object *obj = bump_allocator::allot(size);
- starts.record_object_start_offset(obj);
- return obj;
+ 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);
}
};
{
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. */
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;
{
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();
};
}
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;
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);