vm: data heap compaction work in progress
							parent
							
								
									fd1e992e7d
								
							
						
					
					
						commit
						29a27cfde4
					
				
							
								
								
									
										1
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										1
									
								
								Makefile
								
								
								
								
							| 
						 | 
				
			
			@ -41,6 +41,7 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \
 | 
			
		|||
	vm/callstack.o \
 | 
			
		||||
	vm/code_block.o \
 | 
			
		||||
	vm/code_heap.o \
 | 
			
		||||
	vm/compaction.o \
 | 
			
		||||
	vm/contexts.o \
 | 
			
		||||
	vm/data_heap.o \
 | 
			
		||||
	vm/debug.o \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,15 +2,17 @@ namespace factor
 | 
			
		|||
{
 | 
			
		||||
 | 
			
		||||
template<typename Visitor> struct call_frame_code_block_visitor {
 | 
			
		||||
	factor_vm *parent;
 | 
			
		||||
	Visitor visitor;
 | 
			
		||||
 | 
			
		||||
	explicit call_frame_code_block_visitor(Visitor visitor_) : visitor(visitor_) {}
 | 
			
		||||
	explicit call_frame_code_block_visitor(factor_vm *parent_, Visitor visitor_) :
 | 
			
		||||
		parent(parent_), visitor(visitor_) {}
 | 
			
		||||
 | 
			
		||||
	void operator()(stack_frame *frame)
 | 
			
		||||
	{
 | 
			
		||||
		cell offset = (cell)FRAME_RETURN_ADDRESS(frame,parent) - (cell)frame->xt;
 | 
			
		||||
 | 
			
		||||
		code_block *new_block = visitor.visit_code_block(parent->frame_code(frame));
 | 
			
		||||
		code_block *new_block = visitor(parent->frame_code(frame));
 | 
			
		||||
		frame->xt = new_block->xt();
 | 
			
		||||
 | 
			
		||||
		FRAME_RETURN_ADDRESS(frame,parent) = (void *)((cell)frame->xt + offset);
 | 
			
		||||
| 
						 | 
				
			
			@ -25,24 +27,24 @@ template<typename Visitor> void factor_vm::visit_object_code_block(object *obj,
 | 
			
		|||
		{
 | 
			
		||||
			word *w = (word *)obj;
 | 
			
		||||
			if(w->code)
 | 
			
		||||
				w->code = visitor.visit_code_block(w->code);
 | 
			
		||||
				w->code = visitor(w->code);
 | 
			
		||||
			if(w->profiling)
 | 
			
		||||
				w->code = visitor.visit_code_block(w->profiling);
 | 
			
		||||
				w->code = visitor(w->profiling);
 | 
			
		||||
 | 
			
		||||
			update_word_xt(obj);
 | 
			
		||||
			update_word_xt(w);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	case QUOTATION_TYPE:
 | 
			
		||||
		{
 | 
			
		||||
			quotation *q = (quotation *)obj;
 | 
			
		||||
			if(q->code)
 | 
			
		||||
				set_quot_xt(visitor.visit_code_block(q->code));
 | 
			
		||||
				set_quot_xt(q,visitor(q->code));
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	case CALLSTACK_TYPE:
 | 
			
		||||
		{
 | 
			
		||||
			callstack *stack = (callstack *)obj;
 | 
			
		||||
			call_frame_code_block_visitor<Visitor> call_frame_visitor(visitor);
 | 
			
		||||
			call_frame_code_block_visitor<Visitor> call_frame_visitor(this,visitor);
 | 
			
		||||
			iterate_callstack_object(stack,call_frame_visitor);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -51,8 +53,7 @@ template<typename Visitor> void factor_vm::visit_object_code_block(object *obj,
 | 
			
		|||
 | 
			
		||||
template<typename Visitor> void factor_vm::visit_context_code_blocks(Visitor visitor)
 | 
			
		||||
{
 | 
			
		||||
	callstack *stack = (callstack *)obj;
 | 
			
		||||
	call_frame_code_block_visitor<Visitor> call_frame_visitor(visitor);
 | 
			
		||||
	call_frame_code_block_visitor<Visitor> call_frame_visitor(this,visitor);
 | 
			
		||||
	iterate_active_frames(call_frame_visitor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -65,14 +66,14 @@ template<typename Visitor> struct callback_code_block_visitor {
 | 
			
		|||
 | 
			
		||||
	void operator()(callback *stub)
 | 
			
		||||
	{
 | 
			
		||||
		stub->compiled = visitor.visit_code_block(stub->compiled);
 | 
			
		||||
		stub->compiled = visitor(stub->compiled);
 | 
			
		||||
		callbacks->update(stub);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename Visitor> void factor_vm::visit_callback_code_blocks(Visitor visitor)
 | 
			
		||||
{
 | 
			
		||||
	callback_code_block_visitor callback_visitor(callbacks,visitor);
 | 
			
		||||
	callback_code_block_visitor<Visitor> callback_visitor(callbacks,visitor);
 | 
			
		||||
	callbacks->iterate(callback_visitor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -205,67 +205,6 @@ void factor_vm::primitive_code_room()
 | 
			
		|||
	dpush(tag_fixnum(max_free / 1024));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct code_block_forwarder {
 | 
			
		||||
	mark_bits<heap_block> *forwarding_map;
 | 
			
		||||
 | 
			
		||||
	explicit code_block_forwarder(mark_bits<heap_block> *forwarding_map_) :
 | 
			
		||||
		forwarding_map(forwarding_map_) {}
 | 
			
		||||
 | 
			
		||||
	code_block *operator()(code_block *compiled)
 | 
			
		||||
	{
 | 
			
		||||
		return (code_block *)forwarding_map->forward_block(compiled);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void factor_vm::forward_object_xts()
 | 
			
		||||
{
 | 
			
		||||
	code_block_forwarder forwarder(&code->allocator->state);
 | 
			
		||||
 | 
			
		||||
	begin_scan();
 | 
			
		||||
 | 
			
		||||
	cell obj;
 | 
			
		||||
 | 
			
		||||
	while(to_boolean(obj = next_object()))
 | 
			
		||||
		visit_object_code_block(untag<object>(obj),forwarder);
 | 
			
		||||
 | 
			
		||||
	end_scan();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::forward_context_xts()
 | 
			
		||||
{
 | 
			
		||||
	code_block_forwarder forwarder(&code->allocator->state);
 | 
			
		||||
	visit_context_code_blocks(forwarder);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::forward_callback_xts()
 | 
			
		||||
{
 | 
			
		||||
	code_block_forwarder forwarder(&code->allocator->state);
 | 
			
		||||
	visit_callback_code_blocks(forwarder);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Move all free space to the end of the code heap. Live blocks must be marked
 | 
			
		||||
on entry to this function. XTs in code blocks must be updated after this
 | 
			
		||||
function returns. */
 | 
			
		||||
void factor_vm::compact_code_heap(bool trace_contexts_p)
 | 
			
		||||
{
 | 
			
		||||
	/* Figure out where blocks are going to go */
 | 
			
		||||
	code->allocator->state.compute_forwarding();
 | 
			
		||||
 | 
			
		||||
	/* Update references to the code heap from the data heap */
 | 
			
		||||
	forward_object_xts();
 | 
			
		||||
	if(trace_contexts_p)
 | 
			
		||||
	{
 | 
			
		||||
		forward_context_xts();
 | 
			
		||||
		forward_callback_xts();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Move code blocks and update references amongst them (this requires
 | 
			
		||||
	that the data heap is up to date since relocation looks up object XTs) */
 | 
			
		||||
	code_heap_relocator relocator(this);
 | 
			
		||||
	code_heap_iterator<code_heap_relocator> iter(relocator);
 | 
			
		||||
	code->allocator->compact(iter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct stack_trace_stripper {
 | 
			
		||||
	explicit stack_trace_stripper() {}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,7 +44,7 @@ template<typename TargetGeneration, typename Policy> struct collector_workhorse
 | 
			
		|||
		return newpointer;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	object *visit_handle(object *obj)
 | 
			
		||||
	object *visit_object(object *obj)
 | 
			
		||||
	{
 | 
			
		||||
		if(!policy.should_copy_p(obj))
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,96 @@
 | 
			
		|||
#include "master.hpp"
 | 
			
		||||
 | 
			
		||||
namespace factor {
 | 
			
		||||
 | 
			
		||||
struct object_slot_forwarder {
 | 
			
		||||
	mark_bits<object> *forwarding_map;
 | 
			
		||||
 | 
			
		||||
	explicit object_slot_forwarder(mark_bits<object> *forwarding_map_) :
 | 
			
		||||
		forwarding_map(forwarding_map_) {}
 | 
			
		||||
 | 
			
		||||
	object *visit_object(object *obj)
 | 
			
		||||
	{
 | 
			
		||||
		return forwarding_map->forward_block(obj);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct code_block_forwarder {
 | 
			
		||||
	mark_bits<heap_block> *forwarding_map;
 | 
			
		||||
 | 
			
		||||
	explicit code_block_forwarder(mark_bits<heap_block> *forwarding_map_) :
 | 
			
		||||
		forwarding_map(forwarding_map_) {}
 | 
			
		||||
 | 
			
		||||
	code_block *operator()(code_block *compiled)
 | 
			
		||||
	{
 | 
			
		||||
		return (code_block *)forwarding_map->forward_block(compiled);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct object_compaction_updater {
 | 
			
		||||
	factor_vm *parent;
 | 
			
		||||
	slot_visitor<object_slot_forwarder> slot_forwarder;
 | 
			
		||||
	code_block_forwarder code_forwarder;
 | 
			
		||||
 | 
			
		||||
	explicit object_compaction_updater(factor_vm *parent_,
 | 
			
		||||
		slot_visitor<object_slot_forwarder> slot_forwader_,
 | 
			
		||||
		code_block_forwarder code_forwarder_) :
 | 
			
		||||
		parent(parent_),
 | 
			
		||||
		slot_forwarder(slot_forwader_),
 | 
			
		||||
		code_forwarder(code_forwarder_) {}
 | 
			
		||||
 | 
			
		||||
	void operator()(object *obj, cell size)
 | 
			
		||||
	{
 | 
			
		||||
		slot_forwarder.visit_slots(obj);
 | 
			
		||||
		parent->visit_object_code_block(obj,code_forwarder);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct code_block_compaction_updater {
 | 
			
		||||
	factor_vm *parent;
 | 
			
		||||
	slot_visitor<object_slot_forwarder> slot_forwarder;
 | 
			
		||||
 | 
			
		||||
	explicit code_block_compaction_updater(factor_vm *parent_, slot_visitor<object_slot_forwarder> slot_forwader_) :
 | 
			
		||||
		parent(parent_), slot_forwarder(slot_forwader_) {}
 | 
			
		||||
 | 
			
		||||
	void operator()(code_block *compiled, cell size)
 | 
			
		||||
	{
 | 
			
		||||
		slot_forwarder.visit_literal_references(compiled);
 | 
			
		||||
		parent->relocate_code_block(compiled);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void factor_vm::compact_full_impl(bool trace_contexts_p)
 | 
			
		||||
{
 | 
			
		||||
	tenured_space *tenured = data->tenured;
 | 
			
		||||
	mark_bits<object> *data_forwarding_map = &tenured->state;
 | 
			
		||||
	mark_bits<heap_block> *code_forwarding_map = &code->allocator->state;
 | 
			
		||||
 | 
			
		||||
	/* Figure out where blocks are going to go */
 | 
			
		||||
	data_forwarding_map->compute_forwarding();
 | 
			
		||||
	code_forwarding_map->compute_forwarding();
 | 
			
		||||
 | 
			
		||||
	/* Update root pointers */
 | 
			
		||||
	slot_visitor<object_slot_forwarder> slot_forwarder(this,object_slot_forwarder(data_forwarding_map));
 | 
			
		||||
	code_block_forwarder code_forwarder(code_forwarding_map);
 | 
			
		||||
 | 
			
		||||
	slot_forwarder.visit_roots();
 | 
			
		||||
	if(trace_contexts_p)
 | 
			
		||||
	{
 | 
			
		||||
		slot_forwarder.visit_contexts();
 | 
			
		||||
		visit_context_code_blocks(code_forwarder);
 | 
			
		||||
		visit_callback_code_blocks(code_forwarder);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Slide everything in tenured space up, and update data and code heap
 | 
			
		||||
	pointers inside objects. */
 | 
			
		||||
	object_compaction_updater object_updater(this,slot_forwarder,code_forwarder);
 | 
			
		||||
	tenured->compact(object_updater);
 | 
			
		||||
 | 
			
		||||
	/* Slide everything in the code heap up, and update data and code heap
 | 
			
		||||
	pointers inside code blocks. */
 | 
			
		||||
	code_block_compaction_updater code_block_updater(this,slot_forwarder);
 | 
			
		||||
	code_heap_iterator<code_block_compaction_updater> iter(code_block_updater);
 | 
			
		||||
	code->allocator->compact(iter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
namespace factor
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +85,7 @@ void factor_vm::collect_full_impl(bool trace_contexts_p)
 | 
			
		|||
 | 
			
		||||
void factor_vm::collect_growing_heap(cell requested_bytes,
 | 
			
		||||
	bool trace_contexts_p,
 | 
			
		||||
	bool compact_code_heap_p)
 | 
			
		||||
	bool compact_p)
 | 
			
		||||
{
 | 
			
		||||
	/* Grow the data heap and copy all live objects to the new heap. */
 | 
			
		||||
	data_heap *old = data;
 | 
			
		||||
| 
						 | 
				
			
			@ -93,18 +93,18 @@ void factor_vm::collect_growing_heap(cell requested_bytes,
 | 
			
		|||
	collect_full_impl(trace_contexts_p);
 | 
			
		||||
	delete old;
 | 
			
		||||
 | 
			
		||||
	if(compact_code_heap_p)
 | 
			
		||||
		compact_code_heap(trace_contexts_p);
 | 
			
		||||
	if(compact_p)
 | 
			
		||||
		compact_full_impl(trace_contexts_p);
 | 
			
		||||
	else
 | 
			
		||||
		relocate_code_heap();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::collect_full(bool trace_contexts_p, bool compact_code_heap_p)
 | 
			
		||||
void factor_vm::collect_full(bool trace_contexts_p, bool compact_p)
 | 
			
		||||
{
 | 
			
		||||
	collect_full_impl(trace_contexts_p);
 | 
			
		||||
 | 
			
		||||
	if(compact_code_heap_p)
 | 
			
		||||
		compact_code_heap(trace_contexts_p);
 | 
			
		||||
	if(compact_p)
 | 
			
		||||
		compact_full_impl(trace_contexts_p);
 | 
			
		||||
	else
 | 
			
		||||
		update_code_heap_words_and_literals();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ void factor_vm::record_gc_stats(generation_statistics *stats)
 | 
			
		|||
void factor_vm::gc(gc_op op,
 | 
			
		||||
	cell requested_bytes,
 | 
			
		||||
	bool trace_contexts_p,
 | 
			
		||||
	bool compact_code_heap_p)
 | 
			
		||||
	bool compact_p)
 | 
			
		||||
{
 | 
			
		||||
	assert(!gc_off);
 | 
			
		||||
	assert(!current_gc);
 | 
			
		||||
| 
						 | 
				
			
			@ -83,11 +83,11 @@ void factor_vm::gc(gc_op op,
 | 
			
		|||
		record_gc_stats(&gc_stats.aging_stats);
 | 
			
		||||
		break;
 | 
			
		||||
	case collect_full_op:
 | 
			
		||||
		collect_full(trace_contexts_p,compact_code_heap_p);
 | 
			
		||||
		collect_full(trace_contexts_p,compact_p);
 | 
			
		||||
		record_gc_stats(&gc_stats.full_stats);
 | 
			
		||||
		break;
 | 
			
		||||
	case collect_growing_heap_op:
 | 
			
		||||
		collect_growing_heap(requested_bytes,trace_contexts_p,compact_code_heap_p);
 | 
			
		||||
		collect_growing_heap(requested_bytes,trace_contexts_p,compact_p);
 | 
			
		||||
		record_gc_stats(&gc_stats.full_stats);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -79,6 +79,7 @@ namespace factor
 | 
			
		|||
#include "aging_collector.hpp"
 | 
			
		||||
#include "to_tenured_collector.hpp"
 | 
			
		||||
#include "code_block_visitor.hpp"
 | 
			
		||||
#include "compaction.hpp"
 | 
			
		||||
#include "full_collector.hpp"
 | 
			
		||||
#include "callstack.hpp"
 | 
			
		||||
#include "generic_arrays.hpp"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ template<typename Visitor> struct slot_visitor {
 | 
			
		|||
		if(immediate_p(pointer)) return;
 | 
			
		||||
 | 
			
		||||
		object *untagged = untag<object>(pointer);
 | 
			
		||||
		untagged = visitor.visit_handle(untagged);
 | 
			
		||||
		untagged = visitor.visit_object(untagged);
 | 
			
		||||
		*handle = RETAG(untagged,TAG(pointer));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +56,7 @@ template<typename Visitor> struct slot_visitor {
 | 
			
		|||
			cell *handle = (cell *)(*iter);
 | 
			
		||||
 | 
			
		||||
			if(*handle)
 | 
			
		||||
				*handle = (cell)visitor.visit_handle(*(object **)handle);
 | 
			
		||||
				*handle = (cell)visitor.visit_object(*(object **)handle);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										11
									
								
								vm/vm.hpp
								
								
								
								
							
							
						
						
									
										11
									
								
								vm/vm.hpp
								
								
								
								
							| 
						 | 
				
			
			@ -249,10 +249,11 @@ struct factor_vm
 | 
			
		|||
	void collect_aging();
 | 
			
		||||
	void collect_to_tenured();
 | 
			
		||||
	void collect_full_impl(bool trace_contexts_p);
 | 
			
		||||
	void collect_growing_heap(cell requested_bytes, bool trace_contexts_p, bool compact_code_heap_p);
 | 
			
		||||
	void collect_full(bool trace_contexts_p, bool compact_code_heap_p);
 | 
			
		||||
	void compact_full_impl(bool trace_contexts_p);
 | 
			
		||||
	void collect_growing_heap(cell requested_bytes, bool trace_contexts_p, bool compact_p);
 | 
			
		||||
	void collect_full(bool trace_contexts_p, bool compact_p);
 | 
			
		||||
	void record_gc_stats(generation_statistics *stats);
 | 
			
		||||
	void gc(gc_op op, cell requested_bytes, bool trace_contexts_p, bool compact_code_heap_p);
 | 
			
		||||
	void gc(gc_op op, cell requested_bytes, bool trace_contexts_p, bool compact_p);
 | 
			
		||||
	void primitive_minor_gc();
 | 
			
		||||
	void primitive_full_gc();
 | 
			
		||||
	void primitive_compact_gc();
 | 
			
		||||
| 
						 | 
				
			
			@ -506,10 +507,6 @@ struct factor_vm
 | 
			
		|||
	void relocate_code_heap();
 | 
			
		||||
	void primitive_modify_code_heap();
 | 
			
		||||
	void primitive_code_room();
 | 
			
		||||
	void forward_object_xts();
 | 
			
		||||
	void forward_context_xts();
 | 
			
		||||
	void forward_callback_xts();
 | 
			
		||||
	void compact_code_heap(bool trace_contexts_p);
 | 
			
		||||
	void primitive_strip_stack_traces();
 | 
			
		||||
 | 
			
		||||
	/* Apply a function to every code block */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue