]> gitweb.factorcode.org Git - factor.git/commitdiff
vm: mark sweep gc for tenured space work in progress
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Wed, 21 Oct 2009 03:20:49 +0000 (22:20 -0500)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Wed, 21 Oct 2009 03:20:49 +0000 (22:20 -0500)
22 files changed:
vm/aging_collector.cpp
vm/aging_collector.hpp
vm/aging_space.hpp
vm/bump_allocator.hpp
vm/code_heap.cpp
vm/collector.hpp
vm/copying_collector.hpp
vm/data_heap.cpp
vm/data_heap.hpp
vm/debug.cpp
vm/free_list_allocator.hpp
vm/full_collector.cpp
vm/full_collector.hpp
vm/gc.cpp
vm/image.cpp
vm/master.hpp
vm/nursery_collector.hpp
vm/nursery_space.hpp [new file with mode: 0644]
vm/tenured_space.hpp
vm/to_tenured_collector.cpp
vm/to_tenured_collector.hpp
vm/vm.hpp

index 49b1c520ecbed1690b11691b6326eac61b9e67b7..2972528cb3f4e24b42673764614f9950864ca407 100644 (file)
@@ -25,7 +25,7 @@ void factor_vm::collect_aging()
                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. */
index 8f2677c8b66b1d12314bf14bce3cf8b9b25dc8a0..a04261d8268e1fa05c0f15598e5207d97566fce4 100644 (file)
@@ -15,6 +15,10 @@ struct aging_policy {
        {
                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> {
index 20e25065395ddea021b6beda7d01e811891d64a7..99efd44de5f498214a7a511816489447e749b504 100644 (file)
@@ -1,20 +1,29 @@
 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;
+       }
 };
 
 }
index 64011e0bb66a7272f051349e0220fb7c24962b36..b41613b540b10bfc4c4b5b006e706dbe4dae0fb8 100644 (file)
@@ -1,7 +1,7 @@
 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;
@@ -9,27 +9,18 @@ struct bump_allocator {
        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;
        }
 };
 
index 2a466857f9cd34752fb8ec42f1d7ab0ca3ee9937..5ae55cb760c383646a160b245946e35edf64ee64 100755 (executable)
@@ -8,7 +8,7 @@ code_heap::code_heap(cell size)
        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()
index 9200d953992abfbd8453111f6addf42252fb7014..bc04ee4de793c8148216b5af86ac649373b1c731 100644 (file)
@@ -40,7 +40,10 @@ template<typename TargetGeneration, typename Policy> struct collector {
 
                object *untagged = parent->untag<object>(pointer);
                if(!policy.should_copy_p(untagged))
+               {
+                       policy.visited_object(untagged);
                        return;
+               }
 
                object *forwarding = resolve_forwarding(untagged);
 
@@ -49,7 +52,10 @@ template<typename TargetGeneration, typename Policy> struct collector {
                else if(policy.should_copy_p(forwarding))
                        untagged = promote_object(forwarding);
                else
+               {
                        untagged = forwarding;
+                       policy.visited_object(untagged);
+               }
 
                *handle = RETAG(untagged,TAG(pointer));
        }
@@ -79,6 +85,8 @@ template<typename TargetGeneration, typename Policy> struct collector {
                stats->object_count++;
                stats->bytes_copied += size;
 
+               policy.promoted_object(newpointer);
+
                return newpointer;
        }
 
@@ -145,6 +153,141 @@ template<typename TargetGeneration, typename Policy> struct collector {
                        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);
+       }
 };
 
 }
index ea7faf24230ee916e477b2e297963ca9c99fdb2d..012aa4ec1013e264ac46b94ca11b25bb38657895 100644 (file)
@@ -18,147 +18,12 @@ struct copying_collector : collector<TargetGeneration,Policy> {
        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);
                }
        }
 };
index 5a8f4d6b36a6b666a5fb9f9e4569bdd825d79239..7c887c7419a2e87d2ee4e7f4af81e72773de6a3b 100755 (executable)
@@ -19,7 +19,7 @@ data_heap::data_heap(cell young_size_, cell aging_size_, cell tenured_size_)
        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;
 
@@ -29,20 +29,21 @@ data_heap::data_heap(cell young_size_, cell aging_size_, cell tenured_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);
 }
@@ -54,7 +55,6 @@ data_heap::~data_heap()
        delete aging;
        delete aging_semispace;
        delete tenured;
-       delete tenured_semispace;
        delete[] cards;
        delete[] decks;
 }
@@ -71,8 +71,6 @@ void factor_vm::set_data_heap(data_heap *data_)
        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)
@@ -185,8 +183,11 @@ void factor_vm::primitive_data_room()
        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());
@@ -195,7 +196,7 @@ void factor_vm::primitive_data_room()
 /* 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;
 }
 
@@ -214,12 +215,14 @@ cell factor_vm::next_object()
        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 */
index 526a5eb9ae3add2e7b53dd4fd0862a8b52c8620c..fe714b91b03b81110a3b928ea91b7101644b25ff 100755 (executable)
@@ -10,11 +10,10 @@ struct data_heap {
 
        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;
@@ -49,7 +48,6 @@ their allocation pointers and cards reset. */
 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();
index 31164e972b95e5c6b2bbf19833523eb7045e1eb8..afc0b43f7a9b52685c96c8bf7ab1925e72f9e74f 100755 (executable)
@@ -209,19 +209,21 @@ void factor_vm::dump_memory(cell from, cell to)
                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);
