]> gitweb.factorcode.org Git - factor.git/commitdiff
vm: during tenuring stage of aging collection, if tenured space fills up, it would...
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Thu, 15 Oct 2009 10:51:11 +0000 (05:51 -0500)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Thu, 15 Oct 2009 10:51:11 +0000 (05:51 -0500)
12 files changed:
vm/aging_collector.cpp
vm/code_heap.cpp
vm/collector.hpp
vm/copying_collector.hpp
vm/data_heap.hpp
vm/debug.cpp
vm/full_collector.cpp
vm/gc.cpp
vm/gc.hpp
vm/nursery_collector.cpp
vm/to_tenured_collector.cpp
vm/vm.hpp

index 6d67753b512b137a676532285df23247d760870b..9a856374f6c1232bd63dc2847354a27a4ce34f53 100644 (file)
@@ -4,12 +4,21 @@ namespace factor
 {
 
 aging_collector::aging_collector(factor_vm *myvm_) :
-       copying_collector<aging_space,aging_policy>
-       (myvm_,myvm_->data->aging,aging_policy(myvm_)) {}
+       copying_collector<aging_space,aging_policy>(
+               myvm_,
+               &myvm_->gc_stats.aging_stats,
+               myvm_->data->aging,
+               aging_policy(myvm_)) {}
 
 void factor_vm::collect_aging()
 {
        {
+               /* Change the op so that if we fail here, we proceed to a full
+               tenured collection. We are collecting to tenured space, and
+               cards were unmarked, so we can't proceed with a to_tenured
+               collection. */
+               current_gc->op = collect_to_tenured_op;
+
                to_tenured_collector collector(this);
                collector.trace_cards(data->tenured,
                        card_points_to_aging,
@@ -17,6 +26,9 @@ void factor_vm::collect_aging()
                collector.cheneys_algorithm();
        }
        {
+               /* If collection fails here, do a to_tenured collection. */
+               current_gc->op = collect_aging_op;
+
                std::swap(data->aging,data->aging_semispace);
                reset_generation(data->aging);
 
index 0cb2cae50f220e3d7123f72b797d6308c316e315..6eb420cbdeb8ecd52994be3a12f41557eb7c23d6 100755 (executable)
@@ -229,7 +229,7 @@ critical here */
 void factor_vm::compact_code_heap()
 {
        /* Free all unreachable code blocks, don't trace contexts */
-       garbage_collection(tenured_gen,false,false,0);
+       garbage_collection(collect_full_op,false,0);
 
        /* Figure out where the code heap blocks are going to end up */
        cell size = code->compute_heap_forwarding();
index 8f9d4f26ac57b18b8f580717e14107126a039177..24bba5d0a4607663fdc4ebf79f910cc910e30c2e 100644 (file)
@@ -6,14 +6,16 @@ template<typename TargetGeneration, typename Policy> struct collector {
        data_heap *data;
        code_heap *code;
        gc_state *current_gc;
+       generation_statistics *stats;
        TargetGeneration *target;
        Policy policy;
 
-       explicit collector(factor_vm *myvm_, TargetGeneration *target_, Policy policy_) :
+       explicit collector(factor_vm *myvm_, generation_statistics *stats_, TargetGeneration *target_, Policy policy_) :
                myvm(myvm_),
                data(myvm_->data),
                code(myvm_->code),
                current_gc(myvm_->current_gc),
+               stats(stats_),
                target(target_),
                policy(policy_) {}
 
@@ -74,7 +76,6 @@ template<typename TargetGeneration, typename Policy> struct collector {
                memcpy(newpointer,untagged,size);
                untagged->h.forward_to(newpointer);
 
-               generation_statistics *stats = &myvm->gc_stats.generations[current_gc->collecting_gen];
                stats->object_count++;
                stats->bytes_copied += size;
 
index 1e338899b8a0e9df09b64004e0cf2f8632bb7796..654b84f3ae3577702bb9c111ae67c7c1deda0380 100644 (file)
@@ -15,8 +15,8 @@ template<typename TargetGeneration, typename Policy>
 struct copying_collector : collector<TargetGeneration,Policy> {
        cell scan;
 
-       explicit copying_collector(factor_vm *myvm_, TargetGeneration *target_, Policy policy_) :
-               collector<TargetGeneration,Policy>(myvm_,target_,policy_), scan(target_->here) {}
+       explicit copying_collector(factor_vm *myvm_, generation_statistics *stats_, TargetGeneration *target_, Policy policy_) :
+               collector<TargetGeneration,Policy>(myvm_,stats_,target_,policy_), scan(target_->here) {}
 
        inline cell first_card_in_deck(cell deck)
        {
@@ -28,11 +28,6 @@ struct copying_collector : collector<TargetGeneration,Policy> {
                return first_card_in_deck(deck + 1);
        }
 
-       inline cell card_to_addr(cell c)
-       {
-               return c << card_bits + this->data->start;
-       }
-
        inline cell card_deck_for_address(cell a)
        {
                return addr_to_deck(a - this->data->start);
index 2370325cad8c4db0b5743b6a37517ebbb7b2a833..10f3698e746fb9c94eaa35b7b60e4bdf7fb2fbee 100755 (executable)
@@ -27,9 +27,4 @@ struct data_heap {
        data_heap *grow(cell requested_size);
 };
 
-static const cell nursery_gen = 0;
-static const cell aging_gen = 1;
-static const cell tenured_gen = 2;
-static const cell gen_count = 3;
-
 }
index 64514b9261835553e3cba8d073f93108f16014bb..3a8e847f1429d08d374a1b4d8fb54bab1d8e61df 100755 (executable)
@@ -211,9 +211,9 @@ void factor_vm::dump_memory(cell from, cell to)
                dump_cell(from);
 }
 
-void factor_vm::dump_zone(cell gen, zone *z)
+void factor_vm::dump_zone(char *name, zone *z)
 {
-       print_string("Generation "); print_cell(gen); print_string(": ");
+       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();
@@ -221,9 +221,9 @@ void factor_vm::dump_zone(cell gen, zone *z)
 
 void factor_vm::dump_generations()
 {
-       dump_zone(nursery_gen,&nursery);
-       dump_zone(aging_gen,data->aging);
-       dump_zone(tenured_gen,data->tenured);
+       dump_zone("Nursery",&nursery);
+       dump_zone("Aging",data->aging);
+       dump_zone("Tenured",data->tenured);
 
        print_string("Cards: base=");
        print_cell((cell)data->cards);
index 2496b963e4ee4b1766372fa3688932b740f26302..db3d1dcc53c7a9e74801cc9b7514eedcf6dc4457 100644 (file)
@@ -4,7 +4,11 @@ namespace factor
 {
 
 full_collector::full_collector(factor_vm *myvm_) :
-       copying_collector<tenured_space,full_policy>(myvm_,myvm_->data->tenured,full_policy(myvm_)) {}
+       copying_collector<tenured_space,full_policy>(
+               myvm_,
+               &myvm_->gc_stats.full_stats,
+               myvm_->data->tenured,
+               full_policy(myvm_)) {}
 
 struct stack_frame_marker {
        factor_vm *myvm;
index 10aee9a736b171616e91da7b0fc5d7330f65a7b0..c4e8d25e209338d71f4dc3ec0def1fbf78225b00 100755 (executable)
--- a/vm/gc.cpp
+++ b/vm/gc.cpp
@@ -3,14 +3,9 @@
 namespace factor
 {
 
-gc_state::gc_state(data_heap *data_, bool growing_data_heap_, cell collecting_gen_) :
-       data(data_),
-       growing_data_heap(growing_data_heap_),
-       collecting_gen(collecting_gen_),
-        collecting_aging_again(false),
-       start_time(current_micros()) { }
+gc_state::gc_state(gc_op op_) : op(op_), start_time(current_micros()) {}
 
-gc_state::~gc_state() { }
+gc_state::~gc_state() {}
 
 void factor_vm::update_dirty_code_blocks(std::set<code_block *> *remembered_set)
 {
@@ -21,80 +16,81 @@ void factor_vm::update_dirty_code_blocks(std::set<code_block *> *remembered_set)
        for(; iter != end; iter++) update_literal_references(*iter);
 }
 
-void factor_vm::record_gc_stats()
+void factor_vm::record_gc_stats(generation_statistics *stats)
 {
-       generation_statistics *s = &gc_stats.generations[current_gc->collecting_gen];
-
        cell gc_elapsed = (current_micros() - current_gc->start_time);
-       s->collections++;
-       s->gc_time += gc_elapsed;
-       if(s->max_gc_time < gc_elapsed)
-               s->max_gc_time = gc_elapsed;
+       stats->collections++;
+       stats->gc_time += gc_elapsed;
+       if(stats->max_gc_time < gc_elapsed)
+               stats->max_gc_time = gc_elapsed;
 }
 
 /* Collect gen and all younger generations.
 If growing_data_heap_ is true, we must grow the data heap to such a size that
 an allocation of requested_bytes won't fail */
-void factor_vm::garbage_collection(cell collecting_gen_, bool growing_data_heap_, bool trace_contexts_p, cell requested_bytes)
+void factor_vm::garbage_collection(gc_op op, bool trace_contexts_p, cell requested_bytes)
 {
        assert(!gc_off);
        assert(!current_gc);
 
        save_stacks();
 
-       current_gc = new gc_state(data,growing_data_heap_,collecting_gen_);
+       current_gc = new gc_state(op);
 
        /* Keep trying to GC higher and higher generations until we don't run out
        of space */
        if(setjmp(current_gc->gc_unwind))
        {
                /* We come back here if a generation is full */
-
-               /* We have no older generations we can try collecting, so we
-               resort to growing the data heap */
-               if(current_gc->collecting_tenured_p())
+               switch(current_gc->op)
                {
-                       assert(!current_gc->growing_data_heap);
-                       current_gc->growing_data_heap = true;
-
+               case collect_nursery_op:
+                       current_gc->op = collect_aging_op;
+                       break;
+               case collect_aging_op:
+                       current_gc->op = collect_to_tenured_op;
+                       break;
+               case collect_to_tenured_op:
+                       current_gc->op = collect_full_op;
+                       break;
+               case collect_full_op:
                        /* Since we start tracing again, any previously
                        marked code blocks must be re-marked and re-traced */
                        code->clear_mark_bits();
-               }
-               /* we try collecting aging space twice before going on to
-               collect tenured */
-               else if(current_gc->collecting_aging_p()
-                       && !current_gc->collecting_aging_again)
-               {
-                       current_gc->collecting_aging_again = true;
-               }
-               /* Collect the next oldest generation */
-               else
-               {
-                       current_gc->collecting_gen++;
+                       current_gc->op = collect_growing_heap_op;
+                       break;
+               default:
+                       critical_error("Bad GC op\n",op);
+                       break;
                }
        }
 
-       if(current_gc->collecting_nursery_p())
-               collect_nursery();
-       else if(current_gc->collecting_aging_p())
-       {
-               if(current_gc->collecting_aging_again)
-                       collect_to_tenured();
-               else
-                       collect_aging();
-       }
-        else if(current_gc->collecting_tenured_p())
+       switch(current_gc->op)
        {
-               if(current_gc->growing_data_heap)
-                       collect_growing_heap(requested_bytes,trace_contexts_p);
-               else
-                       collect_full(trace_contexts_p);
+       case collect_nursery_op:
+               collect_nursery();
+               record_gc_stats(&gc_stats.nursery_stats);
+               break;
+       case collect_aging_op:
+               collect_aging();
+               record_gc_stats(&gc_stats.aging_stats);
+               break;
+       case collect_to_tenured_op:
+               collect_to_tenured();
+               record_gc_stats(&gc_stats.aging_stats);
+               break;
+       case collect_full_op:
+               collect_full(trace_contexts_p);
+               record_gc_stats(&gc_stats.full_stats);
+               break;
+       case collect_growing_heap_op:
+               collect_growing_heap(requested_bytes,trace_contexts_p);
+               record_gc_stats(&gc_stats.full_stats);
+               break;
+       default:
+               critical_error("Bad GC op\n",op);
+               break;
        }
-       else
-               critical_error("Bug in GC",0);
-
-       record_gc_stats();
 
        delete current_gc;
        current_gc = NULL;
@@ -102,7 +98,7 @@ void factor_vm::garbage_collection(cell collecting_gen_, bool growing_data_heap_
 
 void factor_vm::gc()
 {
-       garbage_collection(tenured_gen,false,true,0);
+       garbage_collection(collect_full_op,true,0);
 }
 
 void factor_vm::primitive_gc()
@@ -110,25 +106,28 @@ void factor_vm::primitive_gc()
        gc();
 }
 
+void factor_vm::add_gc_stats(generation_statistics *stats, growable_array *result)
+{
+       result->add(allot_cell(stats->collections));
+       result->add(tag<bignum>(long_long_to_bignum(stats->gc_time)));
+       result->add(tag<bignum>(long_long_to_bignum(stats->max_gc_time)));
+       result->add(allot_cell(stats->collections == 0 ? 0 : stats->gc_time / stats->collections));
+       result->add(allot_cell(stats->object_count));
+       result->add(tag<bignum>(long_long_to_bignum(stats->bytes_copied)));
+}
+
 void factor_vm::primitive_gc_stats()
 {
        growable_array result(this);
 
-       cell i;
-       u64 total_gc_time = 0;
+       add_gc_stats(&gc_stats.nursery_stats,&result);
+       add_gc_stats(&gc_stats.aging_stats,&result);
+       add_gc_stats(&gc_stats.full_stats,&result);
 
-       for(i = 0; i < gen_count; i++)
-       {
-               generation_statistics *s = &gc_stats.generations[i];
-               result.add(allot_cell(s->collections));
-               result.add(tag<bignum>(long_long_to_bignum(s->gc_time)));
-               result.add(tag<bignum>(long_long_to_bignum(s->max_gc_time)));
-               result.add(allot_cell(s->collections == 0 ? 0 : s->gc_time / s->collections));
-               result.add(allot_cell(s->object_count));
-               result.add(tag<bignum>(long_long_to_bignum(s->bytes_copied)));
-
-               total_gc_time += s->gc_time;
-       }
+       u64 total_gc_time =
+               gc_stats.nursery_stats.gc_time +
+               gc_stats.aging_stats.gc_time +
+               gc_stats.full_stats.gc_time;
 
        result.add(tag<bignum>(ulong_long_to_bignum(total_gc_time)));
        result.add(tag<bignum>(ulong_long_to_bignum(gc_stats.cards_scanned)));
@@ -186,7 +185,7 @@ void factor_vm::inline_gc(cell *gc_roots_base, cell gc_roots_size)
        for(cell i = 0; i < gc_roots_size; i++)
                gc_locals.push_back((cell)&gc_roots_base[i]);
 
-       garbage_collection(nursery_gen,false,true,0);
+       garbage_collection(collect_nursery_op,true,0);
 
        for(cell i = 0; i < gc_roots_size; i++)
                gc_locals.pop_back();
@@ -215,7 +214,7 @@ object *factor_vm::allot_object(header header, cell size)
        {
                /* If there is insufficient room, collect the nursery */
                if(nursery.here + size > nursery.end)
-                       garbage_collection(nursery_gen,false,true,0);
+                       garbage_collection(collect_nursery_op,true,0);
 
                obj = nursery.allot(size);
        }
@@ -229,7 +228,7 @@ object *factor_vm::allot_object(header header, cell size)
 
                /* If it still won't fit, grow the heap */
                if(data->tenured->here + size > data->tenured->end)
-                       garbage_collection(tenured_gen,true,true,size);
+                       garbage_collection(collect_growing_heap_op,true,size);
 
                obj = data->tenured->allot(size);
 
index 02f54414fd25bebc458c0f7444f48b1870cf22e0..9469603d0c489d649c181f17b977dfbad447d81e 100755 (executable)
--- a/vm/gc.hpp
+++ b/vm/gc.hpp
@@ -1,6 +1,14 @@
 namespace factor
 {
 
+enum gc_op {
+       collect_nursery_op,
+       collect_aging_op,
+       collect_to_tenured_op,
+       collect_full_op,
+       collect_growing_heap_op
+};
+
 /* statistics */
 struct generation_statistics {
        cell collections;
@@ -11,7 +19,9 @@ struct generation_statistics {
 };
 
 struct gc_statistics {
-       generation_statistics generations[gen_count];
+       generation_statistics nursery_stats;
+       generation_statistics aging_stats;
+       generation_statistics full_stats;
        u64 cards_scanned;
        u64 decks_scanned;
        u64 card_scan_time;
@@ -19,47 +29,12 @@ struct gc_statistics {
 };
 
 struct gc_state {
-       /* The data heap we're collecting */
-       data_heap *data;
-
-       /* sometimes we grow the heap */
-       bool growing_data_heap;
-
-       /* Which generation is being collected */
-       cell collecting_gen;
-
-       /* If true, we are collecting aging space for the second time, so if it is still
-          full, we go on to collect tenured */
-       bool collecting_aging_again;
-
-       /* GC start time, for benchmarking */
+       gc_op op;
        u64 start_time;
-
         jmp_buf gc_unwind;
 
-       explicit gc_state(data_heap *data_, bool growing_data_heap_, cell collecting_gen_);
+       explicit gc_state(gc_op op_);
        ~gc_state();
-
-       inline bool collecting_nursery_p()
-       {
-               return collecting_gen == nursery_gen;
-       }
-
-       inline bool collecting_aging_p()
-       {
-               return collecting_gen == aging_gen;
-       }
-
-       inline bool collecting_tenured_p()
-       {
-               return collecting_gen == tenured_gen;
-       }
-
-       inline bool collecting_accumulation_gen_p()
-       {
-               return ((collecting_aging_p() && !collecting_aging_again)
-                       || collecting_tenured_p());
-       }
 };
 
 VM_C_API void inline_gc(cell *gc_roots_base, cell gc_roots_size, factor_vm *myvm);
index de5eab45933b013b2ff22566d593c9c58f1aaa50..85f04dbb2d8a9663334d45ba97928a970287d498 100644 (file)
@@ -4,8 +4,11 @@ namespace factor
 {
 
 nursery_collector::nursery_collector(factor_vm *myvm_) :
-       copying_collector<aging_space,nursery_policy>
-       (myvm_,myvm_->data->aging,nursery_policy(myvm_)) {}
+       copying_collector<aging_space,nursery_policy>(
+               myvm_,
+               &myvm_->gc_stats.nursery_stats,
+               myvm_->data->aging,
+               nursery_policy(myvm_)) {}
 
 void factor_vm::collect_nursery()
 {
index 881b45fbc4624c37b27fd3b61dc8c8a26cdcbb89..6689411684056a64d4ae59cf942452dd15f431de 100644 (file)
@@ -4,8 +4,11 @@ namespace factor
 {
 
 to_tenured_collector::to_tenured_collector(factor_vm *myvm_) :
-       copying_collector<tenured_space,to_tenured_policy>
-       (myvm_,myvm_->data->tenured,to_tenured_policy(myvm_)) {}
+       copying_collector<tenured_space,to_tenured_policy>(
+               myvm_,
+               &myvm_->gc_stats.aging_stats,
+               myvm_->data->tenured,
+               to_tenured_policy(myvm_)) {}
 
 void factor_vm::collect_to_tenured()
 {
index b6a3e30af3d989aba5f182c06b5ce1bc828f9dbc..73a423ccf47fc24f102e762122152aa41d19454d 100755 (executable)
--- a/vm/vm.hpp
+++ b/vm/vm.hpp
@@ -1,6 +1,8 @@
 namespace factor
 {
 
+struct growable_array;
+
 struct factor_vm
 {
        // First five fields accessed directly by assembler. See vm.factor
@@ -240,8 +242,8 @@ struct factor_vm
        void collect_full_impl(bool trace_contexts_p);
        void collect_growing_heap(cell requested_bytes, bool trace_contexts_p);
        void collect_full(bool trace_contexts_p);
-       void record_gc_stats();
-       void garbage_collection(cell gen, bool growing_data_heap, bool trace_contexts_p, cell requested_bytes);
+       void record_gc_stats(generation_statistics *stats);
+       void garbage_collection(gc_op op, bool trace_contexts_p, cell requested_bytes);
        void gc();
        void primitive_gc();
        void primitive_gc_stats();
@@ -249,6 +251,7 @@ struct factor_vm
        void primitive_become();
        void inline_gc(cell *gc_roots_base, cell gc_roots_size);
        object *allot_object(header header, cell size);
+       void add_gc_stats(generation_statistics *stats, growable_array *result);
        void primitive_clear_gc_stats();
 
        template<typename Type> Type *allot(cell size)
@@ -259,7 +262,7 @@ struct factor_vm
        inline void check_data_pointer(object *pointer)
        {
        #ifdef FACTOR_DEBUG
-               if(!(current_gc && current_gc->growing_data_heap))
+               if(!(current_gc && current_gc->op == collect_growing_heap_op))
                {
                        assert((cell)pointer >= data->seg->start
                               && (cell)pointer < data->seg->end);
@@ -298,7 +301,7 @@ struct factor_vm
        void print_callstack();
        void dump_cell(cell x);
        void dump_memory(cell from, cell to);
-       void dump_zone(cell gen, zone *z);
+       void dump_zone(char *name, zone *z);
        void dump_generations();
        void dump_objects(cell type);
        void find_data_references_step(cell *scan);