]> gitweb.factorcode.org Git - factor.git/commitdiff
vm: remove crummy old GC stats, split off free list code, clean up various other...
authorSlava Pestov <slava@shill.local>
Tue, 27 Oct 2009 03:08:35 +0000 (22:08 -0500)
committerSlava Pestov <slava@shill.local>
Tue, 27 Oct 2009 03:08:35 +0000 (22:08 -0500)
24 files changed:
Makefile
basis/tools/memory/memory.factor
core/bootstrap/primitives.factor
vm/aging_collector.cpp
vm/bump_allocator.hpp
vm/code_block.cpp
vm/code_heap.cpp
vm/collector.hpp
vm/copying_collector.hpp
vm/data_heap.cpp
vm/factor.cpp
vm/free_list.cpp [new file with mode: 0644]
vm/free_list.hpp [new file with mode: 0644]
vm/free_list_allocator.hpp
vm/full_collector.cpp
vm/gc.cpp
vm/gc.hpp
vm/image.cpp
vm/image.hpp
vm/master.hpp
vm/nursery_collector.cpp
vm/primitives.cpp
vm/to_tenured_collector.cpp
vm/vm.hpp

index 030a27854368756dac4b868c03d4e95310b83d40..2ea43706f499b5d6eb193175cf4e02408a254f83 100755 (executable)
--- a/Makefile
+++ b/Makefile
@@ -48,6 +48,7 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \
        vm/dispatch.o \
        vm/errors.o \
        vm/factor.o \
+       vm/free_list.o \
        vm/full_collector.o \
        vm/gc.o \
        vm/image.o \
index 2f1827a8ff868dac959a74bdf9ce7b498f314ce0..a5ed0fc0c1832a7f2a83fc12ea38262624b68238 100644 (file)
@@ -9,35 +9,50 @@ IN: tools.memory
 <PRIVATE
 
 : kilobytes ( n -- str )
-    number>string
+    1024 /i number>string
     dup length 4 > [ 3 cut* "," glue ] when
     " KB" append ;
 
-: memory-table. ( sizes seq -- )
-    swap [ kilobytes ] map zip simple-table. ;
+: fancy-table. ( seq alist -- )
+    [ [ nip first ] [ second call( obj -- str ) ] 2bi 2array ] 2map
+    simple-table. ;
 
 : young-room. ( seq -- )
-    { "Total:" "Allocated:" "Free:" } memory-table. ;
+    {
+        { "Total:" [ kilobytes ] }
+        { "Allocated:" [ kilobytes ] }
+        { "Free:" [ kilobytes ] }
+    } fancy-table. ;
 
 : nursery-room. ( seq -- ) "- Nursery space" print young-room. ;
 
 : aging-room. ( seq -- ) "- Aging space" print young-room. ;
 
 : mark-sweep-table. ( sizes -- )
-    { "Total:" "Allocated:" "Contiguous free:" "Total free:" } memory-table. ;
+    {
+        { "Total:" [ kilobytes ] }
+        { "Allocated:" [ kilobytes ] }
+        { "Total free:" [ kilobytes ] }
+        { "Contiguous free:" [ kilobytes ] }
+        { "Free list entries:" [ number>string ] }
+    } fancy-table. ;
 
 : tenured-room. ( seq -- ) "- Tenured space" print mark-sweep-table. ;
 
 : misc-room. ( seq -- )
     "- Miscellaneous buffers" print
-    { "Card array:" "Deck array:" "Mark stack:" } memory-table. ;
+    {
+        { "Card array:" [ kilobytes ] }
+        { "Deck array:" [ kilobytes ] }
+        { "Mark stack:" [ kilobytes ] }
+    } fancy-table. ;
 
 : data-room. ( -- )
     "==== DATA HEAP" print nl
     data-room
     3 cut [ nursery-room. nl ] dip
     3 cut [ aging-room. nl ] dip
-    4 cut [ tenured-room. nl ] dip
+    5 cut [ tenured-room. nl ] dip
     misc-room. ;
 
 : code-room. ( -- )
index ef66cc3cd6957d32dcecd911d6a22ffdbf74f452..30a41eb93db68043831885f46fc4805ac471ffeb 100644 (file)
@@ -423,7 +423,6 @@ tuple
     { "minor-gc" "memory" (( -- )) }
     { "gc" "memory" (( -- )) }
     { "compact-gc" "memory" (( -- )) }
-    { "gc-stats" "memory" f }
     { "(save-image)" "memory.private" (( path -- )) }
     { "(save-image-and-exit)" "memory.private" (( path -- )) }
     { "datastack" "kernel" (( -- ds )) }
@@ -509,7 +508,6 @@ tuple
     { "resize-byte-array" "byte-arrays" (( n byte-array -- newbyte-array )) }
     { "dll-valid?" "alien.libraries" (( dll -- ? )) }
     { "unimplemented" "kernel.private" (( -- * )) }
