| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | namespace factor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | /* Code block visitors iterate over sets of code blocks, applying a functor to
 | 
					
						
							|  |  |  | each one. The functor returns a new code_block pointer, which may or may not | 
					
						
							|  |  |  | equal the old one. This is stored back to the original location. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This is used by GC's sweep and compact phases, and the implementation of the | 
					
						
							|  |  |  | modify-code-heap primitive. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Iteration is driven by visit_*() methods. Some of them define GC roots: | 
					
						
							|  |  |  | - visit_context_code_blocks() | 
					
						
							|  |  |  | - visit_callback_code_blocks() */ | 
					
						
							|  |  |  |   | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> struct code_block_visitor { | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | 	factor_vm *parent; | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	Fixup fixup; | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	explicit code_block_visitor(factor_vm *parent_, Fixup fixup_) : | 
					
						
							|  |  |  | 		parent(parent_), fixup(fixup_) {} | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-28 20:48:26 -05:00
										 |  |  | 	code_block *visit_code_block(code_block *compiled); | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | 	void visit_object_code_block(object *obj); | 
					
						
							| 
									
										
										
										
											2009-11-24 20:29:59 -05:00
										 |  |  | 	void visit_embedded_code_pointers(code_block *compiled); | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | 	void visit_context_code_blocks(); | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 	void visit_uninitialized_code_blocks(); | 
					
						
							| 
									
										
										
										
											2011-10-30 21:41:48 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	void visit_code_roots(); | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | code_block *code_block_visitor<Fixup>::visit_code_block(code_block *compiled) | 
					
						
							| 
									
										
										
										
											2009-11-28 20:48:26 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	return fixup.fixup_code(compiled); | 
					
						
							| 
									
										
										
										
											2009-11-28 20:48:26 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | struct call_frame_code_block_visitor { | 
					
						
							| 
									
										
										
										
											2009-10-24 05:18:33 -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 call_frame_code_block_visitor(factor_vm *parent_, Fixup fixup_) : | 
					
						
							|  |  |  | 		parent(parent_), fixup(fixup_) {} | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-06 12:14:56 -05:00
										 |  |  | 	void operator()(void *frame_top, cell frame_size, code_block *owner, void *addr) | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2011-12-06 12:14:56 -05:00
										 |  |  | 		code_block *compiled = Fixup::translated_code_block_map | 
					
						
							|  |  |  | 			? owner | 
					
						
							|  |  |  | 			: fixup.fixup_code(owner); | 
					
						
							|  |  |  | 		void *fixed_addr = compiled->address_for_offset(owner->offset(addr)); | 
					
						
							|  |  |  | 		set_frame_return_address(frame_top, fixed_addr); | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void code_block_visitor<Fixup>::visit_object_code_block(object *obj) | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	switch(obj->type()) | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | 	case WORD_TYPE: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			word *w = (word *)obj; | 
					
						
							| 
									
										
										
										
											2011-11-10 19:00:47 -05:00
										 |  |  | 			if(w->entry_point) | 
					
						
							|  |  |  | 				w->entry_point = visit_code_block(w->code())->entry_point(); | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case QUOTATION_TYPE: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			quotation *q = (quotation *)obj; | 
					
						
							| 
									
										
										
										
											2011-11-10 19:00:47 -05:00
										 |  |  | 			if(q->entry_point) | 
					
						
							|  |  |  | 				q->entry_point = visit_code_block(q->code())->entry_point(); | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case CALLSTACK_TYPE: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			callstack *stack = (callstack *)obj; | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 			call_frame_code_block_visitor<Fixup> call_frame_visitor(parent,fixup); | 
					
						
							| 
									
										
										
										
											2011-12-06 18:00:02 -05:00
										 |  |  | 			parent->iterate_callstack_object(stack,call_frame_visitor,fixup); | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							| 
									
										
										
										
											2009-11-24 20:29:59 -05:00
										 |  |  | struct embedded_code_pointers_visitor { | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	Fixup fixup; | 
					
						
							| 
									
										
										
										
											2009-10-24 05:36:29 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	explicit embedded_code_pointers_visitor(Fixup fixup_) : fixup(fixup_) {} | 
					
						
							| 
									
										
										
										
											2009-10-31 22:06:34 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 	void operator()(instruction_operand op) | 
					
						
							| 
									
										
										
										
											2009-10-24 05:36:29 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 		relocation_type type = op.rel_type(); | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 		if(type == RT_ENTRY_POINT | 
					
						
							|  |  |  | 			|| type == RT_ENTRY_POINT_PIC | 
					
						
							|  |  |  | 			|| type == RT_ENTRY_POINT_PIC_TAIL) | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 			op.store_code_block(fixup.fixup_code(op.load_code_block())); | 
					
						
							| 
									
										
										
										
											2009-10-24 05:36:29 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2009-10-24 05:36:29 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void code_block_visitor<Fixup>::visit_embedded_code_pointers(code_block *compiled) | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 	if(!parent->code->uninitialized_p(compiled)) | 
					
						
							| 
									
										
										
										
											2009-10-24 05:36:29 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 		embedded_code_pointers_visitor<Fixup> operand_visitor(fixup); | 
					
						
							|  |  |  | 		compiled->each_instruction_operand(operand_visitor); | 
					
						
							| 
									
										
										
										
											2009-10-24 05:36:29 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void code_block_visitor<Fixup>::visit_context_code_blocks() | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 	call_frame_code_block_visitor<Fixup> call_frame_visitor(parent,fixup); | 
					
						
							| 
									
										
										
										
											2011-12-06 18:00:02 -05:00
										 |  |  | 	parent->iterate_active_callstacks(call_frame_visitor,fixup); | 
					
						
							| 
									
										
										
										
											2009-11-23 19:51:08 -05:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-10-24 05:36:29 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void code_block_visitor<Fixup>::visit_uninitialized_code_blocks() | 
					
						
							| 
									
										
										
										
											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( | 
					
						
							| 
									
										
										
										
											2010-06-11 20:06:00 -04:00
										 |  |  | 			fixup.fixup_code(iter->first), | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 			iter->second)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	parent->code->uninitialized_blocks = new_uninitialized_blocks; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-30 21:41:48 -04:00
										 |  |  | template<typename Fixup> | 
					
						
							|  |  |  | void code_block_visitor<Fixup>::visit_code_roots() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	visit_uninitialized_code_blocks(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-24 04:54:53 -04:00
										 |  |  | } |