vm: more code cleanups
parent
1f76a64e91
commit
5c774d8c84
|
@ -3,12 +3,12 @@
|
||||||
namespace factor
|
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)
|
void code_heap::write_barrier(code_block *compiled)
|
||||||
{
|
{
|
||||||
remembered_set[compiled] = myvm->data->nursery();
|
remembered_set[compiled] = nursery_gen;
|
||||||
youngest_referenced_generation = myvm->data->nursery();
|
youngest_referenced_generation = nursery_gen;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool code_heap::needs_fixup_p(code_block *compiled)
|
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 */
|
/* Allocate a code heap during startup */
|
||||||
void factor_vm::init_code_heap(cell size)
|
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)
|
bool factor_vm::in_code_heap_p(cell ptr)
|
||||||
|
@ -228,7 +228,7 @@ critical here */
|
||||||
void factor_vm::compact_code_heap()
|
void factor_vm::compact_code_heap()
|
||||||
{
|
{
|
||||||
/* Free all unreachable code blocks, don't trace contexts */
|
/* 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 */
|
/* Figure out where the code heap blocks are going to end up */
|
||||||
cell size = code->compute_heap_forwarding();
|
cell size = code->compute_heap_forwarding();
|
||||||
|
|
|
@ -13,7 +13,7 @@ struct code_heap : heap {
|
||||||
/* Minimum value in the above map. */
|
/* Minimum value in the above map. */
|
||||||
cell youngest_referenced_generation;
|
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);
|
void write_barrier(code_block *compiled);
|
||||||
bool needs_fixup_p(code_block *compiled);
|
bool needs_fixup_p(code_block *compiled);
|
||||||
void code_heap_free(code_block *compiled);
|
void code_heap_free(code_block *compiled);
|
||||||
|
|
|
@ -44,8 +44,8 @@ context *factor_vm::alloc_context()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
new_context = new context;
|
new_context = new context;
|
||||||
new_context->datastack_region = new segment(this,ds_size);
|
new_context->datastack_region = new segment(ds_size);
|
||||||
new_context->retainstack_region = new segment(this,rs_size);
|
new_context->retainstack_region = new segment(rs_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new_context;
|
return new_context;
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace factor
|
||||||
|
|
||||||
void factor_vm::init_data_gc()
|
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_) :
|
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);
|
object *newpointer = strategy.allot(size);
|
||||||
if(!newpointer) longjmp(current_gc->gc_unwind,1);
|
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->object_count++;
|
||||||
s->bytes_copied += size;
|
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);
|
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)
|
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 */
|
/* 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
|
/* after the collection, no old->nursery pointers remain
|
||||||
anywhere, but old->aging pointers might remain in tenured
|
anywhere, but old->aging pointers might remain in tenured
|
||||||
space */
|
space */
|
||||||
if(gen == data->tenured())
|
if(gen == tenured_gen)
|
||||||
unmask = card_points_to_nursery;
|
unmask = card_points_to_nursery;
|
||||||
/* after the collection, all cards in aging space can be
|
/* after the collection, all cards in aging space can be
|
||||||
cleared */
|
cleared */
|
||||||
else if(gen == data->aging())
|
else if(gen == aging_gen)
|
||||||
unmask = card_mark_mask;
|
unmask = card_mark_mask;
|
||||||
else
|
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++)
|
for(i = current_gc->collecting_gen + 1; i < gen_count; i++)
|
||||||
trace_generation_cards(i,strategy);
|
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 */
|
/* 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);
|
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);
|
literal_and_word_reference_updater updater(this);
|
||||||
code->free_unmarked(updater);
|
code->free_unmarked(updater);
|
||||||
code->remembered_set.clear();
|
code->remembered_set.clear();
|
||||||
code->youngest_referenced_generation = data->tenured();
|
code->youngest_referenced_generation = tenured_gen;
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::update_dirty_code_blocks()
|
void factor_vm::update_dirty_code_blocks()
|
||||||
|
@ -429,7 +429,11 @@ template<typename Strategy> Strategy ©ing_collector<Strategy>::strategy()
|
||||||
template<typename Strategy> object *copying_collector<Strategy>::allot(cell size)
|
template<typename Strategy> object *copying_collector<Strategy>::allot(cell size)
|
||||||
{
|
{
|
||||||
if(newspace->here + size <= newspace->end)
|
if(newspace->here + size <= newspace->end)
|
||||||
return myvm->allot_zone(newspace,size);
|
{
|
||||||
|
object *obj = newspace->allot(size);
|
||||||
|
myvm->allot_barrier(obj);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -478,7 +482,7 @@ struct aging_collector : copying_collector<aging_collector>
|
||||||
|
|
||||||
explicit aging_collector(factor_vm *myvm_, zone *newspace_) :
|
explicit aging_collector(factor_vm *myvm_, zone *newspace_) :
|
||||||
copying_collector<aging_collector>(myvm_,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)
|
bool should_copy_p(object *untagged)
|
||||||
{
|
{
|
||||||
|
@ -532,7 +536,7 @@ struct tenured_collector : copying_collector<tenured_collector>
|
||||||
|
|
||||||
void factor_vm::collect_nursery()
|
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_roots(collector);
|
||||||
trace_contexts(collector);
|
trace_contexts(collector);
|
||||||
|
@ -546,10 +550,10 @@ void factor_vm::collect_nursery()
|
||||||
|
|
||||||
void factor_vm::collect_aging()
|
void factor_vm::collect_aging()
|
||||||
{
|
{
|
||||||
std::swap(data->generations[data->aging()],data->semispaces[data->aging()]);
|
std::swap(data->generations[aging_gen],data->semispaces[aging_gen]);
|
||||||
reset_generation(data->aging());
|
reset_generation(aging_gen);
|
||||||
|
|
||||||
aging_collector collector(this,&data->generations[data->aging()]);
|
aging_collector collector(this,&data->generations[aging_gen]);
|
||||||
|
|
||||||
trace_roots(collector);
|
trace_roots(collector);
|
||||||
trace_contexts(collector);
|
trace_contexts(collector);
|
||||||
|
@ -563,7 +567,7 @@ void factor_vm::collect_aging()
|
||||||
|
|
||||||
void factor_vm::collect_aging_again()
|
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_roots(collector);
|
||||||
trace_contexts(collector);
|
trace_contexts(collector);
|
||||||
|
@ -572,7 +576,7 @@ void factor_vm::collect_aging_again()
|
||||||
collector.go();
|
collector.go();
|
||||||
update_dirty_code_blocks();
|
update_dirty_code_blocks();
|
||||||
|
|
||||||
reset_generation(data->aging());
|
reset_generation(aging_gen);
|
||||||
nursery.here = nursery.start;
|
nursery.here = nursery.start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -585,18 +589,18 @@ void factor_vm::collect_tenured(cell requested_bytes, bool trace_contexts_)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::swap(data->generations[data->tenured()],data->semispaces[data->tenured()]);
|
std::swap(data->generations[tenured_gen],data->semispaces[tenured_gen]);
|
||||||
reset_generation(data->tenured());
|
reset_generation(tenured_gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
tenured_collector collector(this,&data->generations[data->tenured()]);
|
tenured_collector collector(this,&data->generations[tenured_gen]);
|
||||||
|
|
||||||
trace_roots(collector);
|
trace_roots(collector);
|
||||||
if(trace_contexts_) trace_contexts(collector);
|
if(trace_contexts_) trace_contexts(collector);
|
||||||
collector.go();
|
collector.go();
|
||||||
free_unmarked_code_blocks();
|
free_unmarked_code_blocks();
|
||||||
|
|
||||||
reset_generation(data->aging());
|
reset_generation(aging_gen);
|
||||||
nursery.here = nursery.start;
|
nursery.here = nursery.start;
|
||||||
|
|
||||||
if(current_gc->growing_data_heap)
|
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()
|
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);
|
cell gc_elapsed = (current_micros() - current_gc->start_time);
|
||||||
s->collections++;
|
s->collections++;
|
||||||
|
@ -673,7 +677,7 @@ void factor_vm::garbage_collection(cell collecting_gen_, bool growing_data_heap_
|
||||||
|
|
||||||
void factor_vm::gc()
|
void factor_vm::gc()
|
||||||
{
|
{
|
||||||
garbage_collection(data->tenured(),false,true,0);
|
garbage_collection(tenured_gen,false,true,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::primitive_gc()
|
void factor_vm::primitive_gc()
|
||||||
|
@ -690,7 +694,7 @@ void factor_vm::primitive_gc_stats()
|
||||||
|
|
||||||
for(i = 0; i < gen_count; i++)
|
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(allot_cell(s->collections));
|
||||||
result.add(tag<bignum>(long_long_to_bignum(s->gc_time)));
|
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>(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(total_gc_time)));
|
||||||
result.add(tag<bignum>(ulong_long_to_bignum(cards_scanned)));
|
result.add(tag<bignum>(ulong_long_to_bignum(stats.cards_scanned)));
|
||||||
result.add(tag<bignum>(ulong_long_to_bignum(decks_scanned)));
|
result.add(tag<bignum>(ulong_long_to_bignum(stats.decks_scanned)));
|
||||||
result.add(tag<bignum>(ulong_long_to_bignum(card_scan_time)));
|
result.add(tag<bignum>(ulong_long_to_bignum(stats.card_scan_time)));
|
||||||
result.add(allot_cell(code_heap_scans));
|
result.add(allot_cell(stats.code_heap_scans));
|
||||||
|
|
||||||
result.trim();
|
result.trim();
|
||||||
dpush(result.elements.value());
|
dpush(result.elements.value());
|
||||||
|
@ -713,13 +717,7 @@ void factor_vm::primitive_gc_stats()
|
||||||
|
|
||||||
void factor_vm::clear_gc_stats()
|
void factor_vm::clear_gc_stats()
|
||||||
{
|
{
|
||||||
for(cell i = 0; i < gen_count; i++)
|
memset(&stats,0,sizeof(gc_stats));
|
||||||
memset(&stats[i],0,sizeof(gc_stats));
|
|
||||||
|
|
||||||
cards_scanned = 0;
|
|
||||||
decks_scanned = 0;
|
|
||||||
card_scan_time = 0;
|
|
||||||
code_heap_scans = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::primitive_clear_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++)
|
for(cell i = 0; i < gc_roots_size; i++)
|
||||||
gc_locals.push_back((cell)&gc_roots_base[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++)
|
for(cell i = 0; i < gc_roots_size; i++)
|
||||||
gc_locals.pop_back();
|
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);
|
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
|
* It is up to the caller to fill in the object's fields in a meaningful
|
||||||
* fashion!
|
* fashion!
|
||||||
|
@ -801,33 +790,32 @@ object *factor_vm::allot_object(header header, cell size)
|
||||||
{
|
{
|
||||||
/* If there is insufficient room, collect the nursery */
|
/* If there is insufficient room, collect the nursery */
|
||||||
if(nursery.here + size > nursery.end)
|
if(nursery.here + size > nursery.end)
|
||||||
garbage_collection(data->nursery(),false,true,0);
|
garbage_collection(nursery_gen,false,true,0);
|
||||||
|
|
||||||
cell h = nursery.here;
|
obj = nursery.allot(size);
|
||||||
nursery.here = h + align8(size);
|
|
||||||
obj = (object *)h;
|
|
||||||
}
|
}
|
||||||
/* If the object is bigger than the nursery, allocate it in
|
/* If the object is bigger than the nursery, allocate it in
|
||||||
tenured space */
|
tenured space */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
zone *tenured = &data->generations[data->tenured()];
|
zone *tenured = &data->generations[tenured_gen];
|
||||||
|
|
||||||
/* If tenured space does not have enough room, collect */
|
/* If tenured space does not have enough room, collect */
|
||||||
if(tenured->here + size > tenured->end)
|
if(tenured->here + size > tenured->end)
|
||||||
{
|
{
|
||||||
gc();
|
gc();
|
||||||
tenured = &data->generations[data->tenured()];
|
tenured = &data->generations[tenured_gen];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If it still won't fit, grow the heap */
|
/* If it still won't fit, grow the heap */
|
||||||
if(tenured->here + size > tenured->end)
|
if(tenured->here + size > tenured->end)
|
||||||
{
|
{
|
||||||
garbage_collection(data->tenured(),true,true,size);
|
garbage_collection(tenured_gen,true,true,size);
|
||||||
tenured = &data->generations[data->tenured()];
|
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
|
/* Allows initialization code to store old->new pointers
|
||||||
without hitting the write barrier in the common case of
|
without hitting the write barrier in the common case of
|
||||||
|
|
|
@ -2,7 +2,7 @@ namespace factor
|
||||||
{
|
{
|
||||||
|
|
||||||
/* statistics */
|
/* statistics */
|
||||||
struct gc_stats {
|
struct generation_stats {
|
||||||
cell collections;
|
cell collections;
|
||||||
u64 gc_time;
|
u64 gc_time;
|
||||||
u64 max_gc_time;
|
u64 max_gc_time;
|
||||||
|
@ -10,6 +10,14 @@ struct gc_stats {
|
||||||
u64 bytes_copied;
|
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 {
|
struct gc_state {
|
||||||
/* The data heap we're collecting */
|
/* The data heap we're collecting */
|
||||||
data_heap *data;
|
data_heap *data;
|
||||||
|
@ -35,17 +43,17 @@ struct gc_state {
|
||||||
|
|
||||||
inline bool collecting_nursery_p()
|
inline bool collecting_nursery_p()
|
||||||
{
|
{
|
||||||
return collecting_gen == data->nursery();
|
return collecting_gen == nursery_gen;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool collecting_aging_p()
|
inline bool collecting_aging_p()
|
||||||
{
|
{
|
||||||
return collecting_gen == data->aging();
|
return collecting_gen == aging_gen;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool collecting_tenured_p()
|
inline bool collecting_tenured_p()
|
||||||
{
|
{
|
||||||
return collecting_gen == data->tenured();
|
return collecting_gen == tenured_gen;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool collecting_accumulation_gen_p()
|
inline bool collecting_accumulation_gen_p()
|
||||||
|
|
|
@ -25,7 +25,7 @@ data_heap::data_heap(factor_vm *myvm, cell young_size_, cell aging_size_, cell t
|
||||||
|
|
||||||
total_size += deck_size;
|
total_size += deck_size;
|
||||||
|
|
||||||
seg = new segment(myvm,total_size);
|
seg = new segment(total_size);
|
||||||
|
|
||||||
generations = new zone[gen_count];
|
generations = new zone[gen_count];
|
||||||
semispaces = 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);
|
cell alloter = align(seg->start,deck_size);
|
||||||
|
|
||||||
alloter = generations[tenured()].init_zone(tenured_size,alloter);
|
alloter = generations[tenured_gen].init_zone(tenured_size,alloter);
|
||||||
alloter = semispaces[tenured()].init_zone(tenured_size,alloter);
|
alloter = semispaces[tenured_gen].init_zone(tenured_size,alloter);
|
||||||
|
|
||||||
alloter = generations[aging()].init_zone(aging_size,alloter);
|
alloter = generations[aging_gen].init_zone(aging_size,alloter);
|
||||||
alloter = semispaces[aging()].init_zone(aging_size,alloter);
|
alloter = semispaces[aging_gen].init_zone(aging_size,alloter);
|
||||||
|
|
||||||
alloter = generations[nursery()].init_zone(young_size,alloter);
|
alloter = generations[nursery_gen].init_zone(young_size,alloter);
|
||||||
alloter = semispaces[nursery()].init_zone(0,alloter);
|
alloter = semispaces[nursery_gen].init_zone(0,alloter);
|
||||||
|
|
||||||
if(seg->end - alloter > deck_size)
|
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)
|
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. */
|
their allocation pointers and cards reset. */
|
||||||
void factor_vm::reset_generation(cell gen)
|
void factor_vm::reset_generation(cell gen)
|
||||||
{
|
{
|
||||||
assert(gen != data->nursery());
|
assert(gen != nursery_gen);
|
||||||
|
|
||||||
zone *z = &data->generations[gen];
|
zone *z = &data->generations[gen];
|
||||||
z->here = z->start;
|
z->here = z->start;
|
||||||
|
@ -117,11 +117,11 @@ void factor_vm::reset_generation(cell gen)
|
||||||
void factor_vm::set_data_heap(data_heap *data_)
|
void factor_vm::set_data_heap(data_heap *data_)
|
||||||
{
|
{
|
||||||
data = data_;
|
data = data_;
|
||||||
nursery = data->generations[data->nursery()];
|
nursery = data->generations[nursery_gen];
|
||||||
nursery.here = nursery.start;
|
nursery.here = nursery.start;
|
||||||
init_card_decks();
|
init_card_decks();
|
||||||
reset_generation(data->aging());
|
reset_generation(aging_gen);
|
||||||
reset_generation(data->tenured());
|
reset_generation(tenured_gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::init_data_heap(cell young_size, cell aging_size, cell tenured_size, bool secure_gc_)
|
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;
|
cell gen;
|
||||||
for(gen = 0; gen < gen_count; 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->end - z->here) >> 10));
|
||||||
a.add(tag_fixnum((z->size) >> 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 */
|
/* Disables GC and activates next-object ( -- obj ) primitive */
|
||||||
void factor_vm::begin_scan()
|
void factor_vm::begin_scan()
|
||||||
{
|
{
|
||||||
heap_scan_ptr = data->generations[data->tenured()].start;
|
heap_scan_ptr = data->generations[tenured_gen].start;
|
||||||
gc_off = true;
|
gc_off = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ cell factor_vm::next_object()
|
||||||
if(!gc_off)
|
if(!gc_off)
|
||||||
general_error(ERROR_HEAP_SCAN,F,F,NULL);
|
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;
|
return F;
|
||||||
|
|
||||||
object *obj = (object *)heap_scan_ptr;
|
object *obj = (object *)heap_scan_ptr;
|
||||||
|
|
|
@ -22,6 +22,13 @@ struct zone {
|
||||||
{
|
{
|
||||||
return ((cell)pointer - start) < size;
|
return ((cell)pointer - start) < size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline object *allot(cell size)
|
||||||
|
{
|
||||||
|
cell h = here;
|
||||||
|
here = h + align8(size);
|
||||||
|
return (object *)h;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct data_heap {
|
struct data_heap {
|
||||||
|
@ -43,19 +50,13 @@ struct data_heap {
|
||||||
char *decks;
|
char *decks;
|
||||||
char *decks_end;
|
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);
|
explicit data_heap(factor_vm *myvm, cell young_size, cell aging_size, cell tenured_size);
|
||||||
~data_heap();
|
~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;
|
static const cell gen_count = 3;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,26 +3,26 @@
|
||||||
namespace factor
|
namespace factor
|
||||||
{
|
{
|
||||||
|
|
||||||
void factor_vm::out_of_memory()
|
void fatal_error(const char *msg, cell tagged)
|
||||||
{
|
|
||||||
print_string("Out of memory\n\n");
|
|
||||||
dump_generations();
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fatal_error(const char* msg, cell tagged)
|
|
||||||
{
|
{
|
||||||
print_string("fatal_error: "); print_string(msg);
|
print_string("fatal_error: "); print_string(msg);
|
||||||
print_string(": "); print_cell_hex(tagged); nl();
|
print_string(": "); print_cell_hex(tagged); nl();
|
||||||
exit(1);
|
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("You have triggered a bug in Factor. Please report.\n");
|
||||||
print_string("critical_error: "); print_string(msg);
|
print_string("critical_error: "); print_string(msg);
|
||||||
print_string(": "); print_cell_hex(tagged); nl();
|
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)
|
void factor_vm::throw_error(cell error, stack_frame *callstack_top)
|
||||||
|
|
|
@ -23,7 +23,9 @@ enum vm_error_type
|
||||||
ERROR_FP_TRAP,
|
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 memory_signal_handler_impl();
|
||||||
void fp_signal_handler_impl();
|
void fp_signal_handler_impl();
|
||||||
void misc_signal_handler_impl();
|
void misc_signal_handler_impl();
|
||||||
|
|
|
@ -11,10 +11,9 @@ void heap::clear_free_list()
|
||||||
memset(&free,0,sizeof(heap_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(align_page(size));
|
||||||
seg = new segment(myvm,align_page(size));
|
|
||||||
if(!seg) fatal_error("Out of memory in new_heap",size);
|
if(!seg) fatal_error("Out of memory in new_heap",size);
|
||||||
clear_free_list();
|
clear_free_list();
|
||||||
}
|
}
|
||||||
|
@ -85,7 +84,7 @@ void heap::build_free_list(cell size)
|
||||||
void heap::assert_free_block(free_heap_block *block)
|
void heap::assert_free_block(free_heap_block *block)
|
||||||
{
|
{
|
||||||
if(block->type() != FREE_BLOCK_TYPE)
|
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)
|
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)
|
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));
|
memset(scan + 1,0,scan->size() - sizeof(heap_block));
|
||||||
|
|
||||||
if(prev && prev->type() == FREE_BLOCK_TYPE)
|
if(prev && prev->type() == FREE_BLOCK_TYPE)
|
||||||
|
|
|
@ -10,12 +10,12 @@ struct heap_free_list {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct heap {
|
struct heap {
|
||||||
factor_vm *myvm;
|
bool secure_gc;
|
||||||
segment *seg;
|
segment *seg;
|
||||||
heap_free_list free;
|
heap_free_list free;
|
||||||
unordered_map<heap_block *, char *> forwarding;
|
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)
|
inline heap_block *next_block(heap_block *block)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,7 +28,7 @@ void factor_vm::load_data_heap(FILE *file, image_header *h, vm_parameters *p)
|
||||||
|
|
||||||
clear_gc_stats();
|
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);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
zone *tenured = &data->generations[data->tenured()];
|
zone *tenured = &data->generations[tenured_gen];
|
||||||
|
|
||||||
h.magic = image_magic;
|
h.magic = image_magic;
|
||||||
h.version = image_version;
|
h.version = image_version;
|
||||||
|
@ -156,7 +156,7 @@ void factor_vm::data_fixup(cell *cell)
|
||||||
if(immediate_p(*cell))
|
if(immediate_p(*cell))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
zone *tenured = &data->generations[data->tenured()];
|
zone *tenured = &data->generations[tenured_gen];
|
||||||
*cell += (tenured->start - data_relocation_base);
|
*cell += (tenured->start - data_relocation_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +280,7 @@ void factor_vm::relocate_data()
|
||||||
data_fixup(&bignum_pos_one);
|
data_fixup(&bignum_pos_one);
|
||||||
data_fixup(&bignum_neg_one);
|
data_fixup(&bignum_neg_one);
|
||||||
|
|
||||||
zone *tenured = &data->generations[data->tenured()];
|
zone *tenured = &data->generations[tenured_gen];
|
||||||
|
|
||||||
for(relocating = tenured->start;
|
for(relocating = tenured->start;
|
||||||
relocating < tenured->here;
|
relocating < tenured->here;
|
||||||
|
|
|
@ -83,9 +83,8 @@ void factor_vm::primitive_existsp()
|
||||||
box_boolean(stat(path,&sb) >= 0);
|
box_boolean(stat(path,&sb) >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
segment::segment(factor_vm *myvm_, cell size_)
|
segment::segment(cell size_)
|
||||||
{
|
{
|
||||||
myvm = myvm_;
|
|
||||||
size = size_;
|
size = size_;
|
||||||
|
|
||||||
int pagesize = getpagesize();
|
int pagesize = getpagesize();
|
||||||
|
@ -94,8 +93,7 @@ segment::segment(factor_vm *myvm_, cell size_)
|
||||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||||
MAP_ANON | MAP_PRIVATE,-1,0);
|
MAP_ANON | MAP_PRIVATE,-1,0);
|
||||||
|
|
||||||
if(array == (char*)-1)
|
if(array == (char*)-1) out_of_memory();
|
||||||
myvm->out_of_memory();
|
|
||||||
|
|
||||||
if(mprotect(array,pagesize,PROT_NONE) == -1)
|
if(mprotect(array,pagesize,PROT_NONE) == -1)
|
||||||
fatal_error("Cannot protect low guard page",(cell)array);
|
fatal_error("Cannot protect low guard page",(cell)array);
|
||||||
|
|
|
@ -96,9 +96,8 @@ void factor_vm::primitive_existsp()
|
||||||
box_boolean(windows_stat(path));
|
box_boolean(windows_stat(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
segment::segment(factor_vm *myvm_, cell size_)
|
segment::segment(cell size_)
|
||||||
{
|
{
|
||||||
myvm = myvm_;
|
|
||||||
size = size_;
|
size = size_;
|
||||||
|
|
||||||
char *mem;
|
char *mem;
|
||||||
|
@ -106,7 +105,7 @@ segment::segment(factor_vm *myvm_, cell size_)
|
||||||
|
|
||||||
if((mem = (char *)VirtualAlloc(NULL, getpagesize() * 2 + size,
|
if((mem = (char *)VirtualAlloc(NULL, getpagesize() * 2 + size,
|
||||||
MEM_COMMIT, PAGE_EXECUTE_READWRITE)) == 0)
|
MEM_COMMIT, PAGE_EXECUTE_READWRITE)) == 0)
|
||||||
myvm->out_of_memory();
|
out_of_memory();
|
||||||
|
|
||||||
if (!VirtualProtect(mem, getpagesize(), PAGE_NOACCESS, &ignore))
|
if (!VirtualProtect(mem, getpagesize(), PAGE_NOACCESS, &ignore))
|
||||||
fatal_error("Cannot allocate low guard page", (cell)mem);
|
fatal_error("Cannot allocate low guard page", (cell)mem);
|
||||||
|
|
|
@ -9,12 +9,11 @@ inline cell align_page(cell a)
|
||||||
/* segments set up guard pages to check for under/overflow.
|
/* segments set up guard pages to check for under/overflow.
|
||||||
size must be a multiple of the page size */
|
size must be a multiple of the page size */
|
||||||
struct segment {
|
struct segment {
|
||||||
factor_vm *myvm;
|
|
||||||
cell start;
|
cell start;
|
||||||
cell size;
|
cell size;
|
||||||
cell end;
|
cell end;
|
||||||
|
|
||||||
explicit segment(factor_vm *myvm, cell size);
|
explicit segment(cell size);
|
||||||
~segment();
|
~segment();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
148
vm/vm.hpp
148
vm/vm.hpp
|
@ -4,16 +4,97 @@ namespace factor
|
||||||
struct factor_vm
|
struct factor_vm
|
||||||
{
|
{
|
||||||
// First five fields accessed directly by assembler. See vm.factor
|
// First five fields accessed directly by assembler. See vm.factor
|
||||||
|
|
||||||
|
/* Current stacks */
|
||||||
context *stack_chain;
|
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 cards_offset;
|
||||||
cell decks_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;
|
cell ds_size, rs_size;
|
||||||
|
|
||||||
|
/* Pooling unused contexts to make callbacks cheaper */
|
||||||
context *unused_contexts;
|
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_datastack();
|
||||||
void reset_retainstack();
|
void reset_retainstack();
|
||||||
void fix_stacks();
|
void fix_stacks();
|
||||||
|
@ -32,9 +113,6 @@ struct factor_vm
|
||||||
void primitive_check_datastack();
|
void primitive_check_datastack();
|
||||||
|
|
||||||
// run
|
// run
|
||||||
/* Canonical T object. It's just a word */
|
|
||||||
cell T;
|
|
||||||
|
|
||||||
void primitive_getenv();
|
void primitive_getenv();
|
||||||
void primitive_setenv();
|
void primitive_setenv();
|
||||||
void primitive_exit();
|
void primitive_exit();
|
||||||
|
@ -46,23 +124,12 @@ struct factor_vm
|
||||||
void primitive_clone();
|
void primitive_clone();
|
||||||
|
|
||||||
// profiler
|
// profiler
|
||||||
bool profiling_p;
|
|
||||||
|
|
||||||
void init_profiler();
|
void init_profiler();
|
||||||
code_block *compile_profiling_stub(cell word_);
|
code_block *compile_profiling_stub(cell word_);
|
||||||
void set_profiling(bool profiling);
|
void set_profiling(bool profiling);
|
||||||
void primitive_profiling();
|
void primitive_profiling();
|
||||||
|
|
||||||
// errors
|
// 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 throw_error(cell error, stack_frame *callstack_top);
|
||||||
void not_implemented_error();
|
void not_implemented_error();
|
||||||
bool in_page(cell fault, cell area, cell area_size, int offset);
|
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);
|
bignum *digit_stream_to_bignum(unsigned int n_digits, unsigned int (*producer)(unsigned int, factor_vm *), unsigned int radix, int negative_p);
|
||||||
|
|
||||||
//data_heap
|
//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();
|
void init_card_decks();
|
||||||
data_heap *grow_data_heap(data_heap *data, cell requested_bytes);
|
data_heap *grow_data_heap(data_heap *data, cell requested_bytes);
|
||||||
void clear_cards(cell gen);
|
void clear_cards(cell gen);
|
||||||
|
@ -173,8 +233,6 @@ struct factor_vm
|
||||||
cell object_size(cell tagged);
|
cell object_size(cell tagged);
|
||||||
|
|
||||||
//write barrier
|
//write barrier
|
||||||
cell allot_markers_offset;
|
|
||||||
|
|
||||||
inline card *addr_to_card(cell a)
|
inline card *addr_to_card(cell a)
|
||||||
{
|
{
|
||||||
return (card*)(((cell)(a) >> card_bits) + cards_offset);
|
return (card*)(((cell)(a) >> card_bits) + cards_offset);
|
||||||
|
@ -227,15 +285,6 @@ struct factor_vm
|
||||||
}
|
}
|
||||||
|
|
||||||
// data_gc
|
// 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();
|
void init_data_gc();
|
||||||
template<typename Strategy> object *resolve_forwarding(object *untagged, Strategy &strategy);
|
template<typename Strategy> object *resolve_forwarding(object *untagged, Strategy &strategy);
|
||||||
template<typename Strategy> void trace_handle(cell *handle, Strategy &strategy);
|
template<typename Strategy> void trace_handle(cell *handle, Strategy &strategy);
|
||||||
|
@ -269,7 +318,6 @@ struct factor_vm
|
||||||
void clear_gc_stats();
|
void clear_gc_stats();
|
||||||
void primitive_become();
|
void primitive_become();
|
||||||
void inline_gc(cell *gc_roots_base, cell gc_roots_size);
|
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);
|
object *allot_object(header header, cell size);
|
||||||
void primitive_clear_gc_stats();
|
void primitive_clear_gc_stats();
|
||||||
|
|
||||||
|
@ -301,22 +349,12 @@ struct factor_vm
|
||||||
#endif
|
#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
|
// generic arrays
|
||||||
template<typename Array> Array *allot_array_internal(cell capacity);
|
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> bool reallot_array_in_place_p(Array *array, cell capacity);
|
||||||
template<typename Array> Array *reallot_array(Array *array_, cell capacity);
|
template<typename Array> Array *reallot_array(Array *array_, cell capacity);
|
||||||
|
|
||||||
//debug
|
//debug
|
||||||
bool fep_disabled;
|
|
||||||
bool full_output;
|
|
||||||
|
|
||||||
void print_chars(string* str);
|
void print_chars(string* str);
|
||||||
void print_word(word* word, cell nesting);
|
void print_word(word* word, cell nesting);
|
||||||
void print_factor_string(string* str);
|
void print_factor_string(string* str);
|
||||||
|
@ -389,10 +427,6 @@ struct factor_vm
|
||||||
void primitive_wrapper();
|
void primitive_wrapper();
|
||||||
|
|
||||||
//math
|
//math
|
||||||
cell bignum_zero;
|
|
||||||
cell bignum_pos_one;
|
|
||||||
cell bignum_neg_one;
|
|
||||||
|
|
||||||
void primitive_bignum_to_fixnum();
|
void primitive_bignum_to_fixnum();
|
||||||
void primitive_float_to_fixnum();
|
void primitive_float_to_fixnum();
|
||||||
void primitive_fixnum_divint();
|
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_block *add_code_block(cell type, cell code_, cell labels_, cell owner_, cell relocation_, cell literals_);
|
||||||
|
|
||||||
//code_heap
|
//code_heap
|
||||||
code_heap *code;
|
|
||||||
|
|
||||||
inline void check_code_pointer(cell ptr)
|
inline void check_code_pointer(cell ptr)
|
||||||
{
|
{
|
||||||
#ifdef FACTOR_DEBUG
|
#ifdef FACTOR_DEBUG
|
||||||
|
@ -554,9 +586,6 @@ struct factor_vm
|
||||||
}
|
}
|
||||||
|
|
||||||
//image
|
//image
|
||||||
cell code_relocation_base;
|
|
||||||
cell data_relocation_base;
|
|
||||||
|
|
||||||
void init_objects(image_header *h);
|
void init_objects(image_header *h);
|
||||||
void load_data_heap(FILE *file, image_header *h, vm_parameters *p);
|
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 load_code_heap(FILE *file, image_header *h, vm_parameters *p);
|
||||||
|
@ -646,9 +675,6 @@ struct factor_vm
|
||||||
void primitive_quot_compiled_p();
|
void primitive_quot_compiled_p();
|
||||||
|
|
||||||
//dispatch
|
//dispatch
|
||||||
cell megamorphic_cache_hits;
|
|
||||||
cell megamorphic_cache_misses;
|
|
||||||
|
|
||||||
cell search_lookup_alist(cell table, cell klass);
|
cell search_lookup_alist(cell table, cell klass);
|
||||||
cell search_lookup_hash(cell table, cell klass, cell hashcode);
|
cell search_lookup_hash(cell table, cell klass, cell hashcode);
|
||||||
cell nth_superclass(tuple_layout *layout, fixnum echelon);
|
cell nth_superclass(tuple_layout *layout, fixnum echelon);
|
||||||
|
@ -666,12 +692,6 @@ struct factor_vm
|
||||||
void primitive_dispatch_stats();
|
void primitive_dispatch_stats();
|
||||||
|
|
||||||
//inline cache
|
//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 init_inline_caching(int max_size);
|
||||||
void deallocate_inline_cache(cell return_address);
|
void deallocate_inline_cache(cell return_address);
|
||||||
cell determine_inline_cache_type(array *cache_entries);
|
cell determine_inline_cache_type(array *cache_entries);
|
||||||
|
|
Loading…
Reference in New Issue