-    { "gc-reset" "memory" (( -- )) }
     { "jit-compile" "quotations" (( quot -- )) }
     { "load-locals" "locals.backend" (( ... n -- )) }
     { "check-datastack" "kernel.private" (( array in# out# -- ? )) }
index d33823b6240136463b5b1f56e28fc10c5d8946eb..7b74a00f996b4c4de9e83c2c7ebae290166f0184 100644 (file)
@@ -6,7 +6,6 @@ namespace factor
 aging_collector::aging_collector(factor_vm *parent_) :
        copying_collector<aging_space,aging_policy>(
                parent_,
-               &parent_->gc_stats.aging_stats,
                parent_->data->aging,
                aging_policy(parent_)) {}
 
index 8f4fabe9a727c634cfeeb923bda039b0a9e34ff1..5488c653239374ec1f7bc474c31d659fae0c3dc0 100644 (file)
@@ -11,17 +11,27 @@ template<typename Block> struct bump_allocator {
        explicit bump_allocator(cell size_, cell start_) :
                here(start_), start(start_), end(start_ + size_), size(size_) {}
 
-       inline bool contains_p(Block *block)
+       bool contains_p(Block *block)
        {
                return ((cell)block - start) < size;
        }
 
-       inline Block *allot(cell size)
+       Block *allot(cell size)
        {
                cell h = here;
                here = h + align(size,data_alignment);
                return (Block *)h;
        }
+
+       cell occupied_space()
+       {
+               return here - start;
+       }
+
+       cell free_space()
+       {
+               return end - here;
+       }
 };
 
 }
index 831c2388bb56f3cdb5bb2de6ce1001bc0afed6b2..d3670af3c0b1782ebe280d2962a72ca330eb3062 100755 (executable)
@@ -454,13 +454,8 @@ code_block *factor_vm::allot_code_block(cell size, code_block_type type)
                /* Insufficient room even after code GC, give up */
                if(block == NULL)
                {
-                       cell used, total_free, max_free;
-                       code->allocator->usage(&used,&total_free,&max_free);
-
-                       std::cout << "Code heap stats:\n";
-                       std::cout << "Used: " << used << "\n";
-                       std::cout << "Total free space: " << total_free << "\n";
-                       std::cout << "Largest free block: " << max_free << "\n";
+                       std::cout << "Code heap used: " << code->allocator->occupied_space() << "\n";
+                       std::cout << "Code heap free: " << code->allocator->free_space() << "\n";
                        fatal_error("Out of memory in add-compiled-block",0);
                }
        }
index ae53869ef202661f927e89140a05bbe26027b7a9..d38ec9e3f55a866e107b55fd5d9c3a830db31f67 100755 (executable)
@@ -199,13 +199,11 @@ void factor_vm::primitive_code_room()
 {
        growable_array a(this);
 
-       cell used, total_free, max_free;
-       code->allocator->usage(&used,&total_free,&max_free);
-
-       a.add(tag_fixnum(code->seg->size >> 10));
-       a.add(tag_fixnum(used >> 10));
-       a.add(tag_fixnum(total_free >> 10));
-       a.add(tag_fixnum(max_free >> 10));
+       a.add(tag_fixnum(code->allocator->size));
+       a.add(tag_fixnum(code->allocator->occupied_space()));
+       a.add(tag_fixnum(code->allocator->free_space()));
+       a.add(tag_fixnum(code->allocator->free_blocks.largest_free_block()));
+       a.add(tag_fixnum(code->allocator->free_blocks.free_block_count));
 
        a.trim();
        dpush(a.elements.value());
index 54683556b1abcfd31bcb71c88fcb1ae21ed81856..d3cfa246425f6f0a3c1a88d40729b613f9a2b116 100644 (file)
@@ -3,13 +3,11 @@ namespace factor
 
 template<typename TargetGeneration, typename Policy> struct collector_workhorse {
        factor_vm *parent;
-       generation_statistics *stats;
        TargetGeneration *target;
        Policy policy;
 
-       explicit collector_workhorse(factor_vm *parent_, generation_statistics *stats_, TargetGeneration *target_, Policy policy_) :
+       explicit collector_workhorse(factor_vm *parent_, TargetGeneration *target_, Policy policy_) :
                parent(parent_),
-               stats(stats_),
                target(target_),
                policy(policy_) {}
 
@@ -36,9 +34,6 @@ template<typename TargetGeneration, typename Policy> struct collector_workhorse
                memcpy(newpointer,untagged,size);
                untagged->h.forward_to(newpointer);
 
-               stats->object_count++;
-               stats->bytes_copied += size;
-
                policy.promoted_object(newpointer);
 
                return newpointer;
@@ -69,29 +64,34 @@ template<typename TargetGeneration, typename Policy> struct collector_workhorse
 template<typename TargetGeneration, typename Policy>
 inline static slot_visitor<collector_workhorse<TargetGeneration,Policy> > make_collector_workhorse(
        factor_vm *parent,
-       generation_statistics *stats,
        TargetGeneration *target,
        Policy policy)
 {
        return slot_visitor<collector_workhorse<TargetGeneration,Policy> >(parent,
-               collector_workhorse<TargetGeneration,Policy>(parent,stats,target,policy));
+               collector_workhorse<TargetGeneration,Policy>(parent,target,policy));
 }
 
 template<typename TargetGeneration, typename Policy> struct collector {
        factor_vm *parent;
        data_heap *data;
        code_heap *code;
-       generation_statistics *stats;
        TargetGeneration *target;
        slot_visitor<collector_workhorse<TargetGeneration,Policy> > workhorse;
+       cell cards_scanned;
+       cell decks_scanned;
+       cell card_scan_time;
+       cell code_blocks_scanned;
 
-       explicit collector(factor_vm *parent_, generation_statistics *stats_, TargetGeneration *target_, Policy policy_) :
+       explicit collector(factor_vm *parent_, TargetGeneration *target_, Policy policy_) :
                parent(parent_),
                data(parent_->data),
                code(parent_->code),
-               stats(stats_),
                target(target_),
-               workhorse(make_collector_workhorse(parent_,stats_,target_,policy_)) {}
+               workhorse(make_collector_workhorse(parent_,target_,policy_)),
+               cards_scanned(0),
+               decks_scanned(0),
+               card_scan_time(0),
+               code_blocks_scanned(0) {}
 
        void trace_handle(cell *handle)
        {
@@ -127,7 +127,7 @@ template<typename TargetGeneration, typename Policy> struct collector {
                for(; iter != end; iter++)
                {
                        trace_literal_references(*iter);
-                       parent->gc_stats.code_blocks_scanned++;
+                       code_blocks_scanned++;
                }
        }
 
@@ -195,7 +195,7 @@ template<typename TargetGeneration, typename Policy> struct collector {
                {
                        if(decks[deck_index] & mask)
                        {
-                               parent->gc_stats.decks_scanned++;
+                               decks_scanned++;
 
                                cell first_card = first_card_in_deck(deck_index);
                                cell last_card = last_card_in_deck(deck_index);
@@ -204,7 +204,7 @@ template<typename TargetGeneration, typename Policy> struct collector {
                                {
                                        if(cards[card_index] & mask)
                                        {
-                                               parent->gc_stats.cards_scanned++;
+                                               cards_scanned++;
 
                                                if(end < card_start_address(card_index))
                                                {
@@ -246,7 +246,7 @@ scan_next_object:                           {
                        }
                }
 
-end:           parent->gc_stats.card_scan_time += (current_micros() - start_time);
+end:           card_scan_time += (current_micros() - start_time);
        }
 };
 
index f79f97d34e53a279e9f6c5599de3649e40ef1871..2264b600dd484719259f7cb778f898fd470ced2c 100644 (file)
@@ -15,8 +15,8 @@ template<typename TargetGeneration, typename Policy>
 struct copying_collector : collector<TargetGeneration,Policy> {
        cell scan;
 
-       explicit copying_collector(factor_vm *parent_, generation_statistics *stats_, TargetGeneration *target_, Policy policy_) :
-               collector<TargetGeneration,Policy>(parent_,stats_,target_,policy_), scan(target_->here) {}
+       explicit copying_collector(factor_vm *parent_, TargetGeneration *target_, Policy policy_) :
+               collector<TargetGeneration,Policy>(parent_,target_,policy_), scan(target_->here) {}
 
        void cheneys_algorithm()
        {
index 3dd46fd848ba4729f6583e4ed68a776ae51c3590..d8b5ca3efb888faa084c4227d2c2ce2b519b90ae 100755 (executable)
@@ -206,24 +206,23 @@ void factor_vm::primitive_data_room()
 {
        growable_array a(this);
 
-       a.add(tag_fixnum((nursery.size) >> 10));
-       a.add(tag_fixnum((nursery.here - nursery.start) >> 10));
-       a.add(tag_fixnum((nursery.end - nursery.here) >> 10));
-
-       a.add(tag_fixnum((data->aging->size) >> 10));
-       a.add(tag_fixnum((data->aging->here - data->aging->start) >> 10));
-       a.add(tag_fixnum((data->aging->end - data->aging->here) >> 10));
-
-       cell used, total_free, max_free;
-       data->tenured->usage(&used,&total_free,&max_free);
-       a.add(tag_fixnum(data->tenured->size >> 10));
-       a.add(tag_fixnum(used >> 10));
-       a.add(tag_fixnum(total_free >> 10));
-       a.add(tag_fixnum(max_free >> 10));
-
-       a.add(tag_fixnum((data->cards_end - data->cards) >> 10));
-       a.add(tag_fixnum((data->decks_end - data->decks) >> 10));
-       a.add(tag_fixnum((data->tenured->mark_stack.capacity()) >> 10));
+       a.add(tag_fixnum(nursery.size));
+       a.add(tag_fixnum(nursery.occupied_space()));
+       a.add(tag_fixnum(nursery.free_space()));
+
+       a.add(tag_fixnum(data->aging->size));
+       a.add(tag_fixnum(data->aging->occupied_space()));
+       a.add(tag_fixnum(data->aging->free_space()));
+
+       a.add(tag_fixnum(data->tenured->size));
+       a.add(tag_fixnum(data->tenured->occupied_space()));
+       a.add(tag_fixnum(data->tenured->free_space()));
+       a.add(tag_fixnum(data->tenured->free_blocks.largest_free_block()));
+       a.add(tag_fixnum(data->tenured->free_blocks.free_block_count));
+
+       a.add(tag_fixnum(data->cards_end - data->cards));
+       a.add(tag_fixnum(data->decks_end - data->decks));
+       a.add(tag_fixnum(data->tenured->mark_stack.capacity()));
 
        a.trim();
        dpush(a.elements.value());
index 24a3e012376bafe4e00009b3652005a746a79988..6a235ec88de711b9819c3c563e034a85d982b832 100755 (executable)
@@ -38,7 +38,7 @@ void factor_vm::default_parameters(vm_parameters *p)
        p->max_pic_size = 3;
 
        p->fep = false;
-       p->verbosegc = false;
+       p->verbose_gc = false;
        p->signals = true;
 
 #ifdef WINDOWS
@@ -87,7 +87,7 @@ void factor_vm::init_parameters_from_args(vm_parameters *p, int argc, vm_char **
                else if(factor_arg(arg,STRING_LITERAL("-callbacks=%d"),&p->callback_size));
                else if(STRCMP(arg,STRING_LITERAL("-fep")) == 0) p->fep = true;
                else if(STRCMP(arg,STRING_LITERAL("-nosignals")) == 0) p->signals = false;
-               else if(STRCMP(arg,STRING_LITERAL("-verbosegc")) == 0) p->verbosegc = true;
+               else if(STRCMP(arg,STRING_LITERAL("-verbosegc")) == 0) p->verbose_gc = true;
                else if(STRNCMP(arg,STRING_LITERAL("-i="),3) == 0) p->image_path = arg + 3;
                else if(STRCMP(arg,STRING_LITERAL("-console")) == 0) p->console = true;
        }
@@ -142,7 +142,7 @@ void factor_vm::init_factor(vm_parameters *p)
        if(p->signals)
                init_signals();
 
-       verbosegc = p->verbosegc;
+       verbose_gc = p->verbose_gc;
 
        if(p->console)
                open_console();
diff --git a/vm/free_list.cpp b/vm/free_list.cpp
new file mode 100644 (file)
index 0000000..e104e0b
--- /dev/null
@@ -0,0 +1,138 @@
+#include "master.hpp"
+
+namespace factor
+{
+
+void free_list::clear_free_list()
+{
+       memset(this,0,sizeof(free_list));
+}
+
+void free_list::initial_free_list(cell start, cell end, cell occupied)
+{
+       clear_free_list();
+       if(occupied != end - start)
+       {
+               free_heap_block *last_block = (free_heap_block *)(start + occupied);
+               last_block->make_free(end - (cell)last_block);
+               add_to_free_list(last_block);
+       }
+}
+
+void free_list::add_to_free_list(free_heap_block *block)
+{
+       cell size = block->size();
+
+       free_block_count++;
+       free_space += size;
+
+       if(size < free_list_count * block_granularity)
+       {
+               int index = size / block_granularity;
+               block->next_free = small_blocks[index];
+               small_blocks[index] = block;
+       }
+       else
+       {
+               block->next_free = large_blocks;
+               large_blocks = block;
+       }
+}
+
+free_heap_block *free_list::find_free_block(cell size)
+{
+       cell attempt = size;
+
+       while(attempt < free_list_count * block_granularity)
+       {
+               int index = attempt / block_granularity;
+               free_heap_block *block = small_blocks[index];
+               if(block)
+               {
+                       small_blocks[index] = block->next_free;
+
+                       free_block_count--;
+                       free_space -= block->size();
+
+                       return block;
+               }
+
+               attempt++;
+       }
+
+       free_heap_block *prev = NULL;
+       free_heap_block *block = large_blocks;
+
+       while(block)
+       {
+               if(block->size() >= size)
+               {
+                       if(prev)
+                               prev->next_free = block->next_free;
+                       else
+                               large_blocks = block->next_free;
+
+                       free_block_count--;
+                       free_space -= block->size();
+
+                       return block;
+               }
+
+               prev = block;
+               block = block->next_free;
+       }
+
+       return NULL;
+}
+
+free_heap_block *free_list::split_free_block(free_heap_block *block, cell size)
+{
+       if(block->size() != size)
+       {
+               /* split the block in two */
+               free_heap_block *split = (free_heap_block *)((cell)block + size);
+               split->make_free(block->size() - size);
+               split->next_free = block->next_free;
+               block->make_free(size);
+               add_to_free_list(split);
+       }
+
+       return block;
+}
+
+bool free_list::can_allot_p(cell size)
+{
+       cell attempt = size;
+
+       while(attempt < free_list_count * block_granularity)
+       {
+               int index = attempt / block_granularity;
+               if(small_blocks[index]) return true;
+               attempt++;
+       }
+
+       free_heap_block *block = large_blocks;
+       while(block)
+       {
+               if(block->size() >= size) return true;
+               block = block->next_free;
+       }
+
+       return false;
+}
+
+cell free_list::largest_free_block()
+{
+       cell largest = 0;
+       free_heap_block *scan = large_blocks;
+
+       while(scan)
+       {
+               largest = std::max(largest,scan->size());
+               scan = scan->next_free;
+       }
+
+       return largest;
+}
+
+}
diff --git a/vm/free_list.hpp b/vm/free_list.hpp
new file mode 100644 (file)
index 0000000..28bc063
--- /dev/null
@@ -0,0 +1,42 @@
+namespace factor
+{
+
+static const cell free_list_count = 32;
+
+struct free_heap_block
+{
+       cell header;
+       free_heap_block *next_free;
+
+       bool free_p() const
+       {
+               return header & 1 == 1;
+       }
+
+       cell size() const
+       {
+               return header >> 3;
+       }
+
+       void make_free(cell size)
+       {
+               header = (size << 3) | 1;
+       }
+};
+
+struct free_list {
+       free_heap_block *small_blocks[free_list_count];
+       free_heap_block *large_blocks;
+       cell free_block_count;
+       cell free_space;
+
+       void clear_free_list();
+       void initial_free_list(cell start, cell end, cell occupied);
+       void add_to_free_list(free_heap_block *block);
+       free_heap_block *find_free_block(cell size);
+       free_heap_block *split_free_block(free_heap_block *block, cell size);
+       bool can_allot_p(cell size);
+       cell largest_free_block();
+};
+
+}
index d796379799ddba2732a3e3fe5b59726af6627573..d74dd5be9a88ad295f7be7c06fedc4c222056827 100644 (file)
@@ -1,34 +1,6 @@
 namespace factor
 {
 
-static const cell free_list_count = 32;
-
-struct free_heap_block
-{
-       cell header;
-       free_heap_block *next_free;
-
-       bool free_p() const
-       {
-               return header & 1 == 1;
-       }
-
-       cell size() const
-       {
-               return header >> 3;
-       }
-
-       void make_free(cell size)
-       {
-               header = (size << 3) | 1;
-       }
-};
-
-struct free_list {
-       free_heap_block *small_blocks[free_list_count];
-       free_heap_block *large_blocks;
-};
-
 template<typename Block> struct free_list_allocator {
        cell size;
        cell start;
@@ -37,21 +9,16 @@ template<typename Block> struct free_list_allocator {
        mark_bits<Block> state;
 
        explicit free_list_allocator(cell size, cell start);
+       void initial_free_list(cell occupied);
        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 initial_free_list(cell size);
-       void assert_free_block(free_heap_block *block);
-       free_heap_block *find_free_block(cell size);
-       free_heap_block *split_free_block(free_heap_block *block, cell size);
        bool can_allot_p(cell size);
        Block *allot(cell size);
        void free(Block *block);
-       void usage(cell *used, cell *total_free, cell *max_free);
-       cell occupied();
+       cell occupied_space();
+       cell free_space();
        void sweep();
        template<typename Iterator> void sweep(Iterator &iter);
        template<typename Iterator, typename Sizer> void compact(Iterator &iter, Sizer &sizer);
@@ -66,9 +33,9 @@ free_list_allocator<Block>::free_list_allocator(cell size_, cell start_) :
        initial_free_list(0);
 }
 
-template<typename Block> void free_list_allocator<Block>::clear_free_list()
+template<typename Block> void free_list_allocator<Block>::initial_free_list(cell occupied)
 {
-       memset(&free_blocks,0,sizeof(free_list));
+       free_blocks.initial_free_list(start,end,occupied);
 }
 
 template<typename Block> bool free_list_allocator<Block>::contains_p(Block *block)
@@ -91,125 +58,19 @@ template<typename Block> Block *free_list_allocator<Block>::next_block_after(Blo
        return (Block *)((cell)block + block->size());
 }
 
-template<typename Block> void free_list_allocator<Block>::add_to_free_list(free_heap_block *block)
-{
-       if(block->size() < free_list_count * block_granularity)
-       {
-               int index = block->size() / block_granularity;
-               block->next_free = free_blocks.small_blocks[index];
-               free_blocks.small_blocks[index] = block;
-       }
-       else
-       {
-               block->next_free = free_blocks.large_blocks;
-               free_blocks.large_blocks = block;
-       }
-}
-
-/* Called after reading the heap from the image file, and after heap compaction.
-Makes a free list consisting of one free block, at the very end. */
-template<typename Block> void free_list_allocator<Block>::initial_free_list(cell size)
-{
-       clear_free_list();
-       if(size != this->size)
-       {
-               free_heap_block *last_block = (free_heap_block *)(start + size);
-               last_block->make_free(end - (cell)last_block);
-               add_to_free_list(last_block);
-       }
-}
-
-template<typename Block> void free_list_allocator<Block>::assert_free_block(free_heap_block *block)
-{
-#ifdef FACTOR_DEBUG
-       assert(block->free_p());
-#endif
-}
-
-template<typename Block> free_heap_block *free_list_allocator<Block>::find_free_block(cell size)
-{
-       cell attempt = size;
-
-       while(attempt < free_list_count * block_granularity)
-       {
-               int index = attempt / block_granularity;
-               free_heap_block *block = free_blocks.small_blocks[index];
-               if(block)
-               {
-                       assert_free_block(block);
-                       free_blocks.small_blocks[index] = block->next_free;
-                       return block;
-               }
-
-               attempt *= 2;
-       }
-
-       free_heap_block *prev = NULL;
-       free_heap_block *block = free_blocks.large_blocks;
-
-       while(block)
-       {
-               assert_free_block(block);
-               if(block->size() >= size)
-               {
-                       if(prev)
-                               prev->next_free = block->next_free;
-                       else
-                               free_blocks.large_blocks = block->next_free;
-                       return block;
-               }
-
-               prev = block;
-               block = block->next_free;
-       }
-
-       return NULL;
-}
-
-template<typename Block> free_heap_block *free_list_allocator<Block>::split_free_block(free_heap_block *block, cell size)
-{
-       if(block->size() != size)
-       {
-               /* split the block in two */
-               free_heap_block *split = (free_heap_block *)((cell)block + size);
-               split->make_free(block->size() - size);
-               split->next_free = block->next_free;
-               block->make_free(size);
-               add_to_free_list(split);
-       }
-
-       return block;
-}
-
 template<typename Block> bool free_list_allocator<Block>::can_allot_p(cell size)
 {
-       cell attempt = size;
-
-       while(attempt < free_list_count * block_granularity)
-       {
-               int index = attempt / block_granularity;
-               if(free_blocks.small_blocks[index]) return true;
-               attempt *= 2;
-       }
-
-       free_heap_block *block = free_blocks.large_blocks;
-       while(block)
-       {
-               if(block->size() >= size) return true;
-               block = block->next_free;
-       }
-
-       return false;
+       return free_blocks.can_allot_p(size);
 }
 
 template<typename Block> Block *free_list_allocator<Block>::allot(cell size)
 {
        size = align(size,block_granularity);
 
-       free_heap_block *block = find_free_block(size);
+       free_heap_block *block = free_blocks.find_free_block(size);
        if(block)
        {
-               block = split_free_block(block,size);
+               block = free_blocks.split_free_block(block,size);
                return (Block *)block;
        }
        else
@@ -220,64 +81,23 @@ template<typename Block> void free_list_allocator<Block>::free(Block *block)
 {
        free_heap_block *free_block = (free_heap_block *)block;
        free_block->make_free(block->size());
-       add_to_free_list(free_block);
+       free_blocks.add_to_free_list(free_block);
 }
 
-/* Compute total sum of sizes of free blocks, and size of largest free block */
-template<typename Block> void free_list_allocator<Block>::usage(cell *used, cell *total_free, cell *max_free)
+template<typename Block> cell free_list_allocator<Block>::free_space()
 {
-       *used = 0;
-       *total_free = 0;
-       *max_free = 0;
-
-       Block *scan = first_block();
-       Block *end = last_block();
-
-       while(scan != end)
-       {
-               cell size = scan->size();
-
-               if(scan->free_p())
-               {
-                       *total_free += size;
-                       if(size > *max_free)
-                               *max_free = size;
-               }
-               else
-                       *used += size;
-
-               scan = next_block_after(scan);
-       }
+       return free_blocks.free_space;
 }
 
-/* The size of the heap after compaction */
-template<typename Block> cell free_list_allocator<Block>::occupied()
+template<typename Block> cell free_list_allocator<Block>::occupied_space()
 {
-       Block *scan = first_block();
-       Block *last = last_block();
-
-       while(scan != last)
-       {
-               if(scan->free_p()) break;
-               else scan = next_block_after(scan);
-       }
-
-       if(scan != last)
-       {
-               free_heap_block *free_block = (free_heap_block *)scan;
-               assert(free_block->free_p());
-               assert((cell)scan + free_block->size() == end);
-
-               return (cell)scan - (cell)first_block();
-       }
-       else
-               return size;
+       return size - free_blocks.free_space;
 }
 
 template<typename Block>
 void free_list_allocator<Block>::sweep()
 {
-       this->clear_free_list();
+       free_blocks.clear_free_list();
 
        Block *prev = NULL;
        Block *scan = this->first_block();
@@ -300,7 +120,7 @@ void free_list_allocator<Block>::sweep()
                else if(this->state.marked_p(scan))
                {
                        if(prev && prev->free_p())
-                               this->add_to_free_list((free_heap_block *)prev);
+                               free_blocks.add_to_free_list((free_heap_block *)prev);
                        prev = scan;
                }
                else
@@ -322,14 +142,14 @@ void free_list_allocator<Block>::sweep()
        }
 
        if(prev && prev->free_p())
-               this->add_to_free_list((free_heap_block *)prev);
+               free_blocks.add_to_free_list((free_heap_block *)prev);
 }
 
 template<typename Block>
 template<typename Iterator>
 void free_list_allocator<Block>::sweep(Iterator &iter)
 {
-       this->clear_free_list();
+       free_blocks.clear_free_list();
 
        Block *prev = NULL;
        Block *scan = this->first_block();
@@ -352,7 +172,7 @@ void free_list_allocator<Block>::sweep(Iterator &iter)
                else if(this->state.marked_p(scan))
                {
                        if(prev && prev->free_p())
-                               this->add_to_free_list((free_heap_block *)prev);
+                               free_blocks.add_to_free_list((free_heap_block *)prev);
                        prev = scan;
                        iter(scan,size);
                }
@@ -375,7 +195,7 @@ void free_list_allocator<Block>::sweep(Iterator &iter)
        }
 
        if(prev && prev->free_p())
-               this->add_to_free_list((free_heap_block *)prev);
+               free_blocks.add_to_free_list((free_heap_block *)prev);
 }
 
 template<typename Block, typename Iterator> struct heap_compactor {
@@ -403,11 +223,11 @@ template<typename Iterator, typename Sizer>
 void free_list_allocator<Block>::compact(Iterator &iter, Sizer &sizer)
 {
        heap_compactor<Block,Iterator> compactor(&state,first_block(),iter);
-       this->iterate(compactor,sizer);
+       iterate(compactor,sizer);
 
        /* Now update the free list; there will be a single free block at
        the end */
-       this->initial_free_list((cell)compactor.address - this->start);
+       free_blocks.initial_free_list(start,end,(cell)compactor.address - start);
 }
 
 /* During compaction we have to be careful and measure object sizes differently */
index 09e32574fd35e6b4f882dd2e9e6fe51ea2a5a1d2..0c90719b51a46c394fde6f9fd5b14835500dc303 100644 (file)
@@ -6,7 +6,6 @@ namespace factor
 full_collector::full_collector(factor_vm *parent_) :
        collector<tenured_space,full_policy>(
                parent_,
-               &parent_->gc_stats.full_stats,
                parent_->data->tenured,
                full_policy(parent_)) {}
 
index 2c361bcd19cf74b65e9960e068d5b057b2204b99..dd881c257b43378550a976dd254dd1cb47b7d1c5 100755 (executable)
--- a/vm/gc.cpp
+++ b/vm/gc.cpp
@@ -16,15 +16,6 @@ void factor_vm::update_code_heap_for_minor_gc(std::set<code_block *> *remembered
        for(; iter != end; iter++) update_literal_references(*iter);
 }
 
-void factor_vm::record_gc_stats(generation_statistics *stats)
-{
-       cell gc_elapsed = (current_micros() - current_gc->start_time);
-       stats->collections++;
-       stats->gc_time += gc_elapsed;
-       if(stats->max_gc_time < gc_elapsed)
-               stats->max_gc_time = gc_elapsed;
-}
-
 void factor_vm::gc(gc_op op, cell requested_bytes, bool trace_contexts_p)
 {
        assert(!gc_off);
@@ -34,7 +25,7 @@ void factor_vm::gc(gc_op op, cell requested_bytes, bool trace_contexts_p)
 
        current_gc = new gc_state(op);
 
-       if(verbosegc)
+       if(verbose_gc)
                std::cout << "GC requested, op=" << op << std::endl;
 
        /* Keep trying to GC higher and higher generations until we don't run out
@@ -62,7 +53,7 @@ void factor_vm::gc(gc_op op, cell requested_bytes, bool trace_contexts_p)
                        break;
                }
 
-               if(verbosegc)
+               if(verbose_gc)
                        std::cout << "GC rewind, op=" << current_gc->op << std::endl;
        }
 
@@ -70,37 +61,31 @@ void factor_vm::gc(gc_op op, cell requested_bytes, bool 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_mark_impl(trace_contexts_p);
                collect_sweep_impl();
                update_code_heap_words_and_literals();
-               record_gc_stats(&gc_stats.full_stats);
                break;
        case collect_compact_op:
                collect_mark_impl(trace_contexts_p);
                collect_compact_impl(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",current_gc->op);
                break;
        }
 
-       if(verbosegc)
+       if(verbose_gc)
                std::cout << "GC done, op=" << current_gc->op << std::endl;
 
        delete current_gc;
@@ -128,49 +113,6 @@ void factor_vm::primitive_compact_gc()
                true /* trace contexts? */);
 }
 
-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);
-
-       add_gc_stats(&gc_stats.nursery_stats,&result);
-       add_gc_stats(&gc_stats.aging_stats,&result);
-       add_gc_stats(&gc_stats.full_stats,&result);
-
-       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)));
-       result.add(tag<bignum>(ulong_long_to_bignum(gc_stats.decks_scanned)));
-       result.add(tag<bignum>(ulong_long_to_bignum(gc_stats.card_scan_time)));
-       result.add(allot_cell(gc_stats.code_blocks_scanned));
-
-       result.trim();
-       dpush(result.elements.value());
-}
-
-void factor_vm::clear_gc_stats()
-{
-       memset(&gc_stats,0,sizeof(gc_statistics));
-}
-
-void factor_vm::primitive_clear_gc_stats()
-{
-       clear_gc_stats();
-}
-
 /* classes.tuple uses this to reshape tuples; tools.deploy.shaker uses this
    to coalesce equal but distinct quotations and wrappers. */
 void factor_vm::primitive_become()
index a4162ed6203270bb047154689ef5eb9fda82b145..dff9923f6ef4c360471f33a705602079826dcc11 100755 (executable)
--- a/vm/gc.hpp
+++ b/vm/gc.hpp
@@ -10,25 +10,6 @@ enum gc_op {
        collect_growing_heap_op
 };
 
-/* statistics */
-struct generation_statistics {
-       cell collections;
-       u64 gc_time;
-       u64 max_gc_time;
-       cell object_count;
-       u64 bytes_copied;
-};
-
-struct gc_statistics {
-       generation_statistics nursery_stats;
-       generation_statistics aging_stats;
-       generation_statistics full_stats;
-       u64 cards_scanned;
-       u64 decks_scanned;
-       u64 card_scan_time;
-       u64 code_blocks_scanned;
-};
-
 struct gc_state {
        gc_op op;
        u64 start_time;
index c35c0a32b8c2c2f86669efc687a4c563b46d9871..fce730df5ad02736f902bca7e15767aa5257488b 100755 (executable)
@@ -22,8 +22,6 @@ void factor_vm::load_data_heap(FILE *file, image_header *h, vm_parameters *p)
                p->aging_size,
                p->tenured_size);
 
-       clear_gc_stats();
-
        fixnum bytes_read = fread((void*)data->tenured->start,1,h->data_size,file);
 
        if((cell)bytes_read != h->data_size)
@@ -280,9 +278,9 @@ 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->occupied();
+       h.data_size = data->tenured->occupied_space();
        h.code_relocation_base = code->seg->start;
-       h.code_size = code->allocator->occupied();
+       h.code_size = code->allocator->occupied_space();
 
        h.true_object = true_object;
        h.bignum_zero = bignum_zero;
index 3a5447c63bf4031bc208e6f41bb207d0fba155a9..f740b65f68f44d5ca25632e74d95add7d7ccb700 100755 (executable)
@@ -35,7 +35,7 @@ struct vm_parameters {
        cell young_size, aging_size, tenured_size;
        cell code_size;
        bool fep;
-       bool verbosegc;
+       bool verbose_gc;
        bool console;
        bool signals;
        cell max_pic_size;
index 1947c0ad50b9b9aca238961b216cbf368b6eff80..0873480addff31cb8108190133a4c4c83dba734f 100755 (executable)
@@ -51,6 +51,7 @@ namespace factor
 #include "code_block.hpp"
 #include "bump_allocator.hpp"
 #include "mark_bits.hpp"
+#include "free_list.hpp"
 #include "free_list_allocator.hpp"
 #include "write_barrier.hpp"
 #include "object_start_map.hpp"
index 07f9666f373fdf96f308fe674bd620748f2107d3..096bf7f7575cd253dc147762b29515c4ba9c4bb1 100644 (file)
@@ -6,7 +6,6 @@ namespace factor
 nursery_collector::nursery_collector(factor_vm *parent_) :
        copying_collector<aging_space,nursery_policy>(
                parent_,
-               &parent_->gc_stats.nursery_stats,
                parent_->data->aging,
                nursery_policy(parent_)) {}
 
index ea0254514827ea2c84769372e4c25b1dee02c36e..5ba57ec8afb93728e63809c64cce20527a43fd43 100644 (file)
@@ -55,7 +55,6 @@ PRIMITIVE_FORWARD(existsp)
 PRIMITIVE_FORWARD(minor_gc)
 PRIMITIVE_FORWARD(full_gc)
 PRIMITIVE_FORWARD(compact_gc)
-PRIMITIVE_FORWARD(gc_stats)
 PRIMITIVE_FORWARD(save_image)
 PRIMITIVE_FORWARD(save_image_and_exit)
 PRIMITIVE_FORWARD(datastack)
@@ -115,7 +114,6 @@ PRIMITIVE_FORWARD(call_clear)
 PRIMITIVE_FORWARD(resize_byte_array)
 PRIMITIVE_FORWARD(dll_validp)
 PRIMITIVE_FORWARD(unimplemented)
-PRIMITIVE_FORWARD(clear_gc_stats)
 PRIMITIVE_FORWARD(jit_compile)
 PRIMITIVE_FORWARD(load_locals)
 PRIMITIVE_FORWARD(check_datastack)
@@ -193,7 +191,6 @@ const primitive_type primitives[] = {
        primitive_minor_gc,
        primitive_full_gc,
        primitive_compact_gc,
-       primitive_gc_stats,
        primitive_save_image,
        primitive_save_image_and_exit,
        primitive_datastack,
@@ -279,7 +276,6 @@ const primitive_type primitives[] = {
        primitive_resize_byte_array,
        primitive_dll_validp,
        primitive_unimplemented,
-       primitive_clear_gc_stats,
        primitive_jit_compile,
        primitive_load_locals,
        primitive_check_datastack,
index ea7cb8ed7215f11a234a21febc6b0ba5aacb89e4..97009a5cebf694f73803cd39c41928c57078758c 100644 (file)
@@ -6,7 +6,6 @@ namespace factor
 to_tenured_collector::to_tenured_collector(factor_vm *myvm_) :
        collector<tenured_space,to_tenured_policy>(
                myvm_,
-               &myvm_->gc_stats.aging_stats,
                myvm_->data->tenured,
                to_tenured_policy(myvm_)) {}
 
index 0124affefadf1dcb50133ddd78b08fd5ec1391d2..36f0dce04952e9f876a93c7007ad1cabecae1060 100755 (executable)
--- a/vm/vm.hpp
+++ b/vm/vm.hpp
@@ -47,7 +47,7 @@ struct factor_vm
        bool gc_off;
 
        /* GC logging */
-       bool verbosegc;
+       bool verbose_gc;
 
        /* Data heap */
        data_heap *data;
@@ -61,9 +61,6 @@ struct factor_vm
        /* Only set if we're performing a GC */
        gc_state *current_gc;
 
-       /* Statistics */
-       gc_statistics gc_stats;
-
        /* If a runtime function needs to call another function which potentially
           allocates memory, it must wrap any local variable references to Factor
           objects in gc_root instances */
@@ -251,18 +248,13 @@ struct factor_vm
        void collect_sweep_impl();
        void collect_compact_impl(bool trace_contexts_p);
        void collect_growing_heap(cell requested_bytes, bool trace_contexts_p);
-       void record_gc_stats(generation_statistics *stats);
        void gc(gc_op op, cell requested_bytes, bool trace_contexts_p);
        void primitive_minor_gc();
        void primitive_full_gc();
        void primitive_compact_gc();
-       void primitive_gc_stats();
-       void clear_gc_stats();
        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)
        {