vm/dispatch.o \
vm/errors.o \
vm/factor.o \
+ vm/free_list.o \
vm/full_collector.o \
vm/gc.o \
vm/image.o \
<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. ( -- )
{ "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 )) }
{ "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# -- ? )) }
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_)) {}
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;
+ }
};
}
/* 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);
}
}
{
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());
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_) {}
memcpy(newpointer,untagged,size);
untagged->h.forward_to(newpointer);
- stats->object_count++;
- stats->bytes_copied += size;
-
policy.promoted_object(newpointer);
return newpointer;
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)
{
for(; iter != end; iter++)
{
trace_literal_references(*iter);
- parent->gc_stats.code_blocks_scanned++;
+ code_blocks_scanned++;
}
}
{
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);
{
if(cards[card_index] & mask)
{
- parent->gc_stats.cards_scanned++;
+ cards_scanned++;
if(end < card_start_address(card_index))
{
}
}
-end: parent->gc_stats.card_scan_time += (current_micros() - start_time);
+end: card_scan_time += (current_micros() - start_time);
}
};
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()
{
{
growable_array a(this);
- a.add(tag_fixnum((nursery.size) >> 10));
- a.add(tag_fixnum((nursery.here - nursery.start) >> 10));
- a.add(tag_fixnum((nursery.end - nursery.here) >> 10));
-
- a.add(tag_fixnum((data->aging->size) >> 10));
- a.add(tag_fixnum((data->aging->here - data->aging->start) >> 10));
- a.add(tag_fixnum((data->aging->end - data->aging->here) >> 10));
-
- cell used, total_free, max_free;
- data->tenured->usage(&used,&total_free,&max_free);
- a.add(tag_fixnum(data->tenured->size >> 10));
- a.add(tag_fixnum(used >> 10));
- a.add(tag_fixnum(total_free >> 10));
- a.add(tag_fixnum(max_free >> 10));
-
- a.add(tag_fixnum((data->cards_end - data->cards) >> 10));
- a.add(tag_fixnum((data->decks_end - data->decks) >> 10));
- a.add(tag_fixnum((data->tenured->mark_stack.capacity()) >> 10));
+ a.add(tag_fixnum(nursery.size));
+ a.add(tag_fixnum(nursery.occupied_space()));
+ a.add(tag_fixnum(nursery.free_space()));
+
+ a.add(tag_fixnum(data->aging->size));
+ a.add(tag_fixnum(data->aging->occupied_space()));
+ a.add(tag_fixnum(data->aging->free_space()));
+
+ a.add(tag_fixnum(data->tenured->size));
+ a.add(tag_fixnum(data->tenured->occupied_space()));
+ a.add(tag_fixnum(data->tenured->free_space()));
+ a.add(tag_fixnum(data->tenured->free_blocks.largest_free_block()));
+ a.add(tag_fixnum(data->tenured->free_blocks.free_block_count));
+
+ a.add(tag_fixnum(data->cards_end - data->cards));
+ a.add(tag_fixnum(data->decks_end - data->decks));
+ a.add(tag_fixnum(data->tenured->mark_stack.capacity()));
a.trim();
dpush(a.elements.value());
p->max_pic_size = 3;
p->fep = false;
- p->verbosegc = false;
+ p->verbose_gc = false;
p->signals = true;
#ifdef WINDOWS
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;
}
if(p->signals)
init_signals();
- verbosegc = p->verbosegc;
+ verbose_gc = p->verbose_gc;
if(p->console)
open_console();
--- /dev/null
+#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;
+}
+
+}
--- /dev/null
+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();
+};
+
+}
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;
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);
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)
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
{
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();
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
}
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();
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);
}
}
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 {
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 */
full_collector::full_collector(factor_vm *parent_) :
collector<tenured_space,full_policy>(
parent_,
- &parent_->gc_stats.full_stats,
parent_->data->tenured,
full_policy(parent_)) {}
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);
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
break;
}
- if(verbosegc)
+ if(verbose_gc)
std::cout << "GC rewind, op=" << current_gc->op << std::endl;
}
{
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;
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()
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;
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)
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;
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;
#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"
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_)) {}
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)
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)
primitive_minor_gc,
primitive_full_gc,
primitive_compact_gc,
- primitive_gc_stats,
primitive_save_image,
primitive_save_image_and_exit,
primitive_datastack,
primitive_resize_byte_array,
primitive_dll_validp,
primitive_unimplemented,
- primitive_clear_gc_stats,
primitive_jit_compile,
primitive_load_locals,
primitive_check_datastack,
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_)) {}
bool gc_off;
/* GC logging */
- bool verbosegc;
+ bool verbose_gc;
/* Data heap */
data_heap *data;
/* 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 */
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)
{