From bc691eb1980b885c94ca2a07d9435432c7af72a2 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 7 Oct 2009 11:59:59 -0500 Subject: [PATCH] vm: replace generations array with individual instance variables referencing zone objects --- .../concatenative/concatenative.factor | 2 +- vm/code_heap.cpp | 1 + vm/data_gc.cpp | 82 +++++--------- vm/data_heap.cpp | 105 +++++++++--------- vm/data_heap.hpp | 41 ++----- vm/debug.cpp | 22 +--- vm/gc/zone.hpp | 33 ++++++ vm/image.cpp | 23 ++-- vm/master.hpp | 1 + vm/vm.hpp | 18 ++- 10 files changed, 144 insertions(+), 184 deletions(-) create mode 100644 vm/gc/zone.hpp diff --git a/extra/websites/concatenative/concatenative.factor b/extra/websites/concatenative/concatenative.factor index b5a29073cd..11b30a114c 100644 --- a/extra/websites/concatenative/concatenative.factor +++ b/extra/websites/concatenative/concatenative.factor @@ -97,7 +97,7 @@ SYMBOL: dh-file test-db "concatenative.org" add-responder test-db "paste.factorcode.org" add-responder test-db "planet.factorcode.org" add-responder - home "docs" append-path test-db "docs.factorcode.org" add-responder + home "docs" append-path "docs.factorcode.org" add-responder home "cgi" append-path "gitweb.factorcode.org" add-responder "builds.factorcode.org" add-responder main-responder set-global ; diff --git a/vm/code_heap.cpp b/vm/code_heap.cpp index f07639d9bb..6a5391a589 100755 --- a/vm/code_heap.cpp +++ b/vm/code_heap.cpp @@ -27,6 +27,7 @@ void code_heap::code_heap_free(code_block *compiled) 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) diff --git a/vm/data_gc.cpp b/vm/data_gc.cpp index 47effccf85..b3836e4a3b 100755 --- a/vm/data_gc.cpp +++ b/vm/data_gc.cpp @@ -3,11 +3,6 @@ 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_), @@ -81,26 +76,23 @@ template object *factor_vm::promote_object(object *untagged, return newpointer; } -template void factor_vm::trace_card(card *ptr, cell gen, cell here, Strategy &strategy) +template 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 void factor_vm::trace_card_deck(card_deck *deck, cell gen, card mask, card unmask, Strategy &strategy) +template 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); @@ -115,7 +107,7 @@ template void factor_vm::trace_card_deck(card_deck *deck, cel { if(ptr[card] & mask) { - trace_card(&ptr[card],gen,here,strategy); + trace_card(&ptr[card],here,strategy); ptr[card] &= ~unmask; } } @@ -126,10 +118,12 @@ template void factor_vm::trace_card_deck(card_deck *deck, cel } /* Trace all objects referenced from marked cards */ -template void factor_vm::trace_generation_cards(cell gen, Strategy &strategy) +template 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; @@ -185,23 +179,12 @@ template void factor_vm::trace_generation_cards(cell gen, Str { 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 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 */ @@ -482,7 +465,7 @@ struct aging_collector : copying_collector explicit aging_collector(factor_vm *myvm_, zone *newspace_) : copying_collector(myvm_,newspace_), - tenured(&myvm->data->generations[tenured_gen]) {} + tenured(myvm->data->tenured) {} bool should_copy_p(object *untagged) { @@ -536,11 +519,12 @@ struct tenured_collector : copying_collector 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(); @@ -550,14 +534,14 @@ void factor_vm::collect_nursery() 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(); @@ -567,16 +551,16 @@ void factor_vm::collect_aging() 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; } @@ -589,18 +573,18 @@ void factor_vm::collect_tenured(cell requested_bytes, bool trace_contexts_) } 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) @@ -798,23 +782,15 @@ object *factor_vm::allot_object(header header, cell size) 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 diff --git a/vm/data_heap.cpp b/vm/data_heap.cpp index 5ccde31f37..4fc9770c55 100755 --- a/vm/data_heap.cpp +++ b/vm/data_heap.cpp @@ -27,12 +27,7 @@ data_heap::data_heap(factor_vm *myvm, cell young_size_, cell aging_size_, cell t 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; @@ -41,21 +36,41 @@ data_heap::data_heap(factor_vm *myvm, cell young_size_, cell aging_size_, cell t 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; @@ -66,48 +81,35 @@ data_heap *factor_vm::grow_data_heap(data_heap *data, cell 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); @@ -117,18 +119,17 @@ void factor_vm::reset_generation(cell 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 */ @@ -231,13 +232,14 @@ void factor_vm::primitive_data_room() 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()); @@ -246,7 +248,7 @@ void factor_vm::primitive_data_room() /* 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; } @@ -265,7 +267,7 @@ cell factor_vm::next_object() 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; @@ -294,9 +296,6 @@ template void factor_vm::each_object(Iterator &iterator) end_scan(); } -namespace -{ - struct word_counter { cell count; explicit word_counter() : count(0) {} @@ -309,8 +308,6 @@ struct word_accumulator { void operator()(tagged obj) { if(obj.type_p(WORD_TYPE)) words.add(obj.value()); } }; -} - cell factor_vm::find_all_words() { word_counter counter; diff --git a/vm/data_heap.hpp b/vm/data_heap.hpp index cd53d66768..891d1361ed 100755 --- a/vm/data_heap.hpp +++ b/vm/data_heap.hpp @@ -1,45 +1,18 @@ 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; diff --git a/vm/debug.cpp b/vm/debug.cpp index e1c1fa5a85..5460a309fd 100755 --- a/vm/debug.cpp +++ b/vm/debug.cpp @@ -211,8 +211,9 @@ void factor_vm::dump_memory(cell from, cell to) 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(); @@ -220,22 +221,9 @@ void factor_vm::dump_zone(zone *z) 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); diff --git a/vm/gc/zone.hpp b/vm/gc/zone.hpp new file mode 100644 index 0000000000..a05afd45c6 --- /dev/null +++ b/vm/gc/zone.hpp @@ -0,0 +1,33 @@ +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; + } +}; + +} diff --git a/vm/image.cpp b/vm/image.cpp index 5af8790506..9a70937508 100755 --- a/vm/image.cpp +++ b/vm/image.cpp @@ -28,9 +28,7 @@ void factor_vm::load_data_heap(FILE *file, image_header *h, vm_parameters *p) 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) { @@ -42,7 +40,7 @@ void factor_vm::load_data_heap(FILE *file, image_header *h, vm_parameters *p) 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; } @@ -85,12 +83,10 @@ bool factor_vm::save_image(const vm_char *filename) 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(); @@ -105,7 +101,7 @@ bool factor_vm::save_image(const vm_char *filename) 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; @@ -156,8 +152,7 @@ void factor_vm::data_fixup(cell *cell) 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 void factor_vm::code_fixup(Type **handle) @@ -280,10 +275,8 @@ void factor_vm::relocate_data() 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; diff --git a/vm/master.hpp b/vm/master.hpp index 457dbee0ab..d942c1a3ac 100755 --- a/vm/master.hpp +++ b/vm/master.hpp @@ -69,6 +69,7 @@ namespace factor #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" diff --git a/vm/vm.hpp b/vm/vm.hpp index 0ad1303156..9836342fe2 100755 --- a/vm/vm.hpp +++ b/vm/vm.hpp @@ -211,10 +211,10 @@ struct factor_vm //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); @@ -285,15 +285,13 @@ struct factor_vm } // data_gc - void init_data_gc(); template object *resolve_forwarding(object *untagged, Strategy &strategy); template void trace_handle(cell *handle, Strategy &strategy); template object *promote_object(object *pointer, Strategy &strategy); template void trace_slots(object *ptr, Strategy &strategy); - template void trace_card(card *ptr, cell gen, cell here, Strategy &strategy); - template void trace_card_deck(card_deck *deck, cell gen, card mask, card unmask, Strategy &strategy); - template void trace_generation_cards(cell gen, Strategy &strategy); - template void trace_cards(Strategy &strategy); + template void trace_card(card *ptr, cell here, Strategy &strategy); + template void trace_card_deck(card_deck *deck, cell here, card mask, card unmask, Strategy &strategy); + template void trace_cards(cell gen, zone *z, Strategy &strategy); template void trace_stack_elements(segment *region, cell top, Strategy &strategy); template void trace_registered_locals(Strategy &strategy); template void trace_registered_bignums(Strategy &strategy); @@ -368,7 +366,7 @@ struct factor_vm 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);