From 83de156992924979181b4be991776518c36b5879 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 7 Oct 2009 15:48:09 -0500 Subject: [PATCH] vm: working on new object-oriented garbage collector --- Makefile | 5 ++ vm/aging_collector.cpp | 19 +++++ vm/aging_collector.hpp | 24 ++++++ vm/aging_space.hpp | 12 +++ vm/collector.hpp | 143 ++++++++++++++++++++++++++++++++ vm/copying_collector.hpp | 159 ++++++++++++++++++++++++++++++++++++ vm/data_gc.cpp | 46 +++++------ vm/data_gc.hpp | 4 +- vm/data_heap.cpp | 8 +- vm/data_heap.hpp | 8 +- vm/full_collector.cpp | 17 ++++ vm/full_collector.hpp | 23 ++++++ vm/master.hpp | 8 ++ vm/nursery_collector.cpp | 20 +++++ vm/nursery_collector.hpp | 20 +++++ vm/old_space.cpp | 54 ++++++++++++ vm/old_space.hpp | 53 ++---------- vm/tenured_space.hpp | 12 +++ vm/to_tenured_collector.cpp | 19 +++++ vm/to_tenured_collector.hpp | 21 +++++ vm/zone.hpp | 8 +- 21 files changed, 597 insertions(+), 86 deletions(-) create mode 100644 vm/aging_collector.cpp create mode 100644 vm/aging_collector.hpp create mode 100644 vm/aging_space.hpp create mode 100644 vm/collector.hpp create mode 100644 vm/copying_collector.hpp create mode 100644 vm/full_collector.cpp create mode 100644 vm/full_collector.hpp create mode 100644 vm/nursery_collector.cpp create mode 100644 vm/nursery_collector.hpp create mode 100644 vm/old_space.cpp create mode 100644 vm/tenured_space.hpp create mode 100644 vm/to_tenured_collector.cpp create mode 100644 vm/to_tenured_collector.hpp diff --git a/Makefile b/Makefile index 4c50787f2d..0b16233b63 100755 --- a/Makefile +++ b/Makefile @@ -31,6 +31,7 @@ ifdef CONFIG endif DLL_OBJS = $(PLAF_DLL_OBJS) \ + vm/aging_collector.o \ vm/alien.o \ vm/arrays.o \ vm/bignum.o \ @@ -46,17 +47,21 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \ vm/dispatch.o \ vm/errors.o \ vm/factor.o \ + vm/full_collector.o \ vm/heap.o \ vm/image.o \ vm/inline_cache.o \ vm/io.o \ vm/jit.o \ vm/math.o \ + vm/nursery_collector.o \ + vm/old_space.o \ vm/primitives.o \ vm/profiler.o \ vm/quotations.o \ vm/run.o \ vm/strings.o \ + vm/to_tenured_collector.o \ vm/tuples.o \ vm/utilities.o \ vm/vm.o \ diff --git a/vm/aging_collector.cpp b/vm/aging_collector.cpp new file mode 100644 index 0000000000..918d5e322d --- /dev/null +++ b/vm/aging_collector.cpp @@ -0,0 +1,19 @@ +#include "master.hpp" + +namespace factor +{ + +aging_collector::aging_collector(factor_vm *myvm_) : + copying_collector + (myvm_,myvm_->data->aging,aging_policy(myvm_)) {} + +void aging_collector::go() +{ + trace_roots(); + trace_contexts(); + trace_cards(data->tenured); + trace_code_heap_roots(); + cheneys_algorithm(); +} + +} diff --git a/vm/aging_collector.hpp b/vm/aging_collector.hpp new file mode 100644 index 0000000000..71b8938710 --- /dev/null +++ b/vm/aging_collector.hpp @@ -0,0 +1,24 @@ +namespace factor +{ + +struct aging_policy { + factor_vm *myvm; + zone *aging, *tenured; + + aging_policy(factor_vm *myvm_) : + myvm(myvm_), + aging(myvm->data->aging), + tenured(myvm->data->tenured) {} + + bool should_copy_p(object *untagged) + { + return !(aging->contains_p(untagged) || tenured->contains_p(untagged)); + } +}; + +struct aging_collector : copying_collector { + aging_collector(factor_vm *myvm_); + void go(); +}; + +} diff --git a/vm/aging_space.hpp b/vm/aging_space.hpp new file mode 100644 index 0000000000..743363b10c --- /dev/null +++ b/vm/aging_space.hpp @@ -0,0 +1,12 @@ +namespace factor +{ + +struct aging_space : old_space { + aging_space(cell size, cell start) : old_space(size,start) {} + + bool is_nursery_p() { return false; } + bool is_aging_p() { return true; } + bool is_tenured_p() { return false; } +}; + +} diff --git a/vm/collector.hpp b/vm/collector.hpp new file mode 100644 index 0000000000..06134dd9b7 --- /dev/null +++ b/vm/collector.hpp @@ -0,0 +1,143 @@ +namespace factor +{ + +template struct collector { + factor_vm *myvm; + data_heap *data; + gc_state *current_gc; + TargetGeneration *target; + Policy policy; + + explicit collector(factor_vm *myvm_, TargetGeneration *target_, Policy policy_) : + myvm(myvm_), + data(myvm_->data), + current_gc(myvm_->current_gc), + target(target_), + policy(policy_) {} + + object *resolve_forwarding(object *untagged) + { + myvm->check_data_pointer(untagged); + + /* is there another forwarding pointer? */ + while(untagged->h.forwarding_pointer_p()) + untagged = untagged->h.forwarding_pointer(); + + /* we've found the destination */ + untagged->h.check_header(); + return untagged; + } + + void trace_handle(cell *handle) + { + cell pointer = *handle; + + if(immediate_p(pointer)) return; + + object *untagged = myvm->untag(pointer); + if(!policy.should_copy_p(untagged)) + return; + + object *forwarding = resolve_forwarding(untagged); + + if(forwarding == untagged) + untagged = promote_object(untagged); + else if(policy.should_copy_p(forwarding)) + untagged = promote_object(forwarding); + else + untagged = forwarding; + + *handle = RETAG(untagged,TAG(pointer)); + } + + void trace_slots(object *ptr) + { + cell *slot = (cell *)ptr; + cell *end = (cell *)((cell)ptr + myvm->binary_payload_start(ptr)); + + if(slot != end) + { + slot++; + for(; slot < end; slot++) trace_handle(slot); + } + } + + object *promote_object(object *untagged) + { + cell size = myvm->untagged_object_size(untagged); + object *newpointer = target->allot(size); + /* XXX not exception-safe */ + if(!newpointer) longjmp(current_gc->gc_unwind,1); + + memcpy(newpointer,untagged,size); + untagged->h.forward_to(newpointer); + + return newpointer; + } + + void trace_stack_elements(segment *region, cell *top) + { + for(cell *ptr = (cell *)region->start; ptr <= top; ptr++) + trace_handle(ptr); + } + + void trace_registered_locals() + { + std::vector::const_iterator iter = myvm->gc_locals.begin(); + std::vector::const_iterator end = myvm->gc_locals.end(); + + for(; iter < end; iter++) + trace_handle((cell *)(*iter)); + } + + void trace_registered_bignums() + { + std::vector::const_iterator iter = myvm->gc_bignums.begin(); + std::vector::const_iterator end = myvm->gc_bignums.end(); + + for(; iter < end; iter++) + { + cell *handle = (cell *)(*iter); + + if(*handle) + { + *handle |= BIGNUM_TYPE; + trace_handle(handle); + *handle &= ~BIGNUM_TYPE; + } + } + } + + /* Copy roots over at the start of GC, namely various constants, stacks, + the user environment and extra roots registered by local_roots.hpp */ + void trace_roots() + { + trace_handle(&myvm->T); + trace_handle(&myvm->bignum_zero); + trace_handle(&myvm->bignum_pos_one); + trace_handle(&myvm->bignum_neg_one); + + trace_registered_locals(); + trace_registered_bignums(); + + for(int i = 0; i < USER_ENV; i++) trace_handle(&myvm->userenv[i]); + } + + void trace_contexts() + { + context *stacks = myvm->stack_chain; + + while(stacks) + { + trace_stack_elements(stacks->datastack_region,(cell *)stacks->datastack); + trace_stack_elements(stacks->retainstack_region,(cell *)stacks->retainstack); + + trace_handle(&stacks->catchstack_save); + trace_handle(&stacks->current_callback_save); + + stacks = stacks->next; + } + } +}; + +} diff --git a/vm/copying_collector.hpp b/vm/copying_collector.hpp new file mode 100644 index 0000000000..bb17f2e70d --- /dev/null +++ b/vm/copying_collector.hpp @@ -0,0 +1,159 @@ +namespace factor +{ + +template +struct copying_collector : collector { + cell scan; + + explicit copying_collector(factor_vm *myvm_, TargetGeneration *target_, Policy policy_) : + collector(myvm_,target_,policy_), scan(target_->here) {} + + template void trace_objects_between(SourceGeneration *gen, cell scan, cell *end) + { + while(scan && scan < *end) + { + this->trace_slots((object *)scan); + scan = gen->next_object_after(this->myvm,scan); + } + } + + template void trace_card(SourceGeneration *gen, card *ptr) + { + cell card_start = this->myvm->card_to_addr(ptr); + cell card_scan = card_start + gen->card_offset(card_start); + cell card_end = this->myvm->card_to_addr(ptr + 1); + + trace_objects_between(gen,card_scan,&card_end); + + this->myvm->gc_stats.cards_scanned++; + } + + template void trace_card_deck(SourceGeneration *gen, card_deck *deck, card mask, card unmask) + { + card *first_card = this->myvm->deck_to_card(deck); + card *last_card = this->myvm->deck_to_card(deck + 1); + + u32 *quad_ptr; + u32 quad_mask = mask | (mask << 8) | (mask << 16) | (mask << 24); + + for(quad_ptr = (u32 *)first_card; quad_ptr < (u32 *)last_card; quad_ptr++) + { + if(*quad_ptr & quad_mask) + { + card *ptr = (card *)quad_ptr; + + for(int card = 0; card < 4; card++) + { + if(ptr[card] & mask) + { + trace_card(gen,&ptr[card]); + ptr[card] &= ~unmask; + } + } + } + } + + this->myvm->gc_stats.decks_scanned++; + } + + template void trace_cards(SourceGeneration *gen) + { + u64 start = current_micros(); + + card_deck *first_deck = this->myvm->addr_to_deck(gen->start); + card_deck *last_deck = this->myvm->addr_to_deck(gen->end); + + card mask, unmask; + + /* if we are collecting the nursery, we care about old->nursery pointers + but not old->aging pointers */ + if(this->current_gc->collecting_nursery_p()) + { + mask = card_points_to_nursery; + + /* after the collection, no old->nursery pointers remain + anywhere, but old->aging pointers might remain in tenured + space */ + if(gen->is_tenured_p()) + unmask = card_points_to_nursery; + /* after the collection, all cards in aging space can be + cleared */ + else if(gen->is_aging_p()) + unmask = card_mark_mask; + else + { + critical_error("bug in trace_gen_cards",0); + return; + } + } + /* if we are collecting aging space into tenured space, we care about + all old->nursery and old->aging pointers. no old->aging pointers can + remain */ + else if(this->current_gc->collecting_aging_p()) + { + if(this->current_gc->collecting_aging_again) + { + mask = card_points_to_aging; + unmask = card_mark_mask; + } + /* after we collect aging space into the aging semispace, no + old->nursery pointers remain but tenured space might still have + pointers to aging space. */ + else + { + mask = card_points_to_aging; + unmask = card_points_to_nursery; + } + } + else + { + critical_error("bug in trace_gen_cards",0); + return; + } + + for(card_deck *ptr = first_deck; ptr < last_deck; ptr++) + { + if(*ptr & mask) + { + trace_card_deck(gen,ptr,mask,unmask); + *ptr &= ~unmask; + } + } + + this->myvm->gc_stats.card_scan_time += (current_micros() - start); + } + + /* 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); + } + + /* Trace literals referenced from all code blocks. Only for aging and nursery collections */ + void trace_code_heap_roots() + { + if(this->current_gc->collecting_gen >= this->myvm->code->youngest_referenced_generation) + { + unordered_map &remembered_set = this->myvm->code->remembered_set; + unordered_map::const_iterator iter = remembered_set.begin(); + unordered_map::const_iterator end = remembered_set.end(); + + for(; iter != end; iter++) + { + if(this->current_gc->collecting_gen >= iter->second) + trace_literal_references(iter->first); + } + + this->myvm->gc_stats.code_heap_scans++; + } + } + + void cheneys_algorithm() + { + trace_objects_between(this->target,scan,&this->target->here); + } +}; + +} diff --git a/vm/data_gc.cpp b/vm/data_gc.cpp index dfe5ef3365..7e3aa95e11 100755 --- a/vm/data_gc.cpp +++ b/vm/data_gc.cpp @@ -399,48 +399,48 @@ void factor_vm::update_dirty_code_blocks() } template -copying_collector::copying_collector(factor_vm *myvm_, old_space *target_) +cheney_collector::cheney_collector(factor_vm *myvm_, old_space *target_) : myvm(myvm_), current_gc(myvm_->current_gc), target(target_) { scan = target->here; } -template Strategy ©ing_collector::strategy() +template Strategy &cheney_collector::strategy() { return static_cast(*this); } -template object *copying_collector::allot(cell size) +template object *cheney_collector::allot(cell size) { return target->allot(size); } -template object *copying_collector::copy_object(object *untagged) +template object *cheney_collector::copy_object(object *untagged) { return myvm->promote_object(untagged,strategy()); } -template bool copying_collector::should_copy_p(object *pointer) +template bool cheney_collector::should_copy_p(object *pointer) { return strategy().should_copy_p(pointer); } -template cell copying_collector::trace_next(cell scan) +template cell cheney_collector::trace_next(cell scan) { object *obj = (object *)scan; myvm->trace_slots(obj,strategy()); return scan + myvm->untagged_object_size(obj); } -template void copying_collector::go() +template void cheney_collector::go() { strategy().copy_reachable_objects(scan,&target->here); } -struct nursery_collector : copying_collector +struct nursery_strategy : cheney_collector { - explicit nursery_collector(factor_vm *myvm_, old_space *target_) : - copying_collector(myvm_,target_) {} + explicit nursery_strategy(factor_vm *myvm_, old_space *target_) : + cheney_collector(myvm_,target_) {} bool should_copy_p(object *untagged) { @@ -453,12 +453,12 @@ struct nursery_collector : copying_collector } }; -struct aging_collector : copying_collector +struct aging_strategy : cheney_collector { zone *tenured; - explicit aging_collector(factor_vm *myvm_, old_space *target_) : - copying_collector(myvm_,target_), + explicit aging_strategy(factor_vm *myvm_, old_space *target_) : + cheney_collector(myvm_,target_), tenured(myvm->data->tenured) {} bool should_copy_p(object *untagged) @@ -475,10 +475,10 @@ struct aging_collector : copying_collector } }; -struct aging_again_collector : copying_collector +struct aging_agian_strategy : cheney_collector { - explicit aging_again_collector(factor_vm *myvm_, old_space *target_) : - copying_collector(myvm_,target_) {} + explicit aging_agian_strategy(factor_vm *myvm_, old_space *target_) : + cheney_collector(myvm_,target_) {} bool should_copy_p(object *untagged) { @@ -491,10 +491,10 @@ struct aging_again_collector : copying_collector } }; -struct tenured_collector : copying_collector +struct tenured_strategy : cheney_collector { - explicit tenured_collector(factor_vm *myvm_, old_space *target_) : - copying_collector(myvm_,target_) {} + explicit tenured_strategy(factor_vm *myvm_, old_space *target_) : + cheney_collector(myvm_,target_) {} bool should_copy_p(object *untagged) { @@ -513,7 +513,7 @@ struct tenured_collector : copying_collector void factor_vm::collect_nursery() { - nursery_collector collector(this,data->aging); + nursery_strategy collector(this,data->aging); trace_roots(collector); trace_contexts(collector); @@ -531,7 +531,7 @@ void factor_vm::collect_aging() std::swap(data->aging,data->aging_semispace); reset_generation(data->aging); - aging_collector collector(this,data->aging); + aging_strategy collector(this,data->aging); trace_roots(collector); trace_contexts(collector); @@ -545,7 +545,7 @@ void factor_vm::collect_aging() void factor_vm::collect_aging_again() { - aging_again_collector collector(this,data->tenured); + aging_agian_strategy collector(this,data->tenured); trace_roots(collector); trace_contexts(collector); @@ -571,7 +571,7 @@ void factor_vm::collect_tenured(cell requested_bytes, bool trace_contexts_) reset_generation(data->tenured); } - tenured_collector collector(this,data->tenured); + tenured_strategy collector(this,data->tenured); trace_roots(collector); if(trace_contexts_) trace_contexts(collector); diff --git a/vm/data_gc.hpp b/vm/data_gc.hpp index 9032f6696d..d9bed8e785 100755 --- a/vm/data_gc.hpp +++ b/vm/data_gc.hpp @@ -63,13 +63,13 @@ struct gc_state { } }; -template struct copying_collector { +template struct cheney_collector { factor_vm *myvm; gc_state *current_gc; old_space *target; cell scan; - explicit copying_collector(factor_vm *myvm_, old_space *target); + explicit cheney_collector(factor_vm *myvm_, old_space *target); Strategy &strategy(); object *allot(cell size); cell trace_next(cell scan); diff --git a/vm/data_heap.cpp b/vm/data_heap.cpp index 7e358cb2f9..9b0710ae52 100755 --- a/vm/data_heap.cpp +++ b/vm/data_heap.cpp @@ -37,11 +37,11 @@ data_heap::data_heap(factor_vm *myvm, cell young_size_, cell aging_size_, cell t cell start = align(seg->start,deck_size); - tenured = new old_space(tenured_size,start); - tenured_semispace = new old_space(tenured_size,tenured->end); + tenured = new tenured_space(tenured_size,start); + tenured_semispace = new tenured_space(tenured_size,tenured->end); - aging = new old_space(aging_size,tenured_semispace->end); - aging_semispace = new old_space(aging_size,aging->end); + aging = new aging_space(aging_size,tenured_semispace->end); + aging_semispace = new aging_space(aging_size,aging->end); nursery = new zone(young_size,aging_semispace->end); diff --git a/vm/data_heap.hpp b/vm/data_heap.hpp index 3f620e3d42..36c75e23b9 100755 --- a/vm/data_heap.hpp +++ b/vm/data_heap.hpp @@ -9,10 +9,10 @@ struct data_heap { segment *seg; zone *nursery; - old_space *aging; - old_space *aging_semispace; - old_space *tenured; - old_space *tenured_semispace; + aging_space *aging; + aging_space *aging_semispace; + tenured_space *tenured; + tenured_space *tenured_semispace; char *cards; char *cards_end; diff --git a/vm/full_collector.cpp b/vm/full_collector.cpp new file mode 100644 index 0000000000..24ebe3c5e8 --- /dev/null +++ b/vm/full_collector.cpp @@ -0,0 +1,17 @@ +#include "master.hpp" + +namespace factor +{ + +full_collector::full_collector(factor_vm *myvm_, bool trace_contexts_p_) : + copying_collector(myvm_,myvm_->data->tenured,full_policy(myvm_)), + trace_contexts_p(trace_contexts_p_) {} + +void full_collector::go() +{ + trace_roots(); + if(trace_contexts_p) trace_contexts(); + cheneys_algorithm(); +} + +} diff --git a/vm/full_collector.hpp b/vm/full_collector.hpp new file mode 100644 index 0000000000..71ac569772 --- /dev/null +++ b/vm/full_collector.hpp @@ -0,0 +1,23 @@ +namespace factor +{ + +struct full_policy { + factor_vm *myvm; + zone *tenured; + + full_policy(factor_vm *myvm_) : myvm(myvm_), tenured(myvm->data->tenured) {} + + bool should_copy_p(object *untagged) + { + return !tenured->contains_p(untagged); + } +}; + +struct full_collector : copying_collector { + bool trace_contexts_p; + + full_collector(factor_vm *myvm_, bool trace_contexts_p_); + void go(); +}; + +} diff --git a/vm/master.hpp b/vm/master.hpp index 97e9ed4a8b..0e8a03fff6 100755 --- a/vm/master.hpp +++ b/vm/master.hpp @@ -72,6 +72,8 @@ namespace factor #include "zone.hpp" #include "write_barrier.hpp" #include "old_space.hpp" +#include "aging_space.hpp" +#include "tenured_space.hpp" #include "data_heap.hpp" #include "data_gc.hpp" #include "debug.hpp" @@ -87,6 +89,12 @@ namespace factor #include "vm.hpp" #include "tagged.hpp" #include "local_roots.hpp" +#include "collector.hpp" +#include "copying_collector.hpp" +#include "nursery_collector.hpp" +#include "aging_collector.hpp" +#include "to_tenured_collector.hpp" +#include "full_collector.hpp" #include "callstack.hpp" #include "generic_arrays.hpp" #include "arrays.hpp" diff --git a/vm/nursery_collector.cpp b/vm/nursery_collector.cpp new file mode 100644 index 0000000000..302f958562 --- /dev/null +++ b/vm/nursery_collector.cpp @@ -0,0 +1,20 @@ +#include "master.hpp" + +namespace factor +{ + +nursery_collector::nursery_collector(factor_vm *myvm_) : + copying_collector + (myvm_,myvm_->data->aging,nursery_policy(myvm_)) {} + +void nursery_collector::go() +{ + trace_roots(); + trace_contexts(); + trace_cards(data->tenured); + trace_cards(data->aging); + trace_code_heap_roots(); + cheneys_algorithm(); +} + +} diff --git a/vm/nursery_collector.hpp b/vm/nursery_collector.hpp new file mode 100644 index 0000000000..1cfe063187 --- /dev/null +++ b/vm/nursery_collector.hpp @@ -0,0 +1,20 @@ +namespace factor +{ + +struct nursery_policy { + factor_vm *myvm; + + nursery_policy(factor_vm *myvm_) : myvm(myvm_) {} + + bool should_copy_p(object *untagged) + { + return myvm->nursery.contains_p(untagged); + } +}; + +struct nursery_collector : copying_collector { + nursery_collector(factor_vm *myvm_); + void go(); +}; + +} diff --git a/vm/old_space.cpp b/vm/old_space.cpp new file mode 100644 index 0000000000..572f1edc14 --- /dev/null +++ b/vm/old_space.cpp @@ -0,0 +1,54 @@ +#include "master.hpp" + +namespace factor +{ + +old_space::old_space(cell size_, cell start_) : zone(size_,start_) +{ + cell cards_size = size_ >> card_bits; + allot_markers = new card[cards_size]; + allot_markers_end = allot_markers + cards_size; +} + +old_space::~old_space() +{ + delete[] allot_markers; +} + +card *old_space::addr_to_allot_marker(object *a) +{ + return (card *)((((cell)a - start) >> card_bits) + (cell)allot_markers); +} + +/* we need to remember the first object allocated in the card */ +void old_space::record_allocation(object *obj) +{ + card *ptr = addr_to_allot_marker(obj); + if(*ptr == invalid_allot_marker) + *ptr = ((cell)obj & addr_card_mask); +} + +object *old_space::allot(cell size) +{ + if(here + size > end) return NULL; + + object *obj = zone::allot(size); + record_allocation(obj); + return obj; +} + +void old_space::clear_allot_markers() +{ + memset(allot_markers,invalid_allot_marker,size >> card_bits); +} + +cell old_space::next_object_after(factor_vm *myvm, cell scan) +{ + cell size = myvm->untagged_object_size((object *)scan); + if(scan + size < end) + return scan + size; + else + return NULL; +} + +} diff --git a/vm/old_space.hpp b/vm/old_space.hpp index 598c1f4090..3f70403400 100644 --- a/vm/old_space.hpp +++ b/vm/old_space.hpp @@ -5,58 +5,19 @@ struct old_space : zone { card *allot_markers; card *allot_markers_end; - old_space(cell size_, cell start_) : zone(size_,start_) - { - cell cards_size = size_ >> card_bits; - allot_markers = new card[cards_size]; - allot_markers_end = allot_markers + cards_size; - } - - ~old_space() - { - delete[] allot_markers; - } - - card *addr_to_allot_marker(object *a) - { - return (card *)((((cell)a - start) >> card_bits) + (cell)allot_markers); - } - - /* we need to remember the first object allocated in the card */ - void record_allocation(object *obj) - { - card *ptr = addr_to_allot_marker(obj); - if(*ptr == invalid_allot_marker) - *ptr = ((cell)obj & addr_card_mask); - } + old_space(cell size_, cell start_); + ~old_space(); cell card_offset(cell address) { return allot_markers[(address - start) >> card_bits]; } - object *allot(cell size) - { - if(here + size > end) return NULL; - - object *obj = zone::allot(size); - record_allocation(obj); - return obj; - } - - void clear_allot_markers() - { - memset(allot_markers,invalid_allot_marker,size >> card_bits); - } - - /* object *next_object_after(object *ptr) - { - cell size = untagged_object_size(ptr); - if((cell)ptr + size < end) - return (object *)((cell)ptr + size); - else - return NULL; - } */ + card *addr_to_allot_marker(object *a); + void record_allocation(object *obj); + object *allot(cell size); + void clear_allot_markers(); + cell next_object_after(factor_vm *myvm, cell scan); }; } diff --git a/vm/tenured_space.hpp b/vm/tenured_space.hpp new file mode 100644 index 0000000000..a05b272fb6 --- /dev/null +++ b/vm/tenured_space.hpp @@ -0,0 +1,12 @@ +namespace factor +{ + +struct tenured_space : old_space { + tenured_space(cell size, cell start) : old_space(size,start) {} + + bool is_nursery_p() { return false; } + bool is_aging_p() { return false; } + bool is_tenured_p() { return true; } +}; + +} diff --git a/vm/to_tenured_collector.cpp b/vm/to_tenured_collector.cpp new file mode 100644 index 0000000000..2693e35a2f --- /dev/null +++ b/vm/to_tenured_collector.cpp @@ -0,0 +1,19 @@ +#include "master.hpp" + +namespace factor +{ + +to_tenured_collector::to_tenured_collector(factor_vm *myvm_) : + copying_collector + (myvm_,myvm_->data->tenured,to_tenured_policy(myvm_)) {} + +void to_tenured_collector::go() +{ + trace_roots(); + trace_contexts(); + trace_cards(data->tenured); + trace_code_heap_roots(); + cheneys_algorithm(); +} + +} diff --git a/vm/to_tenured_collector.hpp b/vm/to_tenured_collector.hpp new file mode 100644 index 0000000000..55561252bc --- /dev/null +++ b/vm/to_tenured_collector.hpp @@ -0,0 +1,21 @@ +namespace factor +{ + +struct to_tenured_policy { + factor_vm *myvm; + zone *tenured; + + to_tenured_policy(factor_vm *myvm_) : myvm(myvm_), tenured(myvm->data->tenured) {} + + bool should_copy_p(object *untagged) + { + return !tenured->contains_p(untagged); + } +}; + +struct to_tenured_collector : copying_collector { + to_tenured_collector(factor_vm *myvm_); + void go(); +}; + +} diff --git a/vm/zone.hpp b/vm/zone.hpp index a05afd45c6..25859fe500 100644 --- a/vm/zone.hpp +++ b/vm/zone.hpp @@ -9,13 +9,7 @@ struct zone { cell size; cell end; - cell init_zone(cell size_, cell start_) - { - size = size_; - start = here = start_; - end = start_ + size_; - return end; - } + zone(cell size_, cell start_) : start(start_), here(0), size(size_), end(start_ + size_) {} inline bool contains_p(object *pointer) {