From a1aac4278696d303598679561cc8f399e1610cb7 Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Tue, 27 Oct 2009 21:31:28 -0500 Subject: [PATCH] vm: clean up gc events, remove -verbosegc switch, fix compaction bug --- basis/tools/memory/memory.factor | 74 +++++++++++--------------------- basis/vm/vm.factor | 42 ++++++++---------- vm/byte_arrays.hpp | 6 +-- vm/code_heap.cpp | 8 +++- vm/compaction.cpp | 8 ++-- vm/data_heap.cpp | 8 +++- vm/factor.cpp | 4 -- vm/free_list.cpp | 6 +-- vm/free_list_allocator.hpp | 15 +++++++ vm/gc.cpp | 48 +++------------------ vm/gc.hpp | 16 ++----- vm/image.hpp | 1 - vm/mark_bits.hpp | 14 ++++++ vm/master.hpp | 2 +- vm/tenured_space.hpp | 18 +------- vm/vm.hpp | 5 +-- 16 files changed, 110 insertions(+), 165 deletions(-) diff --git a/basis/tools/memory/memory.factor b/basis/tools/memory/memory.factor index 446f047150..6d0c4b7c86 100644 --- a/basis/tools/memory/memory.factor +++ b/basis/tools/memory/memory.factor @@ -10,10 +10,15 @@ IN: tools.memory string + reverse 3 group "," join reverse ; + : kilobytes ( n -- str ) - 1024 /i number>string - dup length 4 > [ 3 cut* "," glue ] when - " KB" append ; + 1024 /i commas " KB" append ; + +: micros>string ( n -- str ) + commas " microseconds" append ; : fancy-table. ( obj alist -- ) [ [ nip first ] [ second call( obj -- str ) ] 2bi 2array ] with map @@ -97,50 +102,23 @@ PRIVATE> enable-gc-events [ ] [ disable-gc-events drop ] cleanup disable-gc-events byte-array>gc-event-array ; inline -: generation-sizes-before ( events -- sizes ) - [ - { - [ start-time>> ] - [ nursery-size-before>> ] - [ aging-size-before>> ] - [ tenured-size-before>> ] - [ code-size-before>> ] - } cleave 5 narray - ] { } map-as ; +: gc-op-string ( op -- string ) + { + { collect-nursery-op [ "copying from nursery" ] } + { collect-aging-op [ "copying from aging" ] } + { collect-to-tenured-op [ "copying to tenured" ] } + { collect-full-op [ "mark and sweep" ] } + { collect-compact-op [ "mark and compact" ] } + { collect-growing-heap-op [ "grow heap" ] } + } case ; -: generation-sizes-after ( events -- sizes ) - [ - { - [ start-time>> ] - [ nursery-size-after>> ] - [ aging-size-after>> ] - [ tenured-size-after>> ] - [ code-size-after>> ] - } cleave 5 narray - ] { } map-as ; +: space-reclaimed ( event -- bytes ) + [ data-heap-before>> ] [ data-heap-after>> ] bi + [ [ nursery>> ] [ aging>> ] [ tenured>> ] tri [ occupied>> ] tri@ + + ] bi@ - ; -: reclaimed-space ( events -- sizes ) - [ - [ start-time>> ] [ - { - [ [ nursery-size-before>> ] [ nursery-size-after>> ] bi - ] - [ [ aging-size-before>> ] [ aging-size-after>> ] bi - ] - [ [ tenured-size-before>> ] [ tenured-size-after>> ] bi - ] - [ [ code-size-before>> ] [ code-size-after>> ] bi - ] - } cleave - + + + - ] bi 2array - ] { } map-as ; - -: allocated-space ( events -- sizes ) - 2 [ - [ second start-time>> ] [ - { - [ [ second nursery-size-before>> ] [ first nursery-size-after>> ] bi - ] - [ [ second aging-size-before>> ] [ first aging-size-after>> ] bi - ] - [ [ second tenured-size-before>> ] [ first tenured-size-after>> ] bi - ] - [ [ second code-size-before>> ] [ first code-size-after>> ] bi - ] - } cleave - + + + - ] bi 2array - ] { } map-as ; +: gc-event. ( event -- ) + { + { "Event type:" [ op>> gc-op-string ] } + { "Total time:" [ total-time>> micros>string ] } + { "Space reclaimed:" [ space-reclaimed kilobytes ] } + } fancy-table. ; diff --git a/basis/vm/vm.factor b/basis/vm/vm.factor index 1351ed10a3..6bcdd2862a 100644 --- a/basis/vm/vm.factor +++ b/basis/vm/vm.factor @@ -29,31 +29,6 @@ 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 } @@ -73,3 +48,20 @@ STRUCT: data-heap-room { cards cell } { decks cell } { mark-stack cell } ; + +STRUCT: gc-event +{ op uint } +{ data-heap-before data-heap-room } +{ code-heap-before mark-sweep-sizes } +{ data-heap-after data-heap-room } +{ code-heap-after mark-sweep-sizes } +{ 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 } ; diff --git a/vm/byte_arrays.hpp b/vm/byte_arrays.hpp index 93cb775b1e..0817f7dcdc 100755 --- a/vm/byte_arrays.hpp +++ b/vm/byte_arrays.hpp @@ -13,14 +13,14 @@ struct growable_byte_array { void trim(); }; -template byte_array *factor_vm::byte_array_from_value(T *value) +template byte_array *factor_vm::byte_array_from_value(Type *value) { return byte_array_from_values(value,1); } -template byte_array *factor_vm::byte_array_from_values(T *values, cell len) +template byte_array *factor_vm::byte_array_from_values(Type *values, cell len) { - cell size = sizeof(T) * len; + cell size = sizeof(Type) * len; byte_array *data = allot_uninitialized_array(size); memcpy(data->data(),values,size); return data; diff --git a/vm/code_heap.cpp b/vm/code_heap.cpp index ac6669ca49..77ae5180c8 100755 --- a/vm/code_heap.cpp +++ b/vm/code_heap.cpp @@ -196,7 +196,7 @@ void factor_vm::primitive_modify_code_heap() update_code_heap_words(); } -void factor_vm::primitive_code_room() +code_heap_room factor_vm::code_room() { code_heap_room room; @@ -206,6 +206,12 @@ void factor_vm::primitive_code_room() room.contiguous_free = code->allocator->free_blocks.largest_free_block(); room.free_block_count = code->allocator->free_blocks.free_block_count; + return room; +} + +void factor_vm::primitive_code_room() +{ + code_heap_room room = code_room(); dpush(tag(byte_array_from_value(&room))); } diff --git a/vm/compaction.cpp b/vm/compaction.cpp index 4540560ac4..bda8035858 100644 --- a/vm/compaction.cpp +++ b/vm/compaction.cpp @@ -55,10 +55,12 @@ struct compaction_sizer { cell operator()(object *obj) { - if(obj->free_p() || obj->h.hi_tag() != TUPLE_TYPE) - return obj->size(); - else + if(!forwarding_map->marked_p(obj)) + return forwarding_map->unmarked_space_starting_at(obj); + else if(obj->h.hi_tag() == TUPLE_TYPE) return align(tuple_size_with_forwarding(forwarding_map,obj),data_alignment); + else + return obj->size(); } }; diff --git a/vm/data_heap.cpp b/vm/data_heap.cpp index 8f8db699f6..b38674fe1f 100755 --- a/vm/data_heap.cpp +++ b/vm/data_heap.cpp @@ -201,7 +201,7 @@ void factor_vm::primitive_size() box_unsigned_cell(object_size(dpop())); } -void factor_vm::primitive_data_room() +data_heap_room factor_vm::data_room() { data_heap_room room; @@ -220,6 +220,12 @@ void factor_vm::primitive_data_room() room.decks = data->decks_end - data->decks; room.mark_stack = data->tenured->mark_stack.capacity(); + return room; +} + +void factor_vm::primitive_data_room() +{ + data_heap_room room = data_room(); dpush(tag(byte_array_from_value(&room))); } diff --git a/vm/factor.cpp b/vm/factor.cpp index 6a235ec88d..510900a036 100755 --- a/vm/factor.cpp +++ b/vm/factor.cpp @@ -38,7 +38,6 @@ void factor_vm::default_parameters(vm_parameters *p) p->max_pic_size = 3; p->fep = false; - p->verbose_gc = false; p->signals = true; #ifdef WINDOWS @@ -87,7 +86,6 @@ 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->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,8 +140,6 @@ void factor_vm::init_factor(vm_parameters *p) if(p->signals) init_signals(); - verbose_gc = p->verbose_gc; - if(p->console) open_console(); diff --git a/vm/free_list.cpp b/vm/free_list.cpp index 24ffab9f2c..644f62d870 100644 --- a/vm/free_list.cpp +++ b/vm/free_list.cpp @@ -108,10 +108,8 @@ cell free_list::largest_free_block() { if(large_blocks.size()) { - large_block_set::iterator end = large_blocks.end(); - free_heap_block *block = *end; - large_blocks.erase(end); - return block->size(); + large_block_set::reverse_iterator last = large_blocks.rbegin(); + return (*last)->size(); } else { diff --git a/vm/free_list_allocator.hpp b/vm/free_list_allocator.hpp index d74dd5be9a..dad54b644d 100644 --- a/vm/free_list_allocator.hpp +++ b/vm/free_list_allocator.hpp @@ -14,6 +14,7 @@ template struct free_list_allocator { Block *first_block(); Block *last_block(); Block *next_block_after(Block *block); + Block *next_allocated_block_after(Block *block); bool can_allot_p(cell size); Block *allot(cell size); void free(Block *block); @@ -58,6 +59,20 @@ template Block *free_list_allocator::next_block_after(Blo return (Block *)((cell)block + block->size()); } +template Block *free_list_allocator::next_allocated_block_after(Block *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; +} + template bool free_list_allocator::can_allot_p(cell size) { return free_blocks.can_allot_p(size); diff --git a/vm/gc.cpp b/vm/gc.cpp index 0c8750ad92..cce8298921 100755 --- a/vm/gc.cpp +++ b/vm/gc.cpp @@ -15,12 +15,8 @@ gc_event::gc_event(gc_op op_, factor_vm *parent) : code_sweep_time(0), compaction_time(0) { - nursery_size_before = parent->nursery.occupied_space(); - aging_size_before = parent->data->aging->occupied_space(); - tenured_size_before = parent->data->tenured->occupied_space(); - tenured_free_block_count_before = parent->data->tenured->free_blocks.free_block_count; - code_size_before = parent->code->allocator->occupied_space(); - code_free_block_count_before = parent->code->allocator->free_blocks.free_block_count; + data_heap_before = parent->data_room(); + code_heap_before = parent->code_room(); start_time = current_micros(); } @@ -79,44 +75,11 @@ void gc_event::ended_compaction() void gc_event::ended_gc(factor_vm *parent) { - nursery_size_after = parent->nursery.occupied_space(); - aging_size_after = parent->data->aging->occupied_space(); - tenured_size_after = parent->data->tenured->occupied_space(); - tenured_free_block_count_after = parent->data->tenured->free_blocks.free_block_count; - code_size_after = parent->code->allocator->occupied_space(); - code_free_block_count_after = parent->code->allocator->free_blocks.free_block_count; + data_heap_after = parent->data_room(); + code_heap_after = parent->code_room(); total_time = current_micros() - start_time; } -std::ostream &operator<<(std::ostream &out, const gc_event *event) -{ - out << ""; - return out; -} - gc_state::gc_state(gc_op op_, factor_vm *parent) : op(op_), start_time(current_micros()) { event = new gc_event(op,parent); @@ -131,7 +94,6 @@ gc_state::~gc_state() void factor_vm::end_gc() { 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; @@ -354,7 +316,7 @@ void factor_vm::primitive_disable_gc_events() { if(gc_events) { - byte_array *data = byte_array_from_values(&gc_events->front(),gc_events->size()); + byte_array *data = byte_array_from_values(&gc_events->first(),gc_events->size()); dpush(tag(data)); delete gc_events; diff --git a/vm/gc.hpp b/vm/gc.hpp index fe19f93ff1..90b5ce6032 100755 --- a/vm/gc.hpp +++ b/vm/gc.hpp @@ -12,18 +12,10 @@ enum gc_op { struct gc_event { gc_op op; - cell 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; + data_heap_room data_heap_before; + code_heap_room code_heap_before; + data_heap_room data_heap_after; + code_heap_room code_heap_after; cell cards_scanned; cell decks_scanned; cell code_blocks_scanned; diff --git a/vm/image.hpp b/vm/image.hpp index f740b65f68..cca0e9e378 100755 --- a/vm/image.hpp +++ b/vm/image.hpp @@ -35,7 +35,6 @@ struct vm_parameters { cell young_size, aging_size, tenured_size; cell code_size; bool fep; - bool verbose_gc; bool console; bool signals; cell max_pic_size; diff --git a/vm/mark_bits.hpp b/vm/mark_bits.hpp index 8b6b0c75eb..1b8fa913a6 100644 --- a/vm/mark_bits.hpp +++ b/vm/mark_bits.hpp @@ -154,6 +154,20 @@ template struct mark_bits { #endif return new_block; } + + /* Find the next allocated block without calling size() on unmarked + objects. */ + cell unmarked_space_starting_at(Block *original) + { + char *start = (char *)original; + char *scan = start; + char *end = (char *)(this->start + this->size); + + while(scan != end && !marked_p((Block *)scan)) + scan += block_granularity; + + return scan - start; + } }; } diff --git a/vm/master.hpp b/vm/master.hpp index 0873480add..9b525bd22e 100755 --- a/vm/master.hpp +++ b/vm/master.hpp @@ -59,6 +59,7 @@ namespace factor #include "aging_space.hpp" #include "tenured_space.hpp" #include "data_heap.hpp" +#include "code_heap.hpp" #include "gc.hpp" #include "debug.hpp" #include "strings.hpp" @@ -68,7 +69,6 @@ namespace factor #include "io.hpp" #include "image.hpp" #include "alien.hpp" -#include "code_heap.hpp" #include "callbacks.hpp" #include "vm.hpp" #include "tagged.hpp" diff --git a/vm/tenured_space.hpp b/vm/tenured_space.hpp index 1b3baeaf52..f77f17a56a 100644 --- a/vm/tenured_space.hpp +++ b/vm/tenured_space.hpp @@ -20,30 +20,16 @@ struct tenured_space : free_list_allocator { 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()); + return (cell)next_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); + return (cell)next_allocated_block_after(next); } void clear_mark_bits() diff --git a/vm/vm.hpp b/vm/vm.hpp index 128982fb9c..0844b47e51 100755 --- a/vm/vm.hpp +++ b/vm/vm.hpp @@ -46,9 +46,6 @@ struct factor_vm /* GC is off during heap walking */ bool gc_off; - /* GC logging */ - bool verbose_gc; - /* Data heap */ data_heap *data; @@ -223,6 +220,7 @@ struct factor_vm void set_data_heap(data_heap *data_); void init_data_heap(cell young_size, cell aging_size, cell tenured_size); void primitive_size(); + data_heap_room data_room(); void primitive_data_room(); void begin_scan(); void end_scan(); @@ -502,6 +500,7 @@ struct factor_vm void update_code_heap_words_and_literals(); void relocate_code_heap(); void primitive_modify_code_heap(); + code_heap_room code_room(); void primitive_code_room(); void primitive_strip_stack_traces();