vm: remove crummy old GC stats, split off free list code, clean up various other things

db4
Slava Pestov 2009-10-26 22:08:35 -05:00
parent 85dc9fda26
commit e793a72060
24 changed files with 286 additions and 364 deletions

View File

@ -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 \

View 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. ( -- )

View 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# -- ? )) }

View 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_)) {}

View 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;
}
};
}

View File

@ -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);
}
}

View File

@ -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());

View 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);
}
};

View 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()
{

View File

@ -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());

View File

@ -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();

138
vm/free_list.cpp Normal file
View File

@ -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;
}
}

42
vm/free_list.hpp Normal file
View File

@ -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();
};
}

View 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 */

View 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_)) {}

View File

@ -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()

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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"

View 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_)) {}

View 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,

View 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_)) {}

View File

@ -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)
{