151 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
namespace factor
 | 
						|
{
 | 
						|
 | 
						|
template<typename TargetGeneration, typename Policy> struct collector {
 | 
						|
	factor_vm *myvm;
 | 
						|
	data_heap *data;
 | 
						|
	code_heap *code;
 | 
						|
	gc_state *current_gc;
 | 
						|
	generation_statistics *stats;
 | 
						|
	TargetGeneration *target;
 | 
						|
	Policy policy;
 | 
						|
 | 
						|
	explicit collector(factor_vm *myvm_, generation_statistics *stats_, TargetGeneration *target_, Policy policy_) :
 | 
						|
		myvm(myvm_),
 | 
						|
		data(myvm_->data),
 | 
						|
		code(myvm_->code),
 | 
						|
		current_gc(myvm_->current_gc),
 | 
						|
		stats(stats_),
 | 
						|
		target(target_),
 | 
						|
		policy(policy_) {}
 | 
						|
 | 
						|
	object *resolve_forwarding(object *untagged)
 | 
						|
	{
 | 
						|
		myvm->check_data_pointer(untagged);
 | 
						|
 | 
						|
		/* is there another forwarding pointer? */
 | 
						|
		while(untagged->h.forwarding_pointer_p())
 | 
						|
			untagged = untagged->h.forwarding_pointer();
 | 
						|
 | 
						|
		/* we've found the destination */
 | 
						|
		untagged->h.check_header();
 | 
						|
		return untagged;
 | 
						|
	}
 | 
						|
 | 
						|
	void trace_handle(cell *handle)
 | 
						|
	{
 | 
						|
		cell pointer = *handle;
 | 
						|
 | 
						|
		if(immediate_p(pointer)) return;
 | 
						|
 | 
						|
		object *untagged = myvm->untag<object>(pointer);
 | 
						|
		if(!policy.should_copy_p(untagged))
 | 
						|
			return;
 | 
						|
 | 
						|
		object *forwarding = resolve_forwarding(untagged);
 | 
						|
 | 
						|
		if(forwarding == untagged)
 | 
						|
			untagged = promote_object(untagged);
 | 
						|
		else if(policy.should_copy_p(forwarding))
 | 
						|
			untagged = promote_object(forwarding);
 | 
						|
		else
 | 
						|
			untagged = forwarding;
 | 
						|
 | 
						|
		*handle = RETAG(untagged,TAG(pointer));
 | 
						|
	}
 | 
						|
 | 
						|
	void trace_slots(object *ptr)
 | 
						|
	{
 | 
						|
		cell *slot = (cell *)ptr;
 | 
						|
		cell *end = (cell *)((cell)ptr + myvm->binary_payload_start(ptr));
 | 
						|
 | 
						|
		if(slot != end)
 | 
						|
		{
 | 
						|
			slot++;
 | 
						|
			for(; slot < end; slot++) trace_handle(slot);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	object *promote_object(object *untagged)
 | 
						|
	{
 | 
						|
		cell size = myvm->untagged_object_size(untagged);
 | 
						|
		object *newpointer = target->allot(size);
 | 
						|
		/* XXX not exception-safe */
 | 
						|
		if(!newpointer) longjmp(current_gc->gc_unwind,1);
 | 
						|
 | 
						|
		memcpy(newpointer,untagged,size);
 | 
						|
		untagged->h.forward_to(newpointer);
 | 
						|
 | 
						|
		stats->object_count++;
 | 
						|
		stats->bytes_copied += size;
 | 
						|
 | 
						|
		return newpointer;
 | 
						|
	}
 | 
						|
 | 
						|
	void trace_stack_elements(segment *region, cell *top)
 | 
						|
	{
 | 
						|
		for(cell *ptr = (cell *)region->start; ptr <= top; ptr++)
 | 
						|
			trace_handle(ptr);
 | 
						|
	}
 | 
						|
 | 
						|
	void trace_registered_locals()
 | 
						|
	{
 | 
						|
		std::vector<cell>::const_iterator iter = myvm->gc_locals.begin();
 | 
						|
		std::vector<cell>::const_iterator end = myvm->gc_locals.end();
 | 
						|
 | 
						|
		for(; iter < end; iter++)
 | 
						|
			trace_handle((cell *)(*iter));
 | 
						|
	}
 | 
						|
 | 
						|
	void trace_registered_bignums()
 | 
						|
	{
 | 
						|
		std::vector<cell>::const_iterator iter = myvm->gc_bignums.begin();
 | 
						|
		std::vector<cell>::const_iterator end = myvm->gc_bignums.end();
 | 
						|
 | 
						|
		for(; iter < end; iter++)
 | 
						|
		{
 | 
						|
			cell *handle = (cell *)(*iter);
 | 
						|
 | 
						|
			if(*handle)
 | 
						|
			{
 | 
						|
				*handle |= BIGNUM_TYPE;
 | 
						|
				trace_handle(handle);
 | 
						|
				*handle &= ~BIGNUM_TYPE;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* Copy roots over at the start of GC, namely various constants, stacks,
 | 
						|
	the user environment and extra roots registered by local_roots.hpp */
 | 
						|
	void trace_roots()
 | 
						|
	{
 | 
						|
		trace_handle(&myvm->T);
 | 
						|
		trace_handle(&myvm->bignum_zero);
 | 
						|
		trace_handle(&myvm->bignum_pos_one);
 | 
						|
		trace_handle(&myvm->bignum_neg_one);
 | 
						|
 | 
						|
		trace_registered_locals();
 | 
						|
		trace_registered_bignums();
 | 
						|
 | 
						|
		for(int i = 0; i < USER_ENV; i++) trace_handle(&myvm->userenv[i]);
 | 
						|
	}
 | 
						|
 | 
						|
	void trace_contexts()
 | 
						|
	{
 | 
						|
		context *stacks = myvm->stack_chain;
 | 
						|
 | 
						|
		while(stacks)
 | 
						|
		{
 | 
						|
			trace_stack_elements(stacks->datastack_region,(cell *)stacks->datastack);
 | 
						|
			trace_stack_elements(stacks->retainstack_region,(cell *)stacks->retainstack);
 | 
						|
 | 
						|
			trace_handle(&stacks->catchstack_save);
 | 
						|
			trace_handle(&stacks->current_callback_save);
 | 
						|
 | 
						|
			stacks = stacks->next;
 | 
						|
		}
 | 
						|
	}
 | 
						|
};
 | 
						|
 | 
						|
}
 |