vm: more code cleanups

db4
Slava Pestov 2009-10-07 08:33:54 -05:00
parent 1f76a64e91
commit 5c774d8c84
16 changed files with 201 additions and 187 deletions

View File

@ -3,12 +3,12 @@
namespace factor
{
code_heap::code_heap(factor_vm *myvm, cell size) : heap(myvm,size) {}
code_heap::code_heap(bool secure_gc, cell size) : heap(secure_gc,size) {}
void code_heap::write_barrier(code_block *compiled)
{
remembered_set[compiled] = myvm->data->nursery();
youngest_referenced_generation = myvm->data->nursery();
remembered_set[compiled] = nursery_gen;
youngest_referenced_generation = nursery_gen;
}
bool code_heap::needs_fixup_p(code_block *compiled)
@ -26,7 +26,7 @@ void code_heap::code_heap_free(code_block *compiled)
/* Allocate a code heap during startup */
void factor_vm::init_code_heap(cell size)
{
code = new code_heap(this,size);
code = new code_heap(secure_gc,size);
}
bool factor_vm::in_code_heap_p(cell ptr)
@ -228,7 +228,7 @@ critical here */
void factor_vm::compact_code_heap()
{
/* Free all unreachable code blocks, don't trace contexts */
garbage_collection(data->tenured(),false,false,0);
garbage_collection(tenured_gen,false,false,0);
/* Figure out where the code heap blocks are going to end up */
cell size = code->compute_heap_forwarding();

View File

@ -13,7 +13,7 @@ struct code_heap : heap {
/* Minimum value in the above map. */
cell youngest_referenced_generation;
explicit code_heap(factor_vm *myvm, cell size);
explicit code_heap(bool secure_gc, cell size);
void write_barrier(code_block *compiled);
bool needs_fixup_p(code_block *compiled);
void code_heap_free(code_block *compiled);

View File

@ -44,8 +44,8 @@ context *factor_vm::alloc_context()
else
{
new_context = new context;
new_context->datastack_region = new segment(this,ds_size);
new_context->retainstack_region = new segment(this,rs_size);
new_context->datastack_region = new segment(ds_size);
new_context->retainstack_region = new segment(rs_size);
}
return new_context;

View File

@ -5,7 +5,7 @@ namespace factor
void factor_vm::init_data_gc()
{
code->youngest_referenced_generation = data->nursery();
code->youngest_referenced_generation = nursery_gen;
}
gc_state::gc_state(data_heap *data_, bool growing_data_heap_, cell collecting_gen_) :
@ -71,7 +71,7 @@ template<typename Strategy> object *factor_vm::promote_object(object *untagged,
object *newpointer = strategy.allot(size);
if(!newpointer) longjmp(current_gc->gc_unwind,1);
gc_stats *s = &stats[current_gc->collecting_gen];
generation_stats *s = &stats.generations[current_gc->collecting_gen];
s->object_count++;
s->bytes_copied += size;
@ -91,7 +91,7 @@ template<typename Strategy> void factor_vm::trace_card(card *ptr, cell gen, cell
strategy.copy_reachable_objects(card_scan,&card_end);
cards_scanned++;
stats.cards_scanned++;
}
template<typename Strategy> void factor_vm::trace_card_deck(card_deck *deck, cell gen, card mask, card unmask, Strategy &strategy)
@ -122,7 +122,7 @@ template<typename Strategy> void factor_vm::trace_card_deck(card_deck *deck, cel
}
}
decks_scanned++;
stats.decks_scanned++;
}
/* Trace all objects referenced from marked cards */
@ -142,11 +142,11 @@ template<typename Strategy> void factor_vm::trace_generation_cards(cell gen, Str
/* after the collection, no old->nursery pointers remain
anywhere, but old->aging pointers might remain in tenured
space */
if(gen == data->tenured())
if(gen == tenured_gen)
unmask = card_points_to_nursery;
/* after the collection, all cards in aging space can be
cleared */
else if(gen == data->aging())
else if(gen == aging_gen)
unmask = card_mark_mask;
else
{
@ -201,7 +201,7 @@ template<typename Strategy> void factor_vm::trace_cards(Strategy &strategy)
for(i = current_gc->collecting_gen + 1; i < gen_count; i++)
trace_generation_cards(i,strategy);
card_scan_time += (current_micros() - start);
stats.card_scan_time += (current_micros() - start);
}
/* Copy all tagged pointers in a range of memory */
@ -353,7 +353,7 @@ template<typename Strategy> void factor_vm::trace_code_heap_roots(Strategy &stra
trace_literal_references(iter->first,strategy);
}
code_heap_scans++;
stats.code_heap_scans++;
}
}
@ -385,7 +385,7 @@ void factor_vm::free_unmarked_code_blocks()
literal_and_word_reference_updater updater(this);
code->free_unmarked(updater);
code->remembered_set.clear();
code->youngest_referenced_generation = data->tenured();
code->youngest_referenced_generation = tenured_gen;
}
void factor_vm::update_dirty_code_blocks()
@ -429,7 +429,11 @@ template<typename Strategy> Strategy &copying_collector<Strategy>::strategy()
template<typename Strategy> object *copying_collector<Strategy>::allot(cell size)
{
if(newspace->here + size <= newspace->end)
return myvm->allot_zone(newspace,size);
{
object *obj = newspace->allot(size);
myvm->allot_barrier(obj);
return obj;
}
else
return NULL;
}
@ -478,7 +482,7 @@ struct aging_collector : copying_collector<aging_collector>
explicit aging_collector(factor_vm *myvm_, zone *newspace_) :
copying_collector<aging_collector>(myvm_,newspace_),
tenured(&myvm->data->generations[myvm->data->tenured()]) {}
tenured(&myvm->data->generations[tenured_gen]) {}
bool should_copy_p(object *untagged)
{
@ -532,7 +536,7 @@ struct tenured_collector : copying_collector<tenured_collector>
void factor_vm::collect_nursery()
{
nursery_collector collector(this,&data->generations[data->aging()]);
nursery_collector collector(this,&data->generations[aging_gen]);
trace_roots(collector);
trace_contexts(collector);
@ -546,10 +550,10 @@ void factor_vm::collect_nursery()
void factor_vm::collect_aging()
{
std::swap(data->generations[data->aging()],data->semispaces[data->aging()]);
reset_generation(data->aging());
std::swap(data->generations[aging_gen],data->semispaces[aging_gen]);
reset_generation(aging_gen);
aging_collector collector(this,&data->generations[data->aging()]);
aging_collector collector(this,&data->generations[aging_gen]);
trace_roots(collector);
trace_contexts(collector);
@ -563,7 +567,7 @@ void factor_vm::collect_aging()
void factor_vm::collect_aging_again()
{
aging_again_collector collector(this,&data->generations[data->tenured()]);
aging_again_collector collector(this,&data->generations[tenured_gen]);
trace_roots(collector);
trace_contexts(collector);
@ -572,7 +576,7 @@ void factor_vm::collect_aging_again()
collector.go();
update_dirty_code_blocks();
reset_generation(data->aging());
reset_generation(aging_gen);
nursery.here = nursery.start;
}
@ -585,18 +589,18 @@ void factor_vm::collect_tenured(cell requested_bytes, bool trace_contexts_)
}
else
{
std::swap(data->generations[data->tenured()],data->semispaces[data->tenured()]);
reset_generation(data->tenured());
std::swap(data->generations[tenured_gen],data->semispaces[tenured_gen]);
reset_generation(tenured_gen);
}
tenured_collector collector(this,&data->generations[data->tenured()]);
tenured_collector collector(this,&data->generations[tenured_gen]);
trace_roots(collector);
if(trace_contexts_) trace_contexts(collector);
collector.go();
free_unmarked_code_blocks();
reset_generation(data->aging());
reset_generation(aging_gen);
nursery.here = nursery.start;
if(current_gc->growing_data_heap)
@ -605,7 +609,7 @@ void factor_vm::collect_tenured(cell requested_bytes, bool trace_contexts_)
void factor_vm::record_gc_stats()
{
gc_stats *s = &stats[current_gc->collecting_gen];
generation_stats *s = &stats.generations[current_gc->collecting_gen];
cell gc_elapsed = (current_micros() - current_gc->start_time);
s->collections++;
@ -673,7 +677,7 @@ void factor_vm::garbage_collection(cell collecting_gen_, bool growing_data_heap_
void factor_vm::gc()
{
garbage_collection(data->tenured(),false,true,0);
garbage_collection(tenured_gen,false,true,0);
}
void factor_vm::primitive_gc()
@ -690,7 +694,7 @@ void factor_vm::primitive_gc_stats()
for(i = 0; i < gen_count; i++)
{
gc_stats *s = &stats[i];
generation_stats *s = &stats.generations[i];
result.add(allot_cell(s->collections));
result.add(tag<bignum>(long_long_to_bignum(s->gc_time)));
result.add(tag<bignum>(long_long_to_bignum(s->max_gc_time)));
@ -702,10 +706,10 @@ void factor_vm::primitive_gc_stats()
}
result.add(tag<bignum>(ulong_long_to_bignum(total_gc_time)));
result.add(tag<bignum>(ulong_long_to_bignum(cards_scanned)));
result.add(tag<bignum>(ulong_long_to_bignum(decks_scanned)));
result.add(tag<bignum>(ulong_long_to_bignum(card_scan_time)));
result.add(allot_cell(code_heap_scans));
result.add(tag<bignum>(ulong_long_to_bignum(stats.cards_scanned)));
result.add(tag<bignum>(ulong_long_to_bignum(stats.decks_scanned)));
result.add(tag<bignum>(ulong_long_to_bignum(stats.card_scan_time)));
result.add(allot_cell(stats.code_heap_scans));
result.trim();
dpush(result.elements.value());
@ -713,13 +717,7 @@ void factor_vm::primitive_gc_stats()
void factor_vm::clear_gc_stats()
{
for(cell i = 0; i < gen_count; i++)
memset(&stats[i],0,sizeof(gc_stats));
cards_scanned = 0;
decks_scanned = 0;
card_scan_time = 0;
code_heap_scans = 0;
memset(&stats,0,sizeof(gc_stats));
}
void factor_vm::primitive_clear_gc_stats()
@ -763,7 +761,7 @@ void factor_vm::inline_gc(cell *gc_roots_base, cell gc_roots_size)
for(cell i = 0; i < gc_roots_size; i++)
gc_locals.push_back((cell)&gc_roots_base[i]);
garbage_collection(data->nursery(),false,true,0);
garbage_collection(nursery_gen,false,true,0);
for(cell i = 0; i < gc_roots_size; i++)
gc_locals.pop_back();
@ -775,15 +773,6 @@ VM_C_API void inline_gc(cell *gc_roots_base, cell gc_roots_size, factor_vm *myvm
VM_PTR->inline_gc(gc_roots_base,gc_roots_size);
}
inline object *factor_vm::allot_zone(zone *z, cell a)
{
cell h = z->here;
z->here = h + align8(a);
object *obj = (object *)h;
allot_barrier(obj);
return obj;
}
/*
* It is up to the caller to fill in the object's fields in a meaningful
* fashion!
@ -801,33 +790,32 @@ object *factor_vm::allot_object(header header, cell size)
{
/* If there is insufficient room, collect the nursery */
if(nursery.here + size > nursery.end)
garbage_collection(data->nursery(),false,true,0);
garbage_collection(nursery_gen,false,true,0);
cell h = nursery.here;
nursery.here = h + align8(size);
obj = (object *)h;
obj = nursery.allot(size);
}
/* If the object is bigger than the nursery, allocate it in
tenured space */
else
{
zone *tenured = &data->generations[data->tenured()];
zone *tenured = &data->generations[tenured_gen];
/* If tenured space does not have enough room, collect */
if(tenured->here + size > tenured->end)
{
gc();
tenured = &data->generations[data->tenured()];
tenured = &data->generations[tenured_gen];
}
/* If it still won't fit, grow the heap */
if(tenured->here + size > tenured->end)
{
garbage_collection(data->tenured(),true,true,size);
tenured = &data->generations[data->tenured()];
garbage_collection(tenured_gen,true,true,size);
tenured = &data->generations[tenured_gen];
}
obj = allot_zone(tenured,size);
obj = tenured->allot(size);
allot_barrier(obj);
/* Allows initialization code to store old->new pointers
without hitting the write barrier in the common case of

View File

@ -2,7 +2,7 @@ namespace factor
{
/* statistics */
struct gc_stats {
struct generation_stats {
cell collections;
u64 gc_time;
u64 max_gc_time;
@ -10,6 +10,14 @@ struct gc_stats {
u64 bytes_copied;
};
struct gc_stats {
generation_stats generations[gen_count];
u64 cards_scanned;
u64 decks_scanned;
u64 card_scan_time;
cell code_heap_scans;
};
struct gc_state {
/* The data heap we're collecting */
data_heap *data;
@ -35,17 +43,17 @@ struct gc_state {
inline bool collecting_nursery_p()
{
return collecting_gen == data->nursery();
return collecting_gen == nursery_gen;
}
inline bool collecting_aging_p()
{
return collecting_gen == data->aging();
return collecting_gen == aging_gen;
}
inline bool collecting_tenured_p()
{
return collecting_gen == data->tenured();
return collecting_gen == tenured_gen;
}
inline bool collecting_accumulation_gen_p()

View File

@ -25,7 +25,7 @@ data_heap::data_heap(factor_vm *myvm, cell young_size_, cell aging_size_, cell t
total_size += deck_size;
seg = new segment(myvm,total_size);
seg = new segment(total_size);
generations = new zone[gen_count];
semispaces = new zone[gen_count];
@ -43,17 +43,17 @@ data_heap::data_heap(factor_vm *myvm, cell young_size_, cell aging_size_, cell t
cell alloter = align(seg->start,deck_size);
alloter = generations[tenured()].init_zone(tenured_size,alloter);
alloter = semispaces[tenured()].init_zone(tenured_size,alloter);
alloter = generations[tenured_gen].init_zone(tenured_size,alloter);
alloter = semispaces[tenured_gen].init_zone(tenured_size,alloter);
alloter = generations[aging()].init_zone(aging_size,alloter);
alloter = semispaces[aging()].init_zone(aging_size,alloter);
alloter = generations[aging_gen].init_zone(aging_size,alloter);
alloter = semispaces[aging_gen].init_zone(aging_size,alloter);
alloter = generations[nursery()].init_zone(young_size,alloter);
alloter = semispaces[nursery()].init_zone(0,alloter);
alloter = generations[nursery_gen].init_zone(young_size,alloter);
alloter = semispaces[nursery_gen].init_zone(0,alloter);
if(seg->end - alloter > deck_size)
myvm->critical_error("Bug in alloc_data_heap",alloter);
critical_error("Bug in alloc_data_heap",alloter);
}
data_heap *factor_vm::grow_data_heap(data_heap *data, cell requested_bytes)
@ -103,7 +103,7 @@ void factor_vm::clear_allot_markers(cell gen)
their allocation pointers and cards reset. */
void factor_vm::reset_generation(cell gen)
{
assert(gen != data->nursery());
assert(gen != nursery_gen);
zone *z = &data->generations[gen];
z->here = z->start;
@ -117,11 +117,11 @@ void factor_vm::reset_generation(cell gen)
void factor_vm::set_data_heap(data_heap *data_)
{
data = data_;
nursery = data->generations[data->nursery()];
nursery = data->generations[nursery_gen];
nursery.here = nursery.start;
init_card_decks();
reset_generation(data->aging());
reset_generation(data->tenured());
reset_generation(aging_gen);
reset_generation(tenured_gen);
}
void factor_vm::init_data_heap(cell young_size, cell aging_size, cell tenured_size, bool secure_gc_)
@ -234,7 +234,7 @@ void factor_vm::primitive_data_room()
cell gen;
for(gen = 0; gen < gen_count; gen++)
{
zone *z = (gen == data->nursery() ? &nursery : &data->generations[gen]);
zone *z = (gen == nursery_gen ? &nursery : &data->generations[gen]);
a.add(tag_fixnum((z->end - z->here) >> 10));
a.add(tag_fixnum((z->size) >> 10));
}
@ -246,7 +246,7 @@ void factor_vm::primitive_data_room()
/* Disables GC and activates next-object ( -- obj ) primitive */
void factor_vm::begin_scan()
{
heap_scan_ptr = data->generations[data->tenured()].start;
heap_scan_ptr = data->generations[tenured_gen].start;
gc_off = true;
}
@ -265,7 +265,7 @@ cell factor_vm::next_object()
if(!gc_off)
general_error(ERROR_HEAP_SCAN,F,F,NULL);
if(heap_scan_ptr >= data->generations[data->tenured()].here)
if(heap_scan_ptr >= data->generations[tenured_gen].here)
return F;
object *obj = (object *)heap_scan_ptr;

View File

@ -22,6 +22,13 @@ struct zone {
{
return ((cell)pointer - start) < size;
}
inline object *allot(cell size)
{
cell h = here;
here = h + align8(size);
return (object *)h;
}
};
struct data_heap {
@ -43,19 +50,13 @@ struct data_heap {
char *decks;
char *decks_end;
/* the 0th generation is where new objects are allocated. */
cell nursery() { return 0; }
/* where objects hang around */
cell aging() { return 1; }
/* the oldest generation */
cell tenured() { return 2; }
explicit data_heap(factor_vm *myvm, cell young_size, cell aging_size, cell tenured_size);
~data_heap();
};
static const cell nursery_gen = 0;
static const cell aging_gen = 1;
static const cell tenured_gen = 2;
static const cell gen_count = 3;
}

View File

@ -3,26 +3,26 @@
namespace factor
{
void factor_vm::out_of_memory()
{
print_string("Out of memory\n\n");
dump_generations();
exit(1);
}
void fatal_error(const char* msg, cell tagged)
void fatal_error(const char *msg, cell tagged)
{
print_string("fatal_error: "); print_string(msg);
print_string(": "); print_cell_hex(tagged); nl();
exit(1);
}
void factor_vm::critical_error(const char* msg, cell tagged)
void critical_error(const char *msg, cell tagged)
{
print_string("You have triggered a bug in Factor. Please report.\n");
print_string("critical_error: "); print_string(msg);
print_string(": "); print_cell_hex(tagged); nl();
factorbug();
SIGNAL_VM_PTR()->factorbug();
}
void out_of_memory()
{
print_string("Out of memory\n\n");
SIGNAL_VM_PTR()->dump_generations();
exit(1);
}
void factor_vm::throw_error(cell error, stack_frame *callstack_top)

View File

@ -23,7 +23,9 @@ enum vm_error_type
ERROR_FP_TRAP,
};
void fatal_error(const char* msg, cell tagged);
void fatal_error(const char *msg, cell tagged);
void critical_error(const char *msg, cell tagged);
void out_of_memory();
void memory_signal_handler_impl();
void fp_signal_handler_impl();
void misc_signal_handler_impl();

View File

@ -11,10 +11,9 @@ void heap::clear_free_list()
memset(&free,0,sizeof(heap_free_list));
}
heap::heap(factor_vm *myvm_, cell size)
heap::heap(bool secure_gc_, cell size) : secure_gc(secure_gc_)
{
myvm = myvm_;
seg = new segment(myvm,align_page(size));
seg = new segment(align_page(size));
if(!seg) fatal_error("Out of memory in new_heap",size);
clear_free_list();
}
@ -85,7 +84,7 @@ void heap::build_free_list(cell size)
void heap::assert_free_block(free_heap_block *block)
{
if(block->type() != FREE_BLOCK_TYPE)
myvm->critical_error("Invalid block in free list",(cell)block);
critical_error("Invalid block in free list",(cell)block);
}
free_heap_block *heap::find_free_block(cell size)
@ -263,7 +262,7 @@ void heap::compact_heap()
heap_block *heap::free_allocated(heap_block *prev, heap_block *scan)
{
if(myvm->secure_gc)
if(secure_gc)
memset(scan + 1,0,scan->size() - sizeof(heap_block));
if(prev && prev->type() == FREE_BLOCK_TYPE)

View File

@ -10,12 +10,12 @@ struct heap_free_list {
};
struct heap {
factor_vm *myvm;
bool secure_gc;
segment *seg;
heap_free_list free;
unordered_map<heap_block *, char *> forwarding;
explicit heap(factor_vm *myvm, cell size);
explicit heap(bool secure_gc_, cell size);
inline heap_block *next_block(heap_block *block)
{

View File

@ -28,7 +28,7 @@ void factor_vm::load_data_heap(FILE *file, image_header *h, vm_parameters *p)
clear_gc_stats();
zone *tenured = &data->generations[data->tenured()];
zone *tenured = &data->generations[tenured_gen];
fixnum bytes_read = fread((void*)tenured->start,1,h->data_size,file);
@ -85,7 +85,7 @@ bool factor_vm::save_image(const vm_char *filename)
return false;
}
zone *tenured = &data->generations[data->tenured()];
zone *tenured = &data->generations[tenured_gen];
h.magic = image_magic;
h.version = image_version;
@ -156,7 +156,7 @@ void factor_vm::data_fixup(cell *cell)
if(immediate_p(*cell))
return;
zone *tenured = &data->generations[data->tenured()];
zone *tenured = &data->generations[tenured_gen];
*cell += (tenured->start - data_relocation_base);
}
@ -280,7 +280,7 @@ void factor_vm::relocate_data()
data_fixup(&bignum_pos_one);
data_fixup(&bignum_neg_one);
zone *tenured = &data->generations[data->tenured()];
zone *tenured = &data->generations[tenured_gen];
for(relocating = tenured->start;
relocating < tenured->here;

View File

@ -83,9 +83,8 @@ void factor_vm::primitive_existsp()
box_boolean(stat(path,&sb) >= 0);
}
segment::segment(factor_vm *myvm_, cell size_)
segment::segment(cell size_)
{
myvm = myvm_;
size = size_;
int pagesize = getpagesize();
@ -94,8 +93,7 @@ segment::segment(factor_vm *myvm_, cell size_)
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_PRIVATE,-1,0);
if(array == (char*)-1)
myvm->out_of_memory();
if(array == (char*)-1) out_of_memory();
if(mprotect(array,pagesize,PROT_NONE) == -1)
fatal_error("Cannot protect low guard page",(cell)array);

View File

@ -96,9 +96,8 @@ void factor_vm::primitive_existsp()
box_boolean(windows_stat(path));
}
segment::segment(factor_vm *myvm_, cell size_)
segment::segment(cell size_)
{
myvm = myvm_;
size = size_;
char *mem;
@ -106,7 +105,7 @@ segment::segment(factor_vm *myvm_, cell size_)
if((mem = (char *)VirtualAlloc(NULL, getpagesize() * 2 + size,
MEM_COMMIT, PAGE_EXECUTE_READWRITE)) == 0)
myvm->out_of_memory();
out_of_memory();
if (!VirtualProtect(mem, getpagesize(), PAGE_NOACCESS, &ignore))
fatal_error("Cannot allocate low guard page", (cell)mem);

View File

@ -9,12 +9,11 @@ inline cell align_page(cell a)
/* segments set up guard pages to check for under/overflow.
size must be a multiple of the page size */
struct segment {
factor_vm *myvm;
cell start;
cell size;
cell end;
explicit segment(factor_vm *myvm, cell size);
explicit segment(cell size);
~segment();
};

148
vm/vm.hpp
View File

@ -4,16 +4,97 @@ namespace factor
struct factor_vm
{
// First five fields accessed directly by assembler. See vm.factor
/* Current stacks */
context *stack_chain;
zone nursery; /* new objects are allocated here */
/* New objects are allocated here */
zone nursery;
/* Add this to a shifted address to compute write barrier offsets */
cell cards_offset;
cell decks_offset;
cell userenv[USER_ENV]; /* TAGGED user environment data; see getenv/setenv prims */
// contexts
/* TAGGED user environment data; see getenv/setenv prims */
cell userenv[USER_ENV];
/* Data stack and retain stack sizes */
cell ds_size, rs_size;
/* Pooling unused contexts to make callbacks cheaper */
context *unused_contexts;
/* Canonical T object. It's just a word */
cell T;
/* Is call counting enabled? */
bool profiling_p;
/* Global variables used to pass fault handler state from signal handler to
user-space */
cell signal_number;
cell signal_fault_addr;
unsigned int signal_fpu_status;
stack_frame *signal_callstack_top;
/* Zeroes out deallocated memory; set by the -securegc command line argument */
bool secure_gc;
/* A heap walk allows useful things to be done, like finding all
references to an object for debugging purposes. */
cell heap_scan_ptr;
/* GC is off during heap walking */
bool gc_off;
/* Data heap */
data_heap *data;
/* Where we store object start offsets in cards */
cell allot_markers_offset;
/* Only set if we're performing a GC */
gc_state *current_gc;
/* Statistics */
gc_stats stats;
/* Code heap */
code_heap *code;
/* 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 */
std::vector<cell> gc_locals;
std::vector<cell> gc_bignums;
/* Debugger */
bool fep_disabled;
bool full_output;
/* Canonical bignums */
cell bignum_zero;
cell bignum_pos_one;
cell bignum_neg_one;
/* Only used during image loading */
cell code_relocation_base;
cell data_relocation_base;
/* Method dispatch statistics */
cell megamorphic_cache_hits;
cell megamorphic_cache_misses;
cell cold_call_to_ic_transitions;
cell ic_to_pic_transitions;
cell pic_to_mega_transitions;
/* Indexed by PIC_TAG, PIC_HI_TAG, PIC_TUPLE, PIC_HI_TAG_TUPLE */
cell pic_counts[4];
/* Number of entries in a polymorphic inline cache */
cell max_pic_size;
// contexts
void reset_datastack();
void reset_retainstack();
void fix_stacks();
@ -32,9 +113,6 @@ struct factor_vm
void primitive_check_datastack();
// run
/* Canonical T object. It's just a word */
cell T;
void primitive_getenv();
void primitive_setenv();
void primitive_exit();
@ -46,23 +124,12 @@ struct factor_vm
void primitive_clone();
// profiler
bool profiling_p;
void init_profiler();
code_block *compile_profiling_stub(cell word_);
void set_profiling(bool profiling);
void primitive_profiling();
// errors
/* Global variables used to pass fault handler state from signal handler to
user-space */
cell signal_number;
cell signal_fault_addr;
unsigned int signal_fpu_status;
stack_frame *signal_callstack_top;
void out_of_memory();
void critical_error(const char* msg, cell tagged);
void throw_error(cell error, stack_frame *callstack_top);
void not_implemented_error();
bool in_page(cell fault, cell area, cell area_size, int offset);
@ -142,13 +209,6 @@ struct factor_vm
bignum *digit_stream_to_bignum(unsigned int n_digits, unsigned int (*producer)(unsigned int, factor_vm *), unsigned int radix, int negative_p);
//data_heap
bool secure_gc; /* Set by the -securegc command line argument */
bool gc_off; /* GC is off during heap walking */
data_heap *data;
/* A heap walk allows useful things to be done, like finding all
references to an object for debugging purposes. */
cell heap_scan_ptr;
void init_card_decks();
data_heap *grow_data_heap(data_heap *data, cell requested_bytes);
void clear_cards(cell gen);
@ -173,8 +233,6 @@ struct factor_vm
cell object_size(cell tagged);
//write barrier
cell allot_markers_offset;
inline card *addr_to_card(cell a)
{
return (card*)(((cell)(a) >> card_bits) + cards_offset);
@ -227,15 +285,6 @@ struct factor_vm
}
// data_gc
/* used during garbage collection only */
gc_state *current_gc;
/* statistics */
gc_stats stats[gen_count];
u64 cards_scanned;
u64 decks_scanned;
u64 card_scan_time;
cell code_heap_scans;
void init_data_gc();
template<typename Strategy> object *resolve_forwarding(object *untagged, Strategy &strategy);
template<typename Strategy> void trace_handle(cell *handle, Strategy &strategy);
@ -269,7 +318,6 @@ struct factor_vm
void clear_gc_stats();
void primitive_become();
void inline_gc(cell *gc_roots_base, cell gc_roots_size);
inline object *allot_zone(zone *z, cell a);
object *allot_object(header header, cell size);
void primitive_clear_gc_stats();
@ -301,22 +349,12 @@ struct factor_vm
#endif
}
// local roots
/* 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 */
std::vector<cell> gc_locals;
std::vector<cell> gc_bignums;
// generic arrays
template<typename Array> Array *allot_array_internal(cell capacity);
template<typename Array> bool reallot_array_in_place_p(Array *array, cell capacity);
template<typename Array> Array *reallot_array(Array *array_, cell capacity);
//debug
bool fep_disabled;
bool full_output;
void print_chars(string* str);
void print_word(word* word, cell nesting);
void print_factor_string(string* str);
@ -389,10 +427,6 @@ struct factor_vm
void primitive_wrapper();
//math
cell bignum_zero;
cell bignum_pos_one;
cell bignum_neg_one;
void primitive_bignum_to_fixnum();
void primitive_float_to_fixnum();
void primitive_fixnum_divint();
@ -519,8 +553,6 @@ struct factor_vm
code_block *add_code_block(cell type, cell code_, cell labels_, cell owner_, cell relocation_, cell literals_);
//code_heap
code_heap *code;
inline void check_code_pointer(cell ptr)
{
#ifdef FACTOR_DEBUG
@ -554,9 +586,6 @@ struct factor_vm
}
//image
cell code_relocation_base;
cell data_relocation_base;
void init_objects(image_header *h);
void load_data_heap(FILE *file, image_header *h, vm_parameters *p);
void load_code_heap(FILE *file, image_header *h, vm_parameters *p);
@ -646,9 +675,6 @@ struct factor_vm
void primitive_quot_compiled_p();
//dispatch
cell megamorphic_cache_hits;
cell megamorphic_cache_misses;
cell search_lookup_alist(cell table, cell klass);
cell search_lookup_hash(cell table, cell klass, cell hashcode);
cell nth_superclass(tuple_layout *layout, fixnum echelon);
@ -666,12 +692,6 @@ struct factor_vm
void primitive_dispatch_stats();
//inline cache
cell max_pic_size;
cell cold_call_to_ic_transitions;
cell ic_to_pic_transitions;
cell pic_to_mega_transitions;
cell pic_counts[4]; /* PIC_TAG, PIC_HI_TAG, PIC_TUPLE, PIC_HI_TAG_TUPLE */
void init_inline_caching(int max_size);
void deallocate_inline_cache(cell return_address);
cell determine_inline_cache_type(array *cache_entries);