vm: more code cleanups
							parent
							
								
									1f76a64e91
								
							
						
					
					
						commit
						5c774d8c84
					
				| 
						 | 
				
			
			@ -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();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 ©ing_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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,7 @@ struct zone {
 | 
			
		|||
	cell here;
 | 
			
		||||
	cell size;
 | 
			
		||||
	cell end;
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	cell init_zone(cell size_, cell start_)
 | 
			
		||||
	{
 | 
			
		||||
		size = size_;
 | 
			
		||||
| 
						 | 
				
			
			@ -17,11 +17,18 @@ struct zone {
 | 
			
		|||
		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 {
 | 
			
		||||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
								
								
								
								
							
							
						
						
									
										148
									
								
								vm/vm.hpp
								
								
								
								
							| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue