<login-config> <factor-boilerplate> test-db <alloy> "concatenative.org" add-responder
<pastebin> <login-config> <factor-boilerplate> test-db <alloy> "paste.factorcode.org" add-responder
<planet> <login-config> <factor-boilerplate> test-db <alloy> "planet.factorcode.org" add-responder
- home "docs" append-path <help-webapp> test-db <alloy> "docs.factorcode.org" add-responder
+ home "docs" append-path <help-webapp> "docs.factorcode.org" add-responder
home "cgi" append-path <gitweb> "gitweb.factorcode.org" add-responder
<mason-app> "builds.factorcode.org" add-responder
main-responder set-global ;
void factor_vm::init_code_heap(cell size)
{
code = new code_heap(secure_gc,size);
+ code->youngest_referenced_generation = nursery_gen;
}
bool factor_vm::in_code_heap_p(cell ptr)
namespace factor
{
-void factor_vm::init_data_gc()
-{
- code->youngest_referenced_generation = nursery_gen;
-}
-
gc_state::gc_state(data_heap *data_, bool growing_data_heap_, cell collecting_gen_) :
data(data_),
growing_data_heap(growing_data_heap_),
return newpointer;
}
-template<typename Strategy> void factor_vm::trace_card(card *ptr, cell gen, cell here, Strategy &strategy)
+template<typename Strategy> void factor_vm::trace_card(card *ptr, cell here, Strategy &strategy)
{
cell card_scan = card_to_addr(ptr) + card_offset(ptr);
cell card_end = card_to_addr(ptr + 1);
- if(here < card_end)
- card_end = here;
+ if(here < card_end) card_end = here;
strategy.copy_reachable_objects(card_scan,&card_end);
gc_stats.cards_scanned++;
}
-template<typename Strategy> void factor_vm::trace_card_deck(card_deck *deck, cell gen, card mask, card unmask, Strategy &strategy)
+template<typename Strategy> void factor_vm::trace_card_deck(card_deck *deck, cell here, card mask, card unmask, Strategy &strategy)
{
card *first_card = deck_to_card(deck);
card *last_card = deck_to_card(deck + 1);
- cell here = data->generations[gen].here;
-
u32 *quad_ptr;
u32 quad_mask = mask | (mask << 8) | (mask << 16) | (mask << 24);
{
if(ptr[card] & mask)
{
- trace_card(&ptr[card],gen,here,strategy);
+ trace_card(&ptr[card],here,strategy);
ptr[card] &= ~unmask;
}
}
}
/* 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_cards(cell gen, zone *z, Strategy &strategy)
{
- card_deck *first_deck = addr_to_deck(data->generations[gen].start);
- card_deck *last_deck = addr_to_deck(data->generations[gen].end);
+ u64 start_time = current_micros();
+
+ card_deck *first_deck = addr_to_deck(z->start);
+ card_deck *last_deck = addr_to_deck(z->end);
card mask, unmask;
{
if(*ptr & mask)
{
- trace_card_deck(ptr,gen,mask,unmask,strategy);
+ trace_card_deck(ptr,z->here,mask,unmask,strategy);
*ptr &= ~unmask;
}
}
-}
-
-/* Scan cards in all generations older than the one being collected, copying
-old->new references */
-template<typename Strategy> void factor_vm::trace_cards(Strategy &strategy)
-{
- u64 start = current_micros();
- cell i;
- for(i = current_gc->collecting_gen + 1; i < gen_count; i++)
- trace_generation_cards(i,strategy);
-
- gc_stats.card_scan_time += (current_micros() - start);
+ gc_stats.card_scan_time += (current_micros() - start_time);
}
/* Copy all tagged pointers in a range of memory */
explicit aging_collector(factor_vm *myvm_, zone *newspace_) :
copying_collector<aging_collector>(myvm_,newspace_),
- tenured(&myvm->data->generations[tenured_gen]) {}
+ tenured(myvm->data->tenured) {}
bool should_copy_p(object *untagged)
{
void factor_vm::collect_nursery()
{
- nursery_collector collector(this,&data->generations[aging_gen]);
+ nursery_collector collector(this,data->aging);
trace_roots(collector);
trace_contexts(collector);
- trace_cards(collector);
+ trace_cards(tenured_gen,data->tenured,collector);
+ trace_cards(aging_gen,data->aging,collector);
trace_code_heap_roots(collector);
collector.go();
update_dirty_code_blocks();
void factor_vm::collect_aging()
{
- std::swap(data->generations[aging_gen],data->semispaces[aging_gen]);
- reset_generation(aging_gen);
+ std::swap(data->aging,data->aging_semispace);
+ reset_generation(data->aging);
- aging_collector collector(this,&data->generations[aging_gen]);
+ aging_collector collector(this,data->aging);
trace_roots(collector);
trace_contexts(collector);
- trace_cards(collector);
+ trace_cards(tenured_gen,data->tenured,collector);
trace_code_heap_roots(collector);
collector.go();
update_dirty_code_blocks();
void factor_vm::collect_aging_again()
{
- aging_again_collector collector(this,&data->generations[tenured_gen]);
+ aging_again_collector collector(this,data->tenured);
trace_roots(collector);
trace_contexts(collector);
- trace_cards(collector);
+ trace_cards(tenured_gen,data->tenured,collector);
trace_code_heap_roots(collector);
collector.go();
update_dirty_code_blocks();
- reset_generation(aging_gen);
+ reset_generation(data->aging);
nursery.here = nursery.start;
}
}
else
{
- std::swap(data->generations[tenured_gen],data->semispaces[tenured_gen]);
- reset_generation(tenured_gen);
+ std::swap(data->tenured,data->tenured_semispace);
+ reset_generation(data->tenured);
}
- tenured_collector collector(this,&data->generations[tenured_gen]);
+ tenured_collector collector(this,data->tenured);
trace_roots(collector);
if(trace_contexts_) trace_contexts(collector);
collector.go();
free_unmarked_code_blocks();
- reset_generation(aging_gen);
+ reset_generation(data->aging);
nursery.here = nursery.start;
if(current_gc->growing_data_heap)
tenured space */
else
{
- zone *tenured = &data->generations[tenured_gen];
-
/* If tenured space does not have enough room, collect */
- if(tenured->here + size > tenured->end)
- {
+ if(data->tenured->here + size > data->tenured->end)
gc();
- tenured = &data->generations[tenured_gen];
- }
/* If it still won't fit, grow the heap */
- if(tenured->here + size > tenured->end)
- {
+ if(data->tenured->here + size > data->tenured->end)
garbage_collection(tenured_gen,true,true,size);
- tenured = &data->generations[tenured_gen];
- }
- obj = tenured->allot(size);
+ obj = data->tenured->allot(size);
allot_barrier(obj);
/* Allows initialization code to store old->new pointers
seg = new segment(total_size);
- generations = new zone[gen_count];
- semispaces = new zone[gen_count];
-
cell cards_size = total_size >> card_bits;
- allot_markers = new char[cards_size];
- allot_markers_end = allot_markers + cards_size;
cards = new char[cards_size];
cards_end = cards + cards_size;
decks = new char[decks_size];
decks_end = decks + decks_size;
+ allot_markers = new char[cards_size];
+ allot_markers_end = allot_markers + cards_size;
+
cell alloter = align(seg->start,deck_size);
- alloter = generations[tenured_gen].init_zone(tenured_size,alloter);
- alloter = semispaces[tenured_gen].init_zone(tenured_size,alloter);
+ tenured = new zone;
+ tenured_semispace = new zone;
+ alloter = tenured->init_zone(tenured_size,alloter);
+ alloter = tenured_semispace->init_zone(tenured_size,alloter);
- alloter = generations[aging_gen].init_zone(aging_size,alloter);
- alloter = semispaces[aging_gen].init_zone(aging_size,alloter);
+ aging = new zone;
+ aging_semispace = new zone;
+ alloter = aging->init_zone(aging_size,alloter);
+ alloter = aging_semispace->init_zone(aging_size,alloter);
- alloter = generations[nursery_gen].init_zone(young_size,alloter);
- alloter = semispaces[nursery_gen].init_zone(0,alloter);
+ nursery = new zone;
+ alloter = nursery->init_zone(young_size,alloter);
if(seg->end - alloter > deck_size)
critical_error("Bug in alloc_data_heap",alloter);
}
+data_heap::~data_heap()
+{
+ delete seg;
+ delete nursery;
+ delete aging;
+ delete aging_semispace;
+ delete tenured;
+ delete tenured_semispace;
+ delete[] allot_markers;
+ delete[] cards;
+ delete[] decks;
+}
+
data_heap *factor_vm::grow_data_heap(data_heap *data, cell requested_bytes)
{
cell new_tenured_size = (data->tenured_size * 2) + requested_bytes;
new_tenured_size);
}
-data_heap::~data_heap()
-{
- delete seg;
- delete[] generations;
- delete[] semispaces;
- delete[] allot_markers;
- delete[] cards;
- delete[] decks;
-}
-
-void factor_vm::clear_cards(cell gen)
+void factor_vm::clear_cards(zone *gen)
{
/* NOTE: reverse order due to heap layout. */
- card *first_card = addr_to_card(data->generations[gen].start);
- card *last_card = addr_to_card(data->generations[gen].end);
+ card *first_card = addr_to_card(gen->start);
+ card *last_card = addr_to_card(gen->end);
memset(first_card,0,last_card - first_card);
}
-void factor_vm::clear_decks(cell gen)
+void factor_vm::clear_decks(zone *gen)
{
/* NOTE: reverse order due to heap layout. */
- card_deck *first_deck = addr_to_deck(data->generations[gen].start);
- card_deck *last_deck = addr_to_deck(data->generations[gen].end);
+ card_deck *first_deck = addr_to_deck(gen->start);
+ card_deck *last_deck = addr_to_deck(gen->end);
memset(first_deck,0,last_deck - first_deck);
}
-void factor_vm::clear_allot_markers(cell gen)
+void factor_vm::clear_allot_markers(zone *gen)
{
- card *first_card = addr_to_allot_marker((object *)data->generations[gen].start);
- card *last_card = addr_to_allot_marker((object *)data->generations[gen].end);
+ card *first_card = addr_to_allot_marker((object *)gen->start);
+ card *last_card = addr_to_allot_marker((object *)gen->end);
memset(first_card,invalid_allot_marker,last_card - first_card);
}
/* After garbage collection, any generations which are now empty need to have
their allocation pointers and cards reset. */
-void factor_vm::reset_generation(cell gen)
+void factor_vm::reset_generation(zone *gen)
{
- assert(gen != nursery_gen);
-
- zone *z = &data->generations[gen];
- z->here = z->start;
- if(secure_gc) memset((void*)z->start,69,z->size);
+ gen->here = gen->start;
+ if(secure_gc) memset((void*)gen->start,69,gen->size);
clear_cards(gen);
clear_decks(gen);
void factor_vm::set_data_heap(data_heap *data_)
{
data = data_;
- nursery = data->generations[nursery_gen];
+ nursery = *data->nursery;
nursery.here = nursery.start;
init_card_decks();
- reset_generation(aging_gen);
- reset_generation(tenured_gen);
+ reset_generation(data->aging);
+ reset_generation(data->tenured);
}
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,young_size,aging_size,tenured_size));
secure_gc = secure_gc_;
- init_data_gc();
}
/* Size of the object pointed to by a tagged pointer */
growable_array a(this);
- cell gen;
- for(gen = 0; gen < gen_count; gen++)
- {
- zone *z = (gen == nursery_gen ? &nursery : &data->generations[gen]);
- a.add(tag_fixnum((z->end - z->here) >> 10));
- a.add(tag_fixnum((z->size) >> 10));
- }
+ a.add(tag_fixnum((nursery.end - nursery.here) >> 10));
+ a.add(tag_fixnum((nursery.size) >> 10));
+
+ 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));
a.trim();
dpush(a.elements.value());
/* Disables GC and activates next-object ( -- obj ) primitive */
void factor_vm::begin_scan()
{
- heap_scan_ptr = data->generations[tenured_gen].start;
+ heap_scan_ptr = data->tenured->start;
gc_off = true;
}
if(!gc_off)
general_error(ERROR_HEAP_SCAN,F,F,NULL);
- if(heap_scan_ptr >= data->generations[tenured_gen].here)
+ if(heap_scan_ptr >= data->tenured->here)
return F;
object *obj = (object *)heap_scan_ptr;
end_scan();
}
-namespace
-{
-
struct word_counter {
cell count;
explicit word_counter() : count(0) {}
void operator()(tagged<object> obj) { if(obj.type_p(WORD_TYPE)) words.add(obj.value()); }
};
-}
-
cell factor_vm::find_all_words()
{
word_counter counter;
namespace factor
{
-/* generational copying GC divides memory into zones */
-struct zone {
- /* allocation pointer is 'here'; its offset is hardcoded in the
- compiler backends */
- cell start;
- cell here;
- cell size;
- cell end;
-
- cell init_zone(cell size_, cell start_)
- {
- size = size_;
- start = here = start_;
- end = start_ + size_;
- return end;
- }
-
- inline bool contains_p(object *pointer)
- {
- return ((cell)pointer - start) < size;
- }
-
- inline object *allot(cell size)
- {
- cell h = here;
- here = h + align8(size);
- return (object *)h;
- }
-};
-
struct data_heap {
- segment *seg;
-
cell young_size;
cell aging_size;
cell tenured_size;
- zone *generations;
- zone *semispaces;
+ segment *seg;
+
+ zone *nursery;
+ zone *aging;
+ zone *aging_semispace;
+ zone *tenured;
+ zone *tenured_semispace;
char *allot_markers;
char *allot_markers_end;
dump_cell(from);
}
-void factor_vm::dump_zone(zone *z)
+void factor_vm::dump_zone(cell gen, zone *z)
{
+ print_string("Generation "); print_cell(gen); 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();
void factor_vm::dump_generations()
{
- cell i;
-
- print_string("Nursery: ");
- dump_zone(&nursery);
-
- for(i = 1; i < gen_count; i++)
- {
- print_string("Generation "); print_cell(i); print_string(": ");
- dump_zone(&data->generations[i]);
- }
-
- for(i = 0; i < gen_count; i++)
- {
- print_string("Semispace "); print_cell(i); print_string(": ");
- dump_zone(&data->semispaces[i]);
- }
+ dump_zone(nursery_gen,&nursery);
+ dump_zone(aging_gen,data->aging);
+ dump_zone(tenured_gen,data->tenured);
print_string("Cards: base=");
print_cell((cell)data->cards);
--- /dev/null
+namespace factor
+{
+
+struct zone {
+ /* allocation pointer is 'here'; its offset is hardcoded in the
+ compiler backends */
+ cell start;
+ cell here;
+ cell size;
+ cell end;
+
+ cell init_zone(cell size_, cell start_)
+ {
+ size = size_;
+ start = here = start_;
+ end = start_ + size_;
+ return end;
+ }
+
+ inline bool contains_p(object *pointer)
+ {
+ return ((cell)pointer - start) < size;
+ }
+
+ inline object *allot(cell size)
+ {
+ cell h = here;
+ here = h + align8(size);
+ return (object *)h;
+ }
+};
+
+}
clear_gc_stats();
- zone *tenured = &data->generations[tenured_gen];
-
- fixnum bytes_read = fread((void*)tenured->start,1,h->data_size,file);
+ fixnum bytes_read = fread((void*)data->tenured->start,1,h->data_size,file);
if((cell)bytes_read != h->data_size)
{
fatal_error("load_data_heap failed",0);
}
- tenured->here = tenured->start + h->data_size;
+ data->tenured->here = data->tenured->start + h->data_size;
data_relocation_base = h->data_relocation_base;
}
return false;
}
- zone *tenured = &data->generations[tenured_gen];
-
h.magic = image_magic;
h.version = image_version;
- h.data_relocation_base = tenured->start;
- h.data_size = tenured->here - tenured->start;
+ h.data_relocation_base = data->tenured->start;
+ h.data_size = data->tenured->here - data->tenured->start;
h.code_relocation_base = code->seg->start;
h.code_size = code->heap_size();
bool ok = true;
if(fwrite(&h,sizeof(image_header),1,file) != 1) ok = false;
- if(fwrite((void*)tenured->start,h.data_size,1,file) != 1) ok = false;
+ if(fwrite((void*)data->tenured->start,h.data_size,1,file) != 1) ok = false;
if(fwrite(code->first_block(),h.code_size,1,file) != 1) ok = false;
if(fclose(file)) ok = false;
if(immediate_p(*cell))
return;
- zone *tenured = &data->generations[tenured_gen];
- *cell += (tenured->start - data_relocation_base);
+ *cell += (data->tenured->start - data_relocation_base);
}
template<typename Type> void factor_vm::code_fixup(Type **handle)
data_fixup(&bignum_pos_one);
data_fixup(&bignum_neg_one);
- zone *tenured = &data->generations[tenured_gen];
-
- for(relocating = tenured->start;
- relocating < tenured->here;
+ for(relocating = data->tenured->start;
+ relocating < data->tenured->here;
relocating += untagged_object_size((object *)relocating))
{
object *obj = (object *)relocating;
#include "bignumint.hpp"
#include "bignum.hpp"
#include "code_block.hpp"
+#include "gc/zone.hpp"
#include "data_heap.hpp"
#include "write_barrier.hpp"
#include "data_gc.hpp"
//data_heap
void init_card_decks();
data_heap *grow_data_heap(data_heap *data, cell requested_bytes);
- void clear_cards(cell gen);
- void clear_decks(cell gen);
- void clear_allot_markers(cell gen);
- void reset_generation(cell gen);
+ void clear_cards(zone *gen);
+ void clear_decks(zone *gen);
+ void clear_allot_markers(zone *gen);
+ void reset_generation(zone *gen);
void set_data_heap(data_heap *data_);
void init_data_heap(cell young_size, cell aging_size, cell tenured_size, bool secure_gc_);
cell untagged_object_size(object *pointer);
}
// data_gc
- void init_data_gc();
template<typename Strategy> object *resolve_forwarding(object *untagged, Strategy &strategy);
template<typename Strategy> void trace_handle(cell *handle, Strategy &strategy);
template<typename Strategy> object *promote_object(object *pointer, Strategy &strategy);
template<typename Strategy> void trace_slots(object *ptr, Strategy &strategy);
- template<typename Strategy> void trace_card(card *ptr, cell gen, cell here, Strategy &strategy);
- template<typename Strategy> void trace_card_deck(card_deck *deck, cell gen, card mask, card unmask, Strategy &strategy);
- template<typename Strategy> void trace_generation_cards(cell gen, Strategy &strategy);
- template<typename Strategy> void trace_cards(Strategy &strategy);
+ template<typename Strategy> void trace_card(card *ptr, cell here, Strategy &strategy);
+ template<typename Strategy> void trace_card_deck(card_deck *deck, cell here, card mask, card unmask, Strategy &strategy);
+ template<typename Strategy> void trace_cards(cell gen, zone *z, Strategy &strategy);
template<typename Strategy> void trace_stack_elements(segment *region, cell top, Strategy &strategy);
template<typename Strategy> void trace_registered_locals(Strategy &strategy);
template<typename Strategy> void trace_registered_bignums(Strategy &strategy);
void print_callstack();
void dump_cell(cell x);
void dump_memory(cell from, cell to);
- void dump_zone(zone *z);
+ void dump_zone(cell gen, zone *z);
void dump_generations();
void dump_objects(cell type);
void find_data_references_step(cell *scan);