| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | namespace factor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | /* Size of the object pointed to by an untagged pointer */ | 
					
						
							|  |  |  | template<typename Fixup> | 
					
						
							|  |  |  | cell object::size(Fixup fixup) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(free_p()) return ((free_heap_block *)this)->size(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch(type()) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	case ARRAY_TYPE: | 
					
						
							|  |  |  | 		return align(array_size((array*)this),data_alignment); | 
					
						
							|  |  |  | 	case BIGNUM_TYPE: | 
					
						
							|  |  |  | 		return align(array_size((bignum*)this),data_alignment); | 
					
						
							|  |  |  | 	case BYTE_ARRAY_TYPE: | 
					
						
							|  |  |  | 		return align(array_size((byte_array*)this),data_alignment); | 
					
						
							|  |  |  | 	case STRING_TYPE: | 
					
						
							|  |  |  | 		return align(string_size(string_capacity((string*)this)),data_alignment); | 
					
						
							|  |  |  | 	case TUPLE_TYPE: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			tuple_layout *layout = (tuple_layout *)fixup.translate_data(untag<object>(((tuple *)this)->layout)); | 
					
						
							|  |  |  | 			return align(tuple_size(layout),data_alignment); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case QUOTATION_TYPE: | 
					
						
							|  |  |  | 		return align(sizeof(quotation),data_alignment); | 
					
						
							|  |  |  | 	case WORD_TYPE: | 
					
						
							|  |  |  | 		return align(sizeof(word),data_alignment); | 
					
						
							|  |  |  | 	case FLOAT_TYPE: | 
					
						
							|  |  |  | 		return align(sizeof(boxed_float),data_alignment); | 
					
						
							|  |  |  | 	case DLL_TYPE: | 
					
						
							|  |  |  | 		return align(sizeof(dll),data_alignment); | 
					
						
							|  |  |  | 	case ALIEN_TYPE: | 
					
						
							|  |  |  | 		return align(sizeof(alien),data_alignment); | 
					
						
							|  |  |  | 	case WRAPPER_TYPE: | 
					
						
							|  |  |  | 		return align(sizeof(wrapper),data_alignment); | 
					
						
							|  |  |  | 	case CALLSTACK_TYPE: | 
					
						
							|  |  |  | 		return align(callstack_object_size(untag_fixnum(((callstack *)this)->length)),data_alignment); | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		critical_error("Invalid header in size",(cell)this); | 
					
						
							|  |  |  | 		return 0; /* can't happen */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | inline cell object::size() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return size(no_fixup()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The number of cells from the start of the object which should be scanned by
 | 
					
						
							|  |  |  | the GC. Some types have a binary payload at the end (string, word, DLL) which | 
					
						
							|  |  |  | we ignore. */ | 
					
						
							|  |  |  | template<typename Fixup> | 
					
						
							|  |  |  | cell object::binary_payload_start(Fixup fixup) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(free_p()) return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch(type()) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	/* these objects do not refer to other objects at all */ | 
					
						
							|  |  |  | 	case FLOAT_TYPE: | 
					
						
							|  |  |  | 	case BYTE_ARRAY_TYPE: | 
					
						
							|  |  |  | 	case BIGNUM_TYPE: | 
					
						
							|  |  |  | 	case CALLSTACK_TYPE: | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	/* these objects have some binary data at the end */ | 
					
						
							|  |  |  | 	case WORD_TYPE: | 
					
						
							| 
									
										
										
										
											2011-11-10 19:00:47 -05:00
										 |  |  | 		return sizeof(word) - sizeof(cell); | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	case ALIEN_TYPE: | 
					
						
							|  |  |  | 		return sizeof(cell) * 3; | 
					
						
							|  |  |  | 	case DLL_TYPE: | 
					
						
							|  |  |  | 		return sizeof(cell) * 2; | 
					
						
							|  |  |  | 	case QUOTATION_TYPE: | 
					
						
							| 
									
										
										
										
											2011-11-10 19:00:47 -05:00
										 |  |  | 		return sizeof(quotation) - sizeof(cell); | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	case STRING_TYPE: | 
					
						
							|  |  |  | 		return sizeof(string); | 
					
						
							|  |  |  | 	/* everything else consists entirely of pointers */ | 
					
						
							|  |  |  | 	case ARRAY_TYPE: | 
					
						
							|  |  |  | 		return array_size<array>(array_capacity((array*)this)); | 
					
						
							|  |  |  | 	case TUPLE_TYPE: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			tuple_layout *layout = (tuple_layout *)fixup.translate_data(untag<object>(((tuple *)this)->layout)); | 
					
						
							|  |  |  | 			return tuple_size(layout); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case WRAPPER_TYPE: | 
					
						
							|  |  |  | 		return sizeof(wrapper); | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		critical_error("Invalid header in binary_payload_start",(cell)this); | 
					
						
							|  |  |  | 		return 0; /* can't happen */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | inline cell object::binary_payload_start() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return binary_payload_start(no_fixup()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | /* Slot visitors iterate over the slots of an object, applying a functor to
 | 
					
						
							|  |  |  | each one that is a non-immediate slot. The pointer is untagged first. The | 
					
						
							|  |  |  | functor returns a new untagged object pointer. The return value may or may not equal the old one, | 
					
						
							|  |  |  | however the new pointer receives the same tag before being stored back to the | 
					
						
							|  |  |  | original location. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Slots storing immediate values are left unchanged and the visitor does inspect | 
					
						
							|  |  |  | them. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This is used by GC's copying, sweep and compact phases, and the implementation | 
					
						
							|  |  |  | of the become primitive. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Iteration is driven by visit_*() methods. Some of them define GC roots: | 
					
						
							|  |  |  | - visit_roots() | 
					
						
							|  |  |  | - visit_contexts() */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> struct slot_visitor { | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 	factor_vm *parent; | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	Fixup fixup; | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	explicit slot_visitor<Fixup>(factor_vm *parent_, Fixup fixup_) : | 
					
						
							|  |  |  | 		parent(parent_), fixup(fixup_) {} | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | 	cell visit_pointer(cell pointer); | 
					
						
							|  |  |  | 	void visit_handle(cell *handle); | 
					
						
							| 
									
										
										
										
											2010-03-18 05:06:00 -04:00
										 |  |  | 	void visit_object_array(cell *start, cell *end); | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | 	void visit_slots(object *ptr, cell payload_start); | 
					
						
							|  |  |  | 	void visit_slots(object *ptr); | 
					
						
							|  |  |  | 	void visit_stack_elements(segment *region, cell *top); | 
					
						
							|  |  |  | 	void visit_data_roots(); | 
					
						
							|  |  |  | 	void visit_bignum_roots(); | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 	void visit_callback_roots(); | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 	void visit_literal_table_roots(); | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | 	void visit_roots(); | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	void visit_callstack_object(callstack *stack); | 
					
						
							|  |  |  | 	void visit_callstack(context *ctx); | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | 	void visit_contexts(); | 
					
						
							| 
									
										
										
										
											2009-11-24 20:29:59 -05:00
										 |  |  | 	void visit_code_block_objects(code_block *compiled); | 
					
						
							|  |  |  | 	void visit_embedded_literals(code_block *compiled); | 
					
						
							| 
									
										
										
										
											2011-11-01 21:53:37 -04:00
										 |  |  | 	void visit_sample_callstacks(); | 
					
						
							| 
									
										
										
										
											2011-11-01 22:39:54 -04:00
										 |  |  | 	void visit_sample_threads(); | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2009-11-06 02:22:53 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | cell slot_visitor<Fixup>::visit_pointer(cell pointer) | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	if(immediate_p(pointer)) return pointer; | 
					
						
							| 
									
										
										
										
											2009-11-07 17:16:09 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	object *untagged = fixup.fixup_data(untag<object>(pointer)); | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | 	return RETAG(untagged,TAG(pointer)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void slot_visitor<Fixup>::visit_handle(cell *handle) | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	*handle = visit_pointer(*handle); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void slot_visitor<Fixup>::visit_object_array(cell *start, cell *end) | 
					
						
							| 
									
										
										
										
											2010-03-18 05:06:00 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	while(start < end) visit_handle(start++); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void slot_visitor<Fixup>::visit_slots(object *ptr, cell payload_start) | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	cell *slot = (cell *)ptr; | 
					
						
							|  |  |  | 	cell *end = (cell *)((cell)ptr + payload_start); | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | 	if(slot != end) | 
					
						
							| 
									
										
										
										
											2009-10-25 00:51:14 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | 		slot++; | 
					
						
							| 
									
										
										
										
											2010-03-18 05:06:00 -04:00
										 |  |  | 		visit_object_array(slot,end); | 
					
						
							| 
									
										
										
										
											2009-10-25 00:51:14 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-10-25 00:51:14 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void slot_visitor<Fixup>::visit_slots(object *obj) | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	if(obj->type() == CALLSTACK_TYPE) | 
					
						
							|  |  |  | 		visit_callstack_object((callstack *)obj); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		visit_slots(obj,obj->binary_payload_start(fixup)); | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void slot_visitor<Fixup>::visit_stack_elements(segment *region, cell *top) | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-18 05:06:00 -04:00
										 |  |  | 	visit_object_array((cell *)region->start,top + 1); | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void slot_visitor<Fixup>::visit_data_roots() | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	std::vector<data_root_range>::const_iterator iter = parent->data_roots.begin(); | 
					
						
							|  |  |  | 	std::vector<data_root_range>::const_iterator end = parent->data_roots.end(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(; iter < end; iter++) | 
					
						
							| 
									
										
										
										
											2010-03-18 05:06:00 -04:00
										 |  |  | 		visit_object_array(iter->start,iter->start + iter->len); | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void slot_visitor<Fixup>::visit_bignum_roots() | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	std::vector<cell>::const_iterator iter = parent->bignum_roots.begin(); | 
					
						
							|  |  |  | 	std::vector<cell>::const_iterator end = parent->bignum_roots.end(); | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | 	for(; iter < end; iter++) | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | 		cell *handle = (cell *)(*iter); | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | 		if(*handle) | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 			*handle = (cell)fixup.fixup_data(*(object **)handle); | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | struct callback_slot_visitor { | 
					
						
							|  |  |  | 	callback_heap *callbacks; | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	slot_visitor<Fixup> *visitor; | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	explicit callback_slot_visitor(callback_heap *callbacks_, slot_visitor<Fixup> *visitor_) : | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 		callbacks(callbacks_), visitor(visitor_) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void operator()(code_block *stub) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		visitor->visit_handle(&stub->owner); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void slot_visitor<Fixup>::visit_callback_roots() | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	callback_slot_visitor<Fixup> callback_visitor(parent->callbacks,this); | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 	parent->callbacks->each_callback(callback_visitor); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void slot_visitor<Fixup>::visit_literal_table_roots() | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	std::map<code_block *, cell> *uninitialized_blocks = &parent->code->uninitialized_blocks; | 
					
						
							|  |  |  | 	std::map<code_block *, cell>::const_iterator iter = uninitialized_blocks->begin(); | 
					
						
							|  |  |  | 	std::map<code_block *, cell>::const_iterator end = uninitialized_blocks->end(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	std::map<code_block *, cell> new_uninitialized_blocks; | 
					
						
							|  |  |  | 	for(; iter != end; iter++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		new_uninitialized_blocks.insert(std::make_pair( | 
					
						
							|  |  |  | 			iter->first, | 
					
						
							|  |  |  | 			visit_pointer(iter->second))); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	parent->code->uninitialized_blocks = new_uninitialized_blocks; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-01 21:53:37 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void slot_visitor<Fixup>::visit_sample_callstacks() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	for (std::vector<cell>::iterator iter = parent->sample_callstacks.begin(); | 
					
						
							|  |  |  | 		iter != parent->sample_callstacks.end(); | 
					
						
							|  |  |  | 		++iter) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		visit_handle(&*iter); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-01 22:39:54 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void slot_visitor<Fixup>::visit_sample_threads() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	for (std::vector<profiling_sample>::iterator iter = parent->samples.begin(); | 
					
						
							|  |  |  | 		iter != parent->samples.end(); | 
					
						
							|  |  |  | 		++iter) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		visit_handle(&iter->thread); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void slot_visitor<Fixup>::visit_roots() | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	visit_handle(&parent->true_object); | 
					
						
							|  |  |  | 	visit_handle(&parent->bignum_zero); | 
					
						
							|  |  |  | 	visit_handle(&parent->bignum_pos_one); | 
					
						
							|  |  |  | 	visit_handle(&parent->bignum_neg_one); | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | 	visit_data_roots(); | 
					
						
							|  |  |  | 	visit_bignum_roots(); | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 	visit_callback_roots(); | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 	visit_literal_table_roots(); | 
					
						
							| 
									
										
										
										
											2011-11-01 21:53:37 -04:00
										 |  |  | 	visit_sample_callstacks(); | 
					
						
							| 
									
										
										
										
											2011-11-01 22:39:54 -04:00
										 |  |  | 	visit_sample_threads(); | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-18 05:06:00 -04:00
										 |  |  | 	visit_object_array(parent->special_objects,parent->special_objects + special_object_count); | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | struct call_frame_slot_visitor { | 
					
						
							|  |  |  | 	factor_vm *parent; | 
					
						
							|  |  |  | 	slot_visitor<Fixup> *visitor; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	explicit call_frame_slot_visitor(factor_vm *parent_, slot_visitor<Fixup> *visitor_) : | 
					
						
							|  |  |  | 		parent(parent_), visitor(visitor_) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							| 
									
										
										
										
											2011-12-05 15:53:34 -05:00
										 |  |  | 	frame top -> [return address] | 
					
						
							|  |  |  | 	             [spill area] | 
					
						
							|  |  |  | 	             ... | 
					
						
							|  |  |  | 	             [entry_point] | 
					
						
							|  |  |  | 	             [size] | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	*/ | 
					
						
							| 
									
										
										
										
											2011-12-06 12:14:56 -05:00
										 |  |  | 	void operator()(void *frame_top, cell frame_size, code_block *owner, void *addr) | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2011-12-05 15:53:34 -05:00
										 |  |  | 		cell return_address = owner->offset(addr); | 
					
						
							| 
									
										
										
										
											2010-06-13 17:57:16 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-06 12:14:56 -05:00
										 |  |  | 		code_block *compiled = Fixup::translated_code_block_map | 
					
						
							|  |  |  | 			? owner | 
					
						
							|  |  |  | 			: visitor->fixup.translate_code(owner); | 
					
						
							|  |  |  | 		gc_info *info = compiled->block_gc_info(); | 
					
						
							| 
									
										
										
										
											2010-06-13 17:57:16 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-06 12:14:56 -05:00
										 |  |  | 		FACTOR_ASSERT(return_address < compiled->size()); | 
					
						
							| 
									
										
										
										
											2010-10-09 17:03:46 -04:00
										 |  |  | 		cell callsite = info->return_address_index(return_address); | 
					
						
							| 
									
										
										
										
											2010-10-09 18:14:14 -04:00
										 |  |  | 		if(callsite == (cell)-1) | 
					
						
							| 
									
										
										
										
											2010-06-13 17:57:16 -04:00
										 |  |  | 			return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-13 17:36:08 -04:00
										 |  |  | #ifdef DEBUG_GC_MAPS
 | 
					
						
							| 
									
										
										
										
											2011-12-06 12:14:56 -05:00
										 |  |  | 		std::cout << "call frame code block " << compiled << " with offset " << return_address << std::endl; | 
					
						
							| 
									
										
										
										
											2010-06-13 17:36:08 -04:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-12-05 15:53:34 -05:00
										 |  |  | 		cell *stack_pointer = (cell *)frame_top; | 
					
						
							| 
									
										
										
										
											2010-09-27 01:20:50 -04:00
										 |  |  | 		u8 *bitmap = info->gc_info_bitmap(); | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-27 01:20:50 -04:00
										 |  |  | 		/* Subtract old value of base pointer from every derived pointer. */ | 
					
						
							|  |  |  | 		for(cell spill_slot = 0; spill_slot < info->derived_root_count; spill_slot++) | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2010-10-09 18:14:14 -04:00
										 |  |  | 			u32 base_pointer = info->lookup_base_pointer(callsite, spill_slot); | 
					
						
							|  |  |  | 			if(base_pointer != (u32)-1) | 
					
						
							| 
									
										
										
										
											2010-06-13 17:36:08 -04:00
										 |  |  | 			{ | 
					
						
							|  |  |  | #ifdef DEBUG_GC_MAPS
 | 
					
						
							| 
									
										
										
										
											2010-09-27 01:20:50 -04:00
										 |  |  | 				std::cout << "visiting derived root " << spill_slot | 
					
						
							|  |  |  | 					<< " with base pointer " << base_pointer | 
					
						
							|  |  |  | 					<< std::endl; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 				stack_pointer[spill_slot] -= stack_pointer[base_pointer]; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Update all GC roots, including base pointers. */ | 
					
						
							|  |  |  | 		cell callsite_gc_roots = info->callsite_gc_roots(callsite); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for(cell spill_slot = 0; spill_slot < info->gc_root_count; spill_slot++) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if(bitmap_p(bitmap,callsite_gc_roots + spill_slot)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | #ifdef DEBUG_GC_MAPS
 | 
					
						
							|  |  |  | 				std::cout << "visiting GC root " << spill_slot << std::endl; | 
					
						
							| 
									
										
										
										
											2010-06-13 17:36:08 -04:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-06-17 02:04:03 -04:00
										 |  |  | 				visitor->visit_handle(stack_pointer + spill_slot); | 
					
						
							| 
									
										
										
										
											2010-06-13 17:36:08 -04:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-09-27 01:20:50 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* Add the base pointers to obtain new derived pointer values. */ | 
					
						
							|  |  |  | 		for(cell spill_slot = 0; spill_slot < info->derived_root_count; spill_slot++) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2010-10-09 18:14:14 -04:00
										 |  |  | 			u32 base_pointer = info->lookup_base_pointer(callsite, spill_slot); | 
					
						
							|  |  |  | 			if(base_pointer != (u32)-1) | 
					
						
							| 
									
										
										
										
											2010-09-27 01:20:50 -04:00
										 |  |  | 				stack_pointer[spill_slot] += stack_pointer[base_pointer]; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void slot_visitor<Fixup>::visit_callstack_object(callstack *stack) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	call_frame_slot_visitor<Fixup> call_frame_visitor(parent,this); | 
					
						
							| 
									
										
										
										
											2011-12-06 18:00:02 -05:00
										 |  |  | 	parent->iterate_callstack_object(stack,call_frame_visitor,fixup); | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void slot_visitor<Fixup>::visit_callstack(context *ctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	call_frame_slot_visitor<Fixup> call_frame_visitor(parent,this); | 
					
						
							| 
									
										
										
										
											2011-12-06 18:00:02 -05:00
										 |  |  | 	parent->iterate_callstack(ctx,call_frame_visitor,fixup); | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void slot_visitor<Fixup>::visit_contexts() | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-26 22:44:43 -04:00
										 |  |  | 	std::set<context *>::const_iterator begin = parent->active_contexts.begin(); | 
					
						
							|  |  |  | 	std::set<context *>::const_iterator end = parent->active_contexts.end(); | 
					
						
							|  |  |  | 	while(begin != end) | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-03-26 22:44:43 -04:00
										 |  |  | 		context *ctx = *begin; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		visit_stack_elements(ctx->datastack_seg,(cell *)ctx->datastack); | 
					
						
							|  |  |  | 		visit_stack_elements(ctx->retainstack_seg,(cell *)ctx->retainstack); | 
					
						
							| 
									
										
										
										
											2010-03-18 05:06:00 -04:00
										 |  |  | 		visit_object_array(ctx->context_objects,ctx->context_objects + context_object_count); | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 		visit_callstack(ctx); | 
					
						
							| 
									
										
										
										
											2010-03-26 22:44:43 -04:00
										 |  |  | 		begin++; | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | struct literal_references_visitor { | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	slot_visitor<Fixup> *visitor; | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	explicit literal_references_visitor(slot_visitor<Fixup> *visitor_) : visitor(visitor_) {} | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 	void operator()(instruction_operand op) | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-15 07:20:09 -05:00
										 |  |  | 		if(op.rel_type() == RT_LITERAL) | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 			op.store_value(visitor->visit_pointer(op.load_value())); | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void slot_visitor<Fixup>::visit_code_block_objects(code_block *compiled) | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	visit_handle(&compiled->owner); | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 	visit_handle(&compiled->parameters); | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | 	visit_handle(&compiled->relocation); | 
					
						
							| 
									
										
										
										
											2009-11-24 20:29:59 -05:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void slot_visitor<Fixup>::visit_embedded_literals(code_block *compiled) | 
					
						
							| 
									
										
										
										
											2009-11-24 20:29:59 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 	if(!parent->code->uninitialized_p(compiled)) | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 		literal_references_visitor<Fixup> visitor(this); | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 		compiled->each_instruction_operand(visitor); | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-22 14:37:39 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | } |