]> gitweb.factorcode.org Git - factor.git/commitdiff
vm: add primitives for getting at GC events, data-room and code-room primitives now...
authorSlava Pestov <slava@shill.local>
Tue, 27 Oct 2009 08:32:28 +0000 (03:32 -0500)
committerSlava Pestov <slava@shill.local>
Tue, 27 Oct 2009 08:32:28 +0000 (03:32 -0500)
13 files changed:
basis/stack-checker/known-words/known-words.factor
basis/tools/memory/memory.factor
basis/vm/vm.factor
core/bootstrap/primitives.factor
vm/byte_arrays.hpp
vm/code_heap.cpp
vm/code_heap.hpp
vm/data_heap.cpp
vm/data_heap.hpp
vm/gc.cpp
vm/primitives.cpp
vm/vm.cpp
vm/vm.hpp

index 1f03df9642ca9bc0cfe85078e457efb3702e6ecc..a5ddde9409e045482b3f6ca17df928c04523f188 100644 (file)
@@ -505,10 +505,10 @@ M: bad-executable summary
 
 \ (save-image-and-exit) { byte-array } { } define-primitive
 
-\ data-room { } { array } define-primitive
+\ data-room { } { byte-array } define-primitive
 \ data-room make-flushable
 
-\ code-room { } { array } define-primitive
+\ code-room { } { byte-array } define-primitive
 \ code-room  make-flushable
 
 \ micros { } { integer } define-primitive
@@ -713,3 +713,6 @@ M: bad-executable summary
 \ strip-stack-traces { } { } define-primitive
 
 \ <callback> { word } { alien } define-primitive
+
+\ enable-gc-events { } { } define-primitive
+\ disable-gc-events { } { object } define-primitive
index a5ed0fc0c1832a7f2a83fc12ea38262624b68238..8ede74d2fe2aa82e95be89abf1e1cbee6a253c58 100644 (file)
@@ -3,7 +3,9 @@
 USING: kernel sequences arrays generic assocs io math
 namespaces parser prettyprint strings io.styles words
 system sorting splitting grouping math.parser classes memory
-combinators fry ;
+combinators fry vm specialized-arrays accessors continuations
+classes.struct ;
+SPECIALIZED-ARRAY: gc-event
 IN: tools.memory
 
 <PRIVATE
@@ -13,51 +15,61 @@ IN: tools.memory
     dup length 4 > [ 3 cut* "," glue ] when
     " KB" append ;
 
-: fancy-table. ( seq alist -- )
-    [ [ nip first ] [ second call( obj -- str ) ] 2bi 2array ] 2map
+: fancy-table. ( obj alist -- )
+    [ [ nip first ] [ second call( obj -- str ) ] 2bi 2array ] with map
     simple-table. ;
 
-: young-room. ( seq -- )
+: copying-room. ( copying-sizes -- )
     {
-        { "Total:" [ kilobytes ] }
-        { "Allocated:" [ kilobytes ] }
-        { "Free:" [ kilobytes ] }
+        { "Size:" [ size>> kilobytes ] }
+        { "Occupied:" [ occupied>> kilobytes ] }
+        { "Free:" [ free>> kilobytes ] }
     } fancy-table. ;
 
-: nursery-room. ( seq -- ) "- Nursery space" print young-room. ;
+: nursery-room. ( data-room -- )
+    "- Nursery space" print nursery>> copying-room. ;
 
-: aging-room. ( seq -- ) "- Aging space" print young-room. ;
+: aging-room. ( data-room -- )
+    "- Aging space" print aging>> copying-room. ;
 
-: mark-sweep-table. ( sizes -- )
+: mark-sweep-table. ( mark-sweep-sizes -- )
     {
-        { "Total:" [ kilobytes ] }
-        { "Allocated:" [ kilobytes ] }
-        { "Total free:" [ kilobytes ] }
-        { "Contiguous free:" [ kilobytes ] }
-        { "Free list entries:" [ number>string ] }
+        { "Size:" [ size>> kilobytes ] }
+        { "Occupied:" [ occupied>> kilobytes ] }
+        { "Total free:" [ total-free>> kilobytes ] }
+        { "Contiguous free:" [ contiguous-free>> kilobytes ] }
+        { "Free block count:" [ free-block-count>> number>string ] }
     } fancy-table. ;
 
-: tenured-room. ( seq -- ) "- Tenured space" print mark-sweep-table. ;
+: tenured-room. ( data-room -- )
+    "- Tenured space" print tenured>> mark-sweep-table. ;
 
-: misc-room. ( seq -- )
+: misc-room. ( data-room -- )
     "- Miscellaneous buffers" print
     {
-        { "Card array:" [ kilobytes ] }
-        { "Deck array:" [ kilobytes ] }
-        { "Mark stack:" [ kilobytes ] }
+        { "Card array:" [ cards>> kilobytes ] }
+        { "Deck array:" [ decks>> kilobytes ] }
+        { "Mark stack:" [ 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
-    5 cut [ tenured-room. nl ] dip
-    misc-room. ;
+    data-room data-heap-room memory>struct {
+        [ nursery-room. nl ]
+        [ aging-room. nl ]
+        [ tenured-room. nl ]
+        [ misc-room. ]
+    } cleave ;
 
 : code-room. ( -- )
     "==== CODE HEAP" print nl
-    code-room mark-sweep-table. ;
+    code-room mark-sweep-sizes memory>struct mark-sweep-table. ;
+
+PRIVATE>
+
+: room. ( -- ) data-room. nl code-room. ;
+
+<PRIVATE
 
 : heap-stat-step ( obj counts sizes -- )
     [ [ class ] dip inc-at ]
@@ -65,8 +77,6 @@ IN: tools.memory
 
 PRIVATE>
 
-: room. ( -- ) data-room. nl code-room. ;
-
 : heap-stats ( -- counts sizes )
     [ ] instances H{ } clone H{ } clone
     [ '[ _ _ heap-stat-step ] each ] 2keep ;
@@ -82,3 +92,7 @@ PRIVATE>
             ] with-row
         ] each 2drop
     ] tabular-output nl ;
+
+: collect-gc-events ( quot -- events )
+    enable-gc-events [ ] [ disable-gc-events drop ] cleanup
+    disable-gc-events byte-array>gc-event-array ;
index 11d9dabb3d9a812abf9c55f10991c32ce5a2440a..1351ed10a3b2c584b8217ae2dc67c832ed57dc5f 100644 (file)
@@ -3,7 +3,7 @@
 USING: classes.struct alien.c-types alien.syntax ;
 IN: vm
 
-TYPEDEF: void* cell
+TYPEDEF: intptr_t cell
 C-TYPE: context
 
 STRUCT: zone
@@ -20,3 +20,56 @@ STRUCT: vm
     { userenv cell[70] } ;
 
 : vm-field-offset ( field -- offset ) vm offset-of ; inline
+
+C-ENUM:
+collect-nursery-op
+collect-aging-op
+collect-to-tenured-op
+collect-full-op
+collect-compact-op
+collect-growing-heap-op ;
+
+STRUCT: gc-event
+{ op uint }
+{ nursery-size-before cell }
+{ aging-size-before cell }
+{ tenured-size-before cell }
+{ tenured-free-block-count-before cell }
+{ code-size-before cell }
+{ code-free-block-count-before cell }
+{ nursery-size-after cell }
+{ aging-size-after cell }
+{ tenured-size-after cell }
+{ tenured-free-block-count-after cell }
+{ code-size-after cell }
+{ code-free-block-count-after cell }
+{ cards-scanned cell }
+{ decks-scanned cell }
+{ code-blocks-scanned cell }
+{ start-time ulonglong }
+{ total-time cell }
+{ card-scan-time cell }
+{ code-scan-time cell }
+{ data-sweep-time cell }
+{ code-sweep-time cell }
+{ compaction-time cell } ;
+
+STRUCT: copying-sizes
+{ size cell }
+{ occupied cell }
+{ free cell } ;
+
+STRUCT: mark-sweep-sizes
+{ size cell }
+{ occupied cell }
+{ total-free cell }
+{ contiguous-free cell }
+{ free-block-count cell } ;
+
+STRUCT: data-heap-room
+{ nursery copying-sizes }
+{ aging copying-sizes }
+{ tenured mark-sweep-sizes }
+{ cards cell }
+{ decks cell }
+{ mark-stack cell } ;
index 30a41eb93db68043831885f46fc4805ac471ffeb..81c09f19fafd3cbece22260ce6ef3a55a49ba76e 100644 (file)
@@ -432,8 +432,8 @@ tuple
     { "set-retainstack" "kernel" (( rs -- )) }
     { "set-callstack" "kernel" (( cs -- )) }
     { "exit" "system" (( n -- )) }
-    { "data-room" "memory" (( -- cards decks generations )) }
-    { "code-room" "memory" (( -- code-total code-used code-free largest-free-block )) }
+    { "data-room" "memory" (( -- data-room )) }
+    { "code-room" "memory" (( -- code-room )) }
     { "micros" "system" (( -- us )) }
     { "modify-code-heap" "compiler.units" (( alist -- )) }
     { "(dlopen)" "alien.libraries" (( path -- dll )) }
@@ -524,6 +524,8 @@ tuple
     { "vm-ptr" "vm" (( -- ptr )) }
     { "strip-stack-traces" "kernel.private" (( -- )) }
     { "<callback>" "alien" (( word -- alien )) }
+    { "enable-gc-events" "memory" (( -- )) }
+    { "disable-gc-events" "memory" (( -- events )) }
 } [ [ first3 ] dip swap make-primitive ] each-index
 
 ! Bump build number
index 8ca95d9d1e2e218400d22ac0580d1fb8dc8157c9..93cb775b1eebb60967565b81bf74059ca2c66944 100755 (executable)
@@ -13,4 +13,17 @@ struct growable_byte_array {
        void trim();
 };
 
+template<typename T> byte_array *factor_vm::byte_array_from_value(T *value)
+{
+       return byte_array_from_values(value,1);
+}
+
+template<typename T> byte_array *factor_vm::byte_array_from_values(T *values, cell len)
+{
+       cell size = sizeof(T) * len;
+       byte_array *data = allot_uninitialized_array<byte_array>(size);
+       memcpy(data->data<char>(),values,size);
+       return data;
+}
+
 }
index 444ec486f47b28ad4c9c3969a446f7a2695624cf..ac6669ca4900827823ee49b7ba988f7a0909f07b 100755 (executable)
@@ -196,19 +196,17 @@ void factor_vm::primitive_modify_code_heap()
        update_code_heap_words();
 }
 
-/* Push the free space and total size of the code heap */
 void factor_vm::primitive_code_room()
 {
-       growable_array a(this);
+       code_heap_room room;
 
-       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));
+       room.size             = code->allocator->size;
+       room.occupied_space   = code->allocator->occupied_space();
+       room.total_free       = code->allocator->free_space();
+       room.contiguous_free  = code->allocator->free_blocks.largest_free_block();
+       room.free_block_count = code->allocator->free_blocks.free_block_count;
 
-       a.trim();
-       dpush(a.elements.value());
+       dpush(tag<byte_array>(byte_array_from_value(&room)));
 }
 
 struct stack_trace_stripper {
index 38e53d9fbe0c14e83db2814ac8433899766d7d4f..8f4790d2f9e0bd6d5e3b1e1a5f64c48392c72438 100755 (executable)
@@ -28,4 +28,12 @@ struct code_heap {
        void code_heap_free(code_block *compiled);
 };
 
+struct code_heap_room {
+       cell size;
+       cell occupied_space;
+       cell total_free;
+       cell contiguous_free;
+       cell free_block_count;
+};
+
 }
index d8b5ca3efb888faa084c4227d2c2ce2b519b90ae..8f8db699f64000d7526e96e54b64b85e988974d8 100755 (executable)
@@ -201,31 +201,26 @@ void factor_vm::primitive_size()
        box_unsigned_cell(object_size(dpop()));
 }
 
-/* Push memory usage statistics in data heap */
 void factor_vm::primitive_data_room()
 {
-       growable_array a(this);
-
-       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());
+       data_heap_room room;
+
+       room.nursery_size             = nursery.size;
+       room.nursery_occupied         = nursery.occupied_space();
+       room.nursery_free             = nursery.free_space();
+       room.aging_size               = data->aging->size;
+       room.aging_occupied           = data->aging->occupied_space();
+       room.aging_free               = data->aging->free_space();
+       room.tenured_size             = data->tenured->size;
+       room.tenured_occupied         = data->tenured->occupied_space();
+       room.tenured_total_free       = data->tenured->free_space();
+       room.tenured_contiguous_free  = data->tenured->free_blocks.largest_free_block();
+       room.tenured_free_block_count = data->tenured->free_blocks.free_block_count;
+       room.cards                    = data->cards_end - data->cards;
+       room.decks                    = data->decks_end - data->decks;
+       room.mark_stack               = data->tenured->mark_stack.capacity();
+
+       dpush(tag<byte_array>(byte_array_from_value(&room)));
 }
 
 /* Disables GC and activates next-object ( -- obj ) primitive */
index c8d6ce0b70c213d4037a1de63c7d2fe8bc17f679..a4340248730dbb8198b024a16ebd2eb9dbb86271 100755 (executable)
@@ -31,4 +31,21 @@ struct data_heap {
        void reset_generation(tenured_space *gen);
 };
 
+struct data_heap_room {
+       cell nursery_size;
+       cell nursery_occupied;
+       cell nursery_free;
+       cell aging_size;
+       cell aging_occupied;
+       cell aging_free;
+       cell tenured_size;
+       cell tenured_occupied;
+       cell tenured_total_free;
+       cell tenured_contiguous_free;
+       cell tenured_free_block_count;
+       cell cards;
+       cell decks;
+       cell mark_stack;
+};
+
 }
index 5d9f68e6b89db8a96c14519d98ca0c1012be9ea7..0c8750ad925e650fcbd807aa6fa0f0b220f108b0 100755 (executable)
--- a/vm/gc.cpp
+++ b/vm/gc.cpp
@@ -128,13 +128,40 @@ gc_state::~gc_state()
        event = NULL;
 }
 
-void gc_state::start_again(gc_op op_, factor_vm *parent)
+void factor_vm::end_gc()
 {
-       event->ended_gc(parent);
-       if(parent->verbose_gc) std::cout << event << std::endl;
-       delete event;
-       event = new gc_event(op_,parent);
-       op = op_;
+       current_gc->event->ended_gc(this);
+       if(verbose_gc) std::cout << current_gc->event << std::endl;
+       if(gc_events) gc_events->push_back(*current_gc->event);
+       delete current_gc->event;
+       current_gc->event = NULL;
+}
+
+void factor_vm::start_gc_again()
+{
+       end_gc();
+
+       switch(current_gc->op)
+       {
+       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:
+       case collect_compact_op:
+               current_gc->op = collect_growing_heap_op;
+               break;
+       default:
+               critical_error("Bad GC op",current_gc->op);
+               break;
+       }
+
+       current_gc->event = new gc_event(current_gc->op,this);
 }
 
 void factor_vm::update_code_heap_for_minor_gc(std::set<code_block *> *remembered_set)
@@ -160,25 +187,7 @@ void factor_vm::gc(gc_op op, cell requested_bytes, bool trace_contexts_p)
        if(setjmp(current_gc->gc_unwind))
        {
                /* We come back here if a generation is full */
-               switch(current_gc->op)
-               {
-               case collect_nursery_op:
-                       current_gc->start_again(collect_aging_op,this);
-                       break;
-               case collect_aging_op:
-                       current_gc->start_again(collect_to_tenured_op,this);
-                       break;
-               case collect_to_tenured_op:
-                       current_gc->start_again(collect_full_op,this);
-                       break;
-               case collect_full_op:
-               case collect_compact_op:
-                       current_gc->start_again(collect_growing_heap_op,this);
-                       break;
-               default:
-                       critical_error("Bad GC op",current_gc->op);
-                       break;
-               }
+               start_gc_again();
        }
 
        switch(current_gc->op)
@@ -209,9 +218,7 @@ void factor_vm::gc(gc_op op, cell requested_bytes, bool trace_contexts_p)
                break;
        }
 
-       current_gc->event->ended_gc(this);
-
-       if(verbose_gc) std::cout << current_gc->event << std::endl;
+       end_gc();
 
        delete current_gc;
        current_gc = NULL;
@@ -338,4 +345,23 @@ object *factor_vm::allot_object(header header, cell size)
        return obj;
 }
 
+void factor_vm::primitive_enable_gc_events()
+{
+       gc_events = new std::vector<gc_event>();
+}
+
+void factor_vm::primitive_disable_gc_events()
+{
+       if(gc_events)
+       {
+               byte_array *data = byte_array_from_values(&gc_events->front(),gc_events->size());
+               dpush(tag<byte_array>(data));
+
+               delete gc_events;
+               gc_events = NULL;
+       }
+       else
+               dpush(false_object);
+}
+
 }
index 5ba57ec8afb93728e63809c64cce20527a43fd43..f950e19e5ad88136640f6ab6345a66ff0194439a 100644 (file)
@@ -128,6 +128,8 @@ PRIMITIVE_FORWARD(quot_compiled_p)
 PRIMITIVE_FORWARD(vm_ptr)
 PRIMITIVE_FORWARD(strip_stack_traces)
 PRIMITIVE_FORWARD(callback)
+PRIMITIVE_FORWARD(enable_gc_events)
+PRIMITIVE_FORWARD(disable_gc_events)
 
 const primitive_type primitives[] = {
        primitive_bignum_to_fixnum,
@@ -292,6 +294,8 @@ const primitive_type primitives[] = {
        primitive_vm_ptr,
        primitive_strip_stack_traces,
        primitive_callback,
+       primitive_enable_gc_events,
+       primitive_disable_gc_events,
 };
 
 }
index bcdead7da596f3030c30dbd46be9843ff702a4c4..2a41e96dfee79bb97a1d3598a60bc422da2ef81f 100755 (executable)
--- a/vm/vm.cpp
+++ b/vm/vm.cpp
@@ -8,6 +8,7 @@ factor_vm::factor_vm() :
        profiling_p(false),\r
        gc_off(false),\r
        current_gc(NULL),\r
+       gc_events(NULL),\r
        fep_disabled(false),\r
        full_output(false)\r
        { }\r
index 36f0dce04952e9f876a93c7007ad1cabecae1060..128982fb9cc54f7f5b6c799b7f02737e912aeae5 100755 (executable)
--- a/vm/vm.hpp
+++ b/vm/vm.hpp
@@ -61,6 +61,9 @@ struct factor_vm
        /* Only set if we're performing a GC */
        gc_state *current_gc;
 
+       /* If not NULL, we push GC events here */
+       std::vector<gc_event> *gc_events;
+
        /* 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 */
@@ -240,6 +243,8 @@ struct factor_vm
        }
 
        // gc
+       void end_gc();
+       void start_gc_again();
        void update_code_heap_for_minor_gc(std::set<code_block *> *remembered_set);
        void collect_nursery();
        void collect_aging();
@@ -255,6 +260,8 @@ 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 primitive_enable_gc_events();
+       void primitive_disable_gc_events();
 
        template<typename Type> Type *allot(cell size)
        {
@@ -336,6 +343,9 @@ struct factor_vm
        void primitive_uninitialized_byte_array();
        void primitive_resize_byte_array();
 
+       template<typename T> byte_array *byte_array_from_value(T *value);
+       template<typename T> byte_array *byte_array_from_values(T *values, cell len);
+
        //tuples
        tuple *allot_tuple(cell layout_);
        void primitive_tuple();