diff --git a/Makefile b/Makefile index 030a278543..2ea43706f4 100755 --- 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 \ diff --git a/basis/tools/memory/memory.factor b/basis/tools/memory/memory.factor index 2f1827a8ff..a5ed0fc0c1 100644 --- a/basis/tools/memory/memory.factor +++ b/basis/tools/memory/memory.factor @@ -9,35 +9,50 @@ IN: tools.memory 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. ( -- ) diff --git a/core/bootstrap/primitives.factor b/core/bootstrap/primitives.factor index ef66cc3cd6..30a41eb93d 100644 --- a/core/bootstrap/primitives.factor +++ b/core/bootstrap/primitives.factor @@ -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# -- ? )) } diff --git a/vm/aging_collector.cpp b/vm/aging_collector.cpp index d33823b624..7b74a00f99 100644 --- a/vm/aging_collector.cpp +++ b/vm/aging_collector.cpp @@ -6,7 +6,6 @@ namespace factor aging_collector::aging_collector(factor_vm *parent_) : copying_collector( parent_, - &parent_->gc_stats.aging_stats, parent_->data->aging, aging_policy(parent_)) {} diff --git a/vm/bump_allocator.hpp b/vm/bump_allocator.hpp index 8f4fabe9a7..5488c65323 100644 --- a/vm/bump_allocator.hpp +++ b/vm/bump_allocator.hpp @@ -11,17 +11,27 @@ template 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; + } }; } diff --git a/vm/code_block.cpp b/vm/code_block.cpp index 831c2388bb..d3670af3c0 100755 --- a/vm/code_block.cpp +++ b/vm/code_block.cpp @@ -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); } } diff --git a/vm/code_heap.cpp b/vm/code_heap.cpp index ae53869ef2..d38ec9e3f5 100755 --- a/vm/code_heap.cpp +++ b/vm/code_heap.cpp @@ -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()); diff --git a/vm/collector.hpp b/vm/collector.hpp index 54683556b1..d3cfa24642 100644 --- a/vm/collector.hpp +++ b/vm/collector.hpp @@ -3,13 +3,11 @@ namespace factor template 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 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 struct collector_workhorse template inline static slot_visitor > make_collector_workhorse( factor_vm *parent, - generation_statistics *stats, TargetGeneration *target, Policy policy) { return slot_visitor >(parent, - collector_workhorse(parent,stats,target,policy)); + collector_workhorse(parent,target,policy)); } template struct collector { factor_vm *parent; data_heap *data; code_heap *code; - generation_statistics *stats; TargetGeneration *target; slot_visitor > 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 struct collector { for(; iter != end; iter++) { trace_literal_references(*iter); - parent->gc_stats.code_blocks_scanned++; + code_blocks_scanned++; } } @@ -195,7 +195,7 @@ template 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 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); } }; diff --git a/vm/copying_collector.hpp b/vm/copying_collector.hpp index f79f97d34e..2264b600dd 100644 --- a/vm/copying_collector.hpp +++ b/vm/copying_collector.hpp @@ -15,8 +15,8 @@ template struct copying_collector : collector { cell scan; - explicit copying_collector(factor_vm *parent_, generation_statistics *stats_, TargetGeneration *target_, Policy policy_) : - collector(parent_,stats_,target_,policy_), scan(target_->here) {} + explicit copying_collector(factor_vm *parent_, TargetGeneration *target_, Policy policy_) : + collector(parent_,target_,policy_), scan(target_->here) {} void cheneys_algorithm() { diff --git a/vm/data_heap.cpp b/vm/data_heap.cpp index 3dd46fd848..d8b5ca3efb 100755 --- a/vm/data_heap.cpp +++ b/vm/data_heap.cpp @@ -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(nursery.size)); + a.add(tag_fixnum(nursery.occupied_space())); + a.add(tag_fixnum(nursery.free_space())); - 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)); + a.add(tag_fixnum(data->aging->size)); + a.add(tag_fixnum(data->aging->occupied_space())); + a.add(tag_fixnum(data->aging->free_space())); - 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->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) >> 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(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()); diff --git a/vm/factor.cpp b/vm/factor.cpp index 24a3e01237..6a235ec88d 100755 --- a/vm/factor.cpp +++ b/vm/factor.cpp @@ -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 index 0000000000..e104e0b9bd --- /dev/null +++ b/vm/free_list.cpp @@ -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 index 0000000000..28bc063883 --- /dev/null +++ b/vm/free_list.hpp @@ -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(); +}; + +} diff --git a/vm/free_list_allocator.hpp b/vm/free_list_allocator.hpp index d796379799..d74dd5be9a 100644 --- a/vm/free_list_allocator.hpp +++ b/vm/free_list_allocator.hpp @@ -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 struct free_list_allocator { cell size; cell start; @@ -37,21 +9,16 @@ template struct free_list_allocator { mark_bits 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 void sweep(Iterator &iter); template void compact(Iterator &iter, Sizer &sizer); @@ -66,9 +33,9 @@ free_list_allocator::free_list_allocator(cell size_, cell start_) : initial_free_list(0); } -template void free_list_allocator::clear_free_list() +template void free_list_allocator::initial_free_list(cell occupied) { - memset(&free_blocks,0,sizeof(free_list)); + free_blocks.initial_free_list(start,end,occupied); } template bool free_list_allocator::contains_p(Block *block) @@ -91,125 +58,19 @@ template Block *free_list_allocator::next_block_after(Blo return (Block *)((cell)block + block->size()); } -template void free_list_allocator::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 void free_list_allocator::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 void free_list_allocator::assert_free_block(free_heap_block *block) -{ -#ifdef FACTOR_DEBUG - assert(block->free_p()); -#endif -} - -template free_heap_block *free_list_allocator::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 free_heap_block *free_list_allocator::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 bool free_list_allocator::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 Block *free_list_allocator::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 void free_list_allocator::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 void free_list_allocator::usage(cell *used, cell *total_free, cell *max_free) +template cell free_list_allocator::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 cell free_list_allocator::occupied() +template cell free_list_allocator::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 void free_list_allocator::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::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::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 template void free_list_allocator::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::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::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 struct heap_compactor { @@ -403,11 +223,11 @@ template void free_list_allocator::compact(Iterator &iter, Sizer &sizer) { heap_compactor 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 */ diff --git a/vm/full_collector.cpp b/vm/full_collector.cpp index 09e32574fd..0c90719b51 100644 --- a/vm/full_collector.cpp +++ b/vm/full_collector.cpp @@ -6,7 +6,6 @@ namespace factor full_collector::full_collector(factor_vm *parent_) : collector( parent_, - &parent_->gc_stats.full_stats, parent_->data->tenured, full_policy(parent_)) {} diff --git a/vm/gc.cpp b/vm/gc.cpp index 2c361bcd19..dd881c257b 100755 --- a/vm/gc.cpp +++ b/vm/gc.cpp @@ -16,15 +16,6 @@ void factor_vm::update_code_heap_for_minor_gc(std::set *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(long_long_to_bignum(stats->gc_time))); - result->add(tag(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(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(ulong_long_to_bignum(total_gc_time))); - result.add(tag(ulong_long_to_bignum(gc_stats.cards_scanned))); - result.add(tag(ulong_long_to_bignum(gc_stats.decks_scanned))); - result.add(tag(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() diff --git a/vm/gc.hpp b/vm/gc.hpp index a4162ed620..dff9923f6e 100755 --- 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; diff --git a/vm/image.cpp b/vm/image.cpp index c35c0a32b8..fce730df5a 100755 --- a/vm/image.cpp +++ b/vm/image.cpp @@ -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; diff --git a/vm/image.hpp b/vm/image.hpp index 3a5447c63b..f740b65f68 100755 --- a/vm/image.hpp +++ b/vm/image.hpp @@ -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; diff --git a/vm/master.hpp b/vm/master.hpp index 1947c0ad50..0873480add 100755 --- a/vm/master.hpp +++ b/vm/master.hpp @@ -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" diff --git a/vm/nursery_collector.cpp b/vm/nursery_collector.cpp index 07f9666f37..096bf7f757 100644 --- a/vm/nursery_collector.cpp +++ b/vm/nursery_collector.cpp @@ -6,7 +6,6 @@ namespace factor nursery_collector::nursery_collector(factor_vm *parent_) : copying_collector( parent_, - &parent_->gc_stats.nursery_stats, parent_->data->aging, nursery_policy(parent_)) {} diff --git a/vm/primitives.cpp b/vm/primitives.cpp index ea02545148..5ba57ec8af 100644 --- a/vm/primitives.cpp +++ b/vm/primitives.cpp @@ -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, diff --git a/vm/to_tenured_collector.cpp b/vm/to_tenured_collector.cpp index ea7cb8ed72..97009a5ceb 100644 --- a/vm/to_tenured_collector.cpp +++ b/vm/to_tenured_collector.cpp @@ -6,7 +6,6 @@ namespace factor to_tenured_collector::to_tenured_collector(factor_vm *myvm_) : collector( myvm_, - &myvm_->gc_stats.aging_stats, myvm_->data->tenured, to_tenured_policy(myvm_)) {} diff --git a/vm/vm.hpp b/vm/vm.hpp index 0124affefa..36f0dce049 100755 --- 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 Type *allot(cell size) {