index da2622bb0b66cc8f5b727b5d331c2786594f418c..c8f3bd6f47a9e71b37e2df783a7d8a9d4bb57256 100644 (file)
@@ -9,29 +9,17 @@ struct free_list {
 };
 
 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);
@@ -42,35 +30,42 @@ template<typename Block> struct free_list_allocator {
        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)
@@ -234,8 +229,56 @@ template<typename Block> cell free_list_allocator<Block>::occupied()
                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)
@@ -302,4 +345,20 @@ void free_list_allocator<Block>::compact(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;
+       }
+}
+
 }
index 924cad67773203038a41154220f36e7d03b7393a..9191823d75ff894b8bca38178041bce03e7758ed 100644 (file)
@@ -4,7 +4,7 @@ namespace factor
 {
 
 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,
@@ -89,18 +89,22 @@ void full_collector::trace_literal_references(code_block *compiled)
 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);
        }
 }
 
@@ -109,6 +113,7 @@ void factor_vm::collect_full_impl(bool trace_contexts_p)
        full_collector collector(this);
 
        code->clear_mark_bits();
+       data->tenured->clear_mark_bits();
 
        collector.trace_roots();
         if(trace_contexts_p)
@@ -118,8 +123,9 @@ void factor_vm::collect_full_impl(bool 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;
 }
@@ -144,9 +150,6 @@ void factor_vm::collect_growing_heap(cell requested_bytes,
 
 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)
index 5298f56637af5c8e7d6cd98032285a8c260ecb4b..9aef352b4b1a1bb5218df4730bf08c37584b0986 100644 (file)
@@ -11,9 +11,20 @@ struct full_policy {
        {
                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_);
@@ -22,7 +33,7 @@ struct full_collector : copying_collector<tenured_space,full_policy> {
        void trace_callbacks();
        void trace_literal_references(code_block *compiled);
        void mark_code_block(code_block *compiled);
-       void cheneys_algorithm();
+       void mark_reachable_objects();
 };
 
 }
index c8ba57b7f2a5315c92d59cb1ceab37420ecc72ee..6cb99b6da0333b0f91861d1cbca52a428b98fcf0 100755 (executable)
--- a/vm/gc.cpp
+++ b/vm/gc.cpp
@@ -235,11 +235,13 @@ object *factor_vm::allot_object(header header, cell size)
        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 */
index b47fe4e86a1c67dd4a73a9bda73f5ea59f802167..ee0a1064ed0fb560260eececdcaed835559a0995 100755 (executable)
@@ -39,7 +39,7 @@ void factor_vm::load_data_heap(FILE *file, image_header *h, vm_parameters *p)
                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)
@@ -203,7 +203,7 @@ void factor_vm::relocate_data(cell data_relocation_base, cell code_relocation_ba
        {
                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);
        }
 }
 
@@ -289,7 +289,7 @@ bool factor_vm::save_image(const vm_char *filename)
        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();
 
index 293923ca7bc72f7d87ad74454c049be1bdc9628a..0282a0597d30639e227888aa940bc9cc4cfa45fd 100755 (executable)
@@ -53,6 +53,7 @@ namespace factor
 #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"
index f9d21729299d5658674ab205b80063f820a9176c..778efab138d39106d721155c88194bcfdd739a05 100644 (file)
@@ -6,10 +6,14 @@ struct nursery_policy {
 
        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> {
diff --git a/vm/nursery_space.hpp b/vm/nursery_space.hpp
new file mode 100644 (file)
index 0000000..4425c16
--- /dev/null
@@ -0,0 +1,9 @@
+namespace factor
+{
+
+struct nursery_space : bump_allocator<object>
+{
+       nursery_space(cell size, cell start) : bump_allocator<object>(size,start) {}
+};
+
+}
index 1162bb5fd334cbc78ce9814ea210995f7f370d86..c0c12d3f581587a28b3ff3667dee6d2be2df3965 100644 (file)
@@ -1,19 +1,65 @@
 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);
        }
 };
 
index 3676324ce28b96d94d74e8a15896ec5a320b6388..3150647cd22580687d44c20de0c927ec78e4b4f2 100644 (file)
@@ -4,12 +4,23 @@ namespace factor
 {
 
 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. */
@@ -21,7 +32,7 @@ void factor_vm::collect_to_tenured()
                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;
index 9a4cf3764b4d95c99b89ba2149073975cbed7b35..e87ba5ee2979031818571de2b3d3a69cc53e2489 100644 (file)
@@ -11,10 +11,18 @@ struct to_tenured_policy {
        {
                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();
 };
 
 }
index 05091279184d8f68f3462eeaae21e2b8d470dafc..615efe35edf1dbe47cbf50fe4808c48ce474446c 100755 (executable)
--- a/vm/vm.hpp
+++ b/vm/vm.hpp
@@ -11,7 +11,7 @@ struct factor_vm
        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;
@@ -308,7 +308,7 @@ struct factor_vm
        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);