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)
/* 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)
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();
/* 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);
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;
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_) :
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;
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)
}
}
- decks_scanned++;
+ stats.decks_scanned++;
}
/* Trace all objects referenced from marked cards */
/* 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
{
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 */
trace_literal_references(iter->first,strategy);
}
- code_heap_scans++;
+ stats.code_heap_scans++;
}
}
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()
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;
}
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)
{
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);
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);
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);
collector.go();
update_dirty_code_blocks();
- reset_generation(data->aging());
+ reset_generation(aging_gen);
nursery.here = nursery.start;
}
}
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)
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++;
void factor_vm::gc()
{
- garbage_collection(data->tenured(),false,true,0);
+ garbage_collection(tenured_gen,false,true,0);
}
void factor_vm::primitive_gc()
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)));
}
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());
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()
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();
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!
{
/* 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
{
/* statistics */
-struct gc_stats {
+struct generation_stats {
cell collections;
u64 gc_time;
u64 max_gc_time;
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;
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()
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];
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)
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;
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_)
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));
}
/* 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;
}
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;
cell here;
cell size;
cell end;
-
+
cell init_zone(cell size_, cell start_)
{
size = size_;
end = start_ + size_;
return end;
}
-
+
inline bool contains_p(object *pointer)
{
return ((cell)pointer - start) < size;
}
+
+ inline object *allot(cell size)
+ {
+ cell h = here;
+ here = h + align8(size);
+ return (object *)h;
+ }
};
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;
}
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)
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();
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();
}
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)
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)
};
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)
{
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);
return false;
}
- zone *tenured = &data->generations[data->tenured()];
+ zone *tenured = &data->generations[tenured_gen];
h.magic = image_magic;
h.version = image_version;
if(immediate_p(*cell))
return;
- zone *tenured = &data->generations[data->tenured()];
+ zone *tenured = &data->generations[tenured_gen];
*cell += (tenured->start - data_relocation_base);
}
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;
box_boolean(stat(path,&sb) >= 0);
}
-segment::segment(factor_vm *myvm_, cell size_)
+segment::segment(cell size_)
{
- myvm = myvm_;
size = size_;
int pagesize = getpagesize();
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);
box_boolean(windows_stat(path));
}
-segment::segment(factor_vm *myvm_, cell size_)
+segment::segment(cell size_)
{
- myvm = myvm_;
size = size_;
char *mem;
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);
/* 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();
};
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();
void primitive_check_datastack();
// run
- /* Canonical T object. It's just a word */
- cell T;
-
void primitive_getenv();
void primitive_setenv();
void primitive_exit();
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);
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);
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);
}
// 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);
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();
#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);
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();
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
}
//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);
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);
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);