| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | #include "master.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | namespace factor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | cell factor_vm::compute_entry_point_address(cell obj) | 
					
						
							| 
									
										
										
										
											2009-05-07 15:26:08 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	switch(tagged<object>(obj).type()) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	case WORD_TYPE: | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 		return (cell)untag<word>(obj)->entry_point; | 
					
						
							| 
									
										
										
										
											2009-05-07 15:26:08 -04:00
										 |  |  | 	case QUOTATION_TYPE: | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 		return (cell)untag<quotation>(obj)->entry_point; | 
					
						
							| 
									
										
										
										
											2009-05-07 15:26:08 -04:00
										 |  |  | 	default: | 
					
						
							|  |  |  | 		critical_error("Expected word or quotation",obj); | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2009-05-07 15:26:08 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | cell factor_vm::compute_entry_point_pic_address(word *w, cell tagged_quot) | 
					
						
							| 
									
										
										
										
											2009-05-07 15:26:08 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-18 21:26:21 -04:00
										 |  |  | 	if(!to_boolean(tagged_quot) || max_pic_size == 0) | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 		return (cell)w->entry_point; | 
					
						
							| 
									
										
										
										
											2009-05-07 15:26:08 -04:00
										 |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		quotation *quot = untag<quotation>(tagged_quot); | 
					
						
							| 
									
										
										
										
											2010-01-06 05:49:14 -05:00
										 |  |  | 		if(quot_compiled_p(quot)) | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 			return (cell)quot->entry_point; | 
					
						
							| 
									
										
										
										
											2009-05-12 04:09:15 -04:00
										 |  |  | 		else | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 			return (cell)w->entry_point; | 
					
						
							| 
									
										
										
										
											2009-05-07 15:26:08 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | cell factor_vm::compute_entry_point_pic_address(cell w_) | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	tagged<word> w(w_); | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 	return compute_entry_point_pic_address(w.untagged(),w->pic_def); | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | cell factor_vm::compute_entry_point_pic_tail_address(cell w_) | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	tagged<word> w(w_); | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 	return compute_entry_point_pic_address(w.untagged(),w->pic_tail_def); | 
					
						
							| 
									
										
										
										
											2009-05-07 15:26:08 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | cell factor_vm::code_block_owner(code_block *compiled) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	tagged<object> owner(compiled->owner); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Cold generic word call sites point to quotations that call the
 | 
					
						
							|  |  |  | 	inline-cache-miss and inline-cache-miss-tail primitives. */ | 
					
						
							|  |  |  | 	if(owner.type_p(QUOTATION_TYPE)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		tagged<quotation> quot(owner.as<quotation>()); | 
					
						
							|  |  |  | 		tagged<array> elements(quot->array); | 
					
						
							|  |  |  | #ifdef FACTOR_DEBUG
 | 
					
						
							|  |  |  | 		assert(array_capacity(elements.untagged()) == 5); | 
					
						
							|  |  |  | 		assert(array_nth(elements.untagged(),4) == special_objects[PIC_MISS_WORD] | 
					
						
							|  |  |  | 			|| array_nth(elements.untagged(),4) == special_objects[PIC_MISS_TAIL_WORD]); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		tagged<wrapper> word_wrapper(array_nth(elements.untagged(),0)); | 
					
						
							|  |  |  | 		return word_wrapper->object; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return compiled->owner; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-28 20:48:26 -05:00
										 |  |  | struct update_word_references_relocation_visitor { | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | 	factor_vm *parent; | 
					
						
							| 
									
										
										
										
											2010-02-01 08:49:05 -05:00
										 |  |  | 	bool reset_inline_caches; | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-01 08:49:05 -05:00
										 |  |  | 	update_word_references_relocation_visitor( | 
					
						
							|  |  |  | 		factor_vm *parent_, | 
					
						
							|  |  |  | 		bool reset_inline_caches_) : | 
					
						
							|  |  |  | 		parent(parent_), | 
					
						
							|  |  |  | 		reset_inline_caches(reset_inline_caches_) {} | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 	void operator()(instruction_operand op) | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 		switch(op.rel_type()) | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 		case RT_ENTRY_POINT: | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				code_block *compiled = op.load_code_block(); | 
					
						
							| 
									
										
										
										
											2009-12-02 06:27:48 -05:00
										 |  |  | 				cell owner = compiled->owner; | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 				if(to_boolean(owner)) | 
					
						
							|  |  |  | 					op.store_value(parent->compute_entry_point_address(owner)); | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 		case RT_ENTRY_POINT_PIC: | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				code_block *compiled = op.load_code_block(); | 
					
						
							| 
									
										
										
										
											2010-02-01 08:49:05 -05:00
										 |  |  | 				if(reset_inline_caches || !compiled->pic_p()) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					cell owner = parent->code_block_owner(compiled); | 
					
						
							|  |  |  | 					if(to_boolean(owner)) | 
					
						
							|  |  |  | 						op.store_value(parent->compute_entry_point_pic_address(owner)); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 		case RT_ENTRY_POINT_PIC_TAIL: | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				code_block *compiled = op.load_code_block(); | 
					
						
							| 
									
										
										
										
											2010-02-01 08:49:05 -05:00
										 |  |  | 				if(reset_inline_caches || !compiled->pic_p()) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					cell owner = parent->code_block_owner(compiled); | 
					
						
							|  |  |  | 					if(to_boolean(owner)) | 
					
						
							|  |  |  | 						op.store_value(parent->compute_entry_point_pic_tail_address(owner)); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Relocate new code blocks completely; updating references to literals,
 | 
					
						
							|  |  |  | dlsyms, and words. For all other words in the code heap, we only need | 
					
						
							|  |  |  | to update references to other words, without worrying about literals | 
					
						
							|  |  |  | or dlsyms. */ | 
					
						
							| 
									
										
										
										
											2010-02-01 08:49:05 -05:00
										 |  |  | void factor_vm::update_word_references(code_block *compiled, bool reset_inline_caches) | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 	if(code->uninitialized_p(compiled)) | 
					
						
							| 
									
										
										
										
											2009-12-02 02:09:08 -05:00
										 |  |  | 		initialize_code_block(compiled); | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | 	/* update_word_references() is always applied to every block in
 | 
					
						
							|  |  |  | 	   the code heap. Since it resets all call sites to point to | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 	   their canonical entry point (cold entry point for non-tail calls, | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | 	   standard entry point for tail calls), it means that no PICs | 
					
						
							|  |  |  | 	   are referenced after this is done. So instead of polluting | 
					
						
							|  |  |  | 	   the code heap with dead PICs that will be freed on the next | 
					
						
							|  |  |  | 	   GC, we add them to the free list immediately. */ | 
					
						
							| 
									
										
										
										
											2010-02-01 08:49:05 -05:00
										 |  |  | 	else if(reset_inline_caches && compiled->pic_p()) | 
					
						
							| 
									
										
										
										
											2009-12-02 06:27:48 -05:00
										 |  |  | 		code->free(compiled); | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-02-01 08:49:05 -05:00
										 |  |  | 		update_word_references_relocation_visitor visitor(this,reset_inline_caches); | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 		compiled->each_instruction_operand(visitor); | 
					
						
							| 
									
										
										
										
											2009-11-25 18:20:48 -05:00
										 |  |  | 		compiled->flush_icache(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 02:09:08 -05:00
										 |  |  | /* References to undefined symbols are patched up to call this function on
 | 
					
						
							|  |  |  | image load */ | 
					
						
							|  |  |  | void factor_vm::undefined_symbol() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-27 07:33:28 -04:00
										 |  |  | 	general_error(ERROR_UNDEFINED_SYMBOL,false_object,false_object); | 
					
						
							| 
									
										
										
										
											2009-12-02 02:09:08 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void undefined_symbol() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2010-03-27 03:44:40 -04:00
										 |  |  | 	return current_vm()->undefined_symbol(); | 
					
						
							| 
									
										
										
										
											2009-12-02 02:09:08 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Look up an external library symbol referenced by a compiled code block */ | 
					
						
							|  |  |  | cell factor_vm::compute_dlsym_address(array *literals, cell index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	cell symbol = array_nth(literals,index); | 
					
						
							|  |  |  | 	cell library = array_nth(literals,index + 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dll *d = (to_boolean(library) ? untag<dll>(library) : NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-16 09:43:22 -05:00
										 |  |  | 	if(d != NULL && !d->handle) | 
					
						
							| 
									
										
										
										
											2009-12-02 02:09:08 -05:00
										 |  |  | 		return (cell)factor::undefined_symbol; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch(tagged<object>(symbol).type()) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	case BYTE_ARRAY_TYPE: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			symbol_char *name = alien_offset(symbol); | 
					
						
							|  |  |  | 			void *sym = ffi_dlsym(d,name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(sym) | 
					
						
							|  |  |  | 				return (cell)sym; | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				return (cell)factor::undefined_symbol; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case ARRAY_TYPE: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			array *names = untag<array>(symbol); | 
					
						
							|  |  |  | 			for(cell i = 0; i < array_capacity(names); i++) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				symbol_char *name = alien_offset(array_nth(names,i)); | 
					
						
							|  |  |  | 				void *sym = ffi_dlsym(d,name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if(sym) | 
					
						
							|  |  |  | 					return (cell)sym; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return (cell)factor::undefined_symbol; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		critical_error("Bad symbol specifier",symbol); | 
					
						
							|  |  |  | 		return (cell)factor::undefined_symbol; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | cell factor_vm::compute_vm_address(cell arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return (cell)this + untag_fixnum(arg); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void factor_vm::store_external_address(instruction_operand op) | 
					
						
							| 
									
										
										
										
											2009-12-02 01:54:16 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	code_block *compiled = op.parent_code_block(); | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 	array *parameters = (to_boolean(compiled->parameters) ? untag<array>(compiled->parameters) : NULL); | 
					
						
							| 
									
										
										
										
											2009-12-02 01:54:16 -05:00
										 |  |  | 	cell index = op.parameter_index(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch(op.rel_type()) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	case RT_DLSYM: | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 		op.store_value(compute_dlsym_address(parameters,index)); | 
					
						
							| 
									
										
										
										
											2009-12-02 01:54:16 -05:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case RT_THIS: | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 		op.store_value((cell)compiled->entry_point()); | 
					
						
							| 
									
										
										
										
											2009-12-02 01:54:16 -05:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case RT_MEGAMORPHIC_CACHE_HITS: | 
					
						
							| 
									
										
										
										
											2009-12-02 02:09:08 -05:00
										 |  |  | 		op.store_value((cell)&dispatch_stats.megamorphic_cache_hits); | 
					
						
							| 
									
										
										
										
											2009-12-02 01:54:16 -05:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case RT_VM: | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 		op.store_value(compute_vm_address(array_nth(parameters,index))); | 
					
						
							| 
									
										
										
										
											2009-12-02 01:54:16 -05:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case RT_CARDS_OFFSET: | 
					
						
							| 
									
										
										
										
											2009-12-02 02:09:08 -05:00
										 |  |  | 		op.store_value(cards_offset); | 
					
						
							| 
									
										
										
										
											2009-12-02 01:54:16 -05:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case RT_DECKS_OFFSET: | 
					
						
							| 
									
										
										
										
											2009-12-02 02:09:08 -05:00
										 |  |  | 		op.store_value(decks_offset); | 
					
						
							| 
									
										
										
										
											2009-12-02 01:54:16 -05:00
										 |  |  | 		break; | 
					
						
							| 
									
										
										
										
											2010-04-03 20:24:33 -04:00
										 |  |  | #ifdef WINDOWS
 | 
					
						
							|  |  |  | 	case RT_EXCEPTION_HANDLER: | 
					
						
							| 
									
										
										
										
											2010-04-04 14:53:17 -04:00
										 |  |  | 		op.store_value((cell)&factor::exception_handler); | 
					
						
							| 
									
										
										
										
											2010-04-03 20:24:33 -04:00
										 |  |  | 		break; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:54:16 -05:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2010-04-30 21:33:42 -04:00
										 |  |  | 		critical_error("Bad rel type in store_external_address()",op.rel_type()); | 
					
						
							| 
									
										
										
										
											2009-12-02 01:54:16 -05:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 05:55:48 -05:00
										 |  |  | cell factor_vm::compute_here_address(cell arg, cell offset, code_block *compiled) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	fixnum n = untag_fixnum(arg); | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 	if(n >= 0) | 
					
						
							|  |  |  | 		return (cell)compiled->entry_point() + offset + n; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return (cell)compiled->entry_point() - n; | 
					
						
							| 
									
										
										
										
											2009-12-02 05:55:48 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 02:09:08 -05:00
										 |  |  | struct initial_code_block_visitor { | 
					
						
							| 
									
										
										
										
											2009-10-18 21:31:59 -04:00
										 |  |  | 	factor_vm *parent; | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 	cell literals; | 
					
						
							|  |  |  | 	cell literal_index; | 
					
						
							| 
									
										
										
										
											2009-10-03 09:47:05 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 	explicit initial_code_block_visitor(factor_vm *parent_, cell literals_) | 
					
						
							|  |  |  | 		: parent(parent_), literals(literals_), literal_index(0) {} | 
					
						
							| 
									
										
										
										
											2009-10-03 09:47:05 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 	cell next_literal() | 
					
						
							| 
									
										
										
										
											2009-10-03 09:47:05 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 		return array_nth(untag<array>(literals),literal_index++); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-28 20:48:26 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 	void operator()(instruction_operand op) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 		switch(op.rel_type()) | 
					
						
							| 
									
										
										
										
											2009-11-28 20:48:26 -05:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-12-15 07:20:09 -05:00
										 |  |  | 		case RT_LITERAL: | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 			op.store_value(next_literal()); | 
					
						
							| 
									
										
										
										
											2009-11-28 20:48:26 -05:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 		case RT_ENTRY_POINT: | 
					
						
							|  |  |  | 			op.store_value(parent->compute_entry_point_address(next_literal())); | 
					
						
							| 
									
										
										
										
											2009-11-28 20:48:26 -05:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 		case RT_ENTRY_POINT_PIC: | 
					
						
							|  |  |  | 			op.store_value(parent->compute_entry_point_pic_address(next_literal())); | 
					
						
							| 
									
										
										
										
											2009-11-28 20:48:26 -05:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 		case RT_ENTRY_POINT_PIC_TAIL: | 
					
						
							|  |  |  | 			op.store_value(parent->compute_entry_point_pic_tail_address(next_literal())); | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-12-02 05:55:48 -05:00
										 |  |  | 		case RT_HERE: | 
					
						
							|  |  |  | 			op.store_value(parent->compute_here_address(next_literal(),op.rel_offset(),op.parent_code_block())); | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 		case RT_UNTAGGED: | 
					
						
							|  |  |  | 			op.store_value(untag_fixnum(next_literal())); | 
					
						
							| 
									
										
										
										
											2009-11-28 20:48:26 -05:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2009-12-02 02:09:08 -05:00
										 |  |  | 			parent->store_external_address(op); | 
					
						
							| 
									
										
										
										
											2009-11-28 20:48:26 -05:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-10-03 09:47:05 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | /* Perform all fixups on a code block */ | 
					
						
							| 
									
										
										
										
											2010-02-01 08:49:05 -05:00
										 |  |  | void factor_vm::initialize_code_block(code_block *compiled, cell literals) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-02-01 08:49:05 -05:00
										 |  |  | 	initial_code_block_visitor visitor(this,literals); | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 	compiled->each_instruction_operand(visitor); | 
					
						
							| 
									
										
										
										
											2009-11-24 22:36:35 -05:00
										 |  |  | 	compiled->flush_icache(); | 
					
						
							| 
									
										
										
										
											2009-12-21 21:49:21 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* next time we do a minor GC, we have to trace this code block, since
 | 
					
						
							|  |  |  | 	the newly-installed instruction operands might point to literals in | 
					
						
							|  |  |  | 	nursery or aging */ | 
					
						
							|  |  |  | 	code->write_barrier(compiled); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-01 08:49:05 -05:00
										 |  |  | void factor_vm::initialize_code_block(code_block *compiled) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	std::map<code_block *,cell>::iterator iter = code->uninitialized_blocks.find(compiled); | 
					
						
							|  |  |  | 	initialize_code_block(compiled,iter->second); | 
					
						
							|  |  |  | 	code->uninitialized_blocks.erase(iter); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | /* Fixup labels. This is done at compile time, not image load time */ | 
					
						
							| 
									
										
										
										
											2009-09-23 14:05:46 -04:00
										 |  |  | void factor_vm::fixup_labels(array *labels, code_block *compiled) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	cell size = array_capacity(labels); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 	for(cell i = 0; i < size; i += 3) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 		relocation_class rel_class = (relocation_class)untag_fixnum(array_nth(labels,i)); | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		cell offset = untag_fixnum(array_nth(labels,i + 1)); | 
					
						
							|  |  |  | 		cell target = untag_fixnum(array_nth(labels,i + 2)); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 		relocation_entry new_entry(RT_HERE,rel_class,offset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		instruction_operand op(new_entry,compiled,0); | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 		op.store_value(target + (cell)compiled->entry_point()); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Might GC */ | 
					
						
							| 
									
										
										
										
											2009-10-20 10:37:24 -04:00
										 |  |  | code_block *factor_vm::allot_code_block(cell size, code_block_type type) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-24 22:24:06 -04:00
										 |  |  | 	code_block *block = code->allocator->allot(size + sizeof(code_block)); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-16 12:39:22 -04:00
										 |  |  | 	/* If allocation failed, do a full GC and compact the code heap.
 | 
					
						
							|  |  |  | 	A full GC that occurs as a result of the data heap filling up does not | 
					
						
							|  |  |  | 	trigger a compaction. This setup ensures that most GCs do not compact | 
					
						
							|  |  |  | 	the code heap, but if the code fills up, it probably means it will be | 
					
						
							|  |  |  | 	fragmented after GC anyway, so its best to compact. */ | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	if(block == NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-10-16 12:39:22 -04:00
										 |  |  | 		primitive_compact_gc(); | 
					
						
							| 
									
										
										
										
											2009-10-20 16:15:05 -04:00
										 |  |  | 		block = code->allocator->allot(size + sizeof(code_block)); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* Insufficient room even after code GC, give up */ | 
					
						
							|  |  |  | 		if(block == NULL) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-10-26 23:08:35 -04:00
										 |  |  | 			std::cout << "Code heap used: " << code->allocator->occupied_space() << "\n"; | 
					
						
							|  |  |  | 			std::cout << "Code heap free: " << code->allocator->free_space() << "\n"; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 			fatal_error("Out of memory in add-compiled-block",0); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-24 22:24:06 -04:00
										 |  |  | 	block->set_type(type); | 
					
						
							|  |  |  | 	return block; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Might GC */ | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | code_block *factor_vm::add_code_block(code_block_type type, cell code_, cell labels_, cell owner_, cell relocation_, cell parameters_, cell literals_) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-11-02 19:10:34 -05:00
										 |  |  | 	data_root<byte_array> code(code_,this); | 
					
						
							|  |  |  | 	data_root<object> labels(labels_,this); | 
					
						
							|  |  |  | 	data_root<object> owner(owner_,this); | 
					
						
							|  |  |  | 	data_root<byte_array> relocation(relocation_,this); | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 	data_root<array> parameters(parameters_,this); | 
					
						
							| 
									
										
										
										
											2009-11-02 19:10:34 -05:00
										 |  |  | 	data_root<array> literals(literals_,this); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-20 13:19:02 -04:00
										 |  |  | 	cell code_length = array_capacity(code.untagged()); | 
					
						
							| 
									
										
										
										
											2009-10-06 06:52:45 -04:00
										 |  |  | 	code_block *compiled = allot_code_block(code_length,type); | 
					
						
							| 
									
										
										
										
											2009-05-02 10:19:09 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-06 07:25:07 -04:00
										 |  |  | 	compiled->owner = owner.value(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 10:19:09 -04:00
										 |  |  | 	/* slight space optimization */ | 
					
						
							| 
									
										
										
										
											2009-10-06 02:31:39 -04:00
										 |  |  | 	if(relocation.type() == BYTE_ARRAY_TYPE && array_capacity(relocation.untagged()) == 0) | 
					
						
							| 
									
										
										
										
											2009-10-18 21:26:21 -04:00
										 |  |  | 		compiled->relocation = false_object; | 
					
						
							| 
									
										
										
										
											2009-10-06 02:31:39 -04:00
										 |  |  | 	else | 
					
						
							|  |  |  | 		compiled->relocation = relocation.value(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 	if(parameters.type() == ARRAY_TYPE && array_capacity(parameters.untagged()) == 0) | 
					
						
							|  |  |  | 		compiled->parameters = false_object; | 
					
						
							| 
									
										
										
										
											2009-05-02 10:19:09 -04:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 		compiled->parameters = parameters.value(); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* code */ | 
					
						
							| 
									
										
										
										
											2009-05-02 10:19:09 -04:00
										 |  |  | 	memcpy(compiled + 1,code.untagged() + 1,code_length); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* fixup labels */ | 
					
						
							| 
									
										
										
										
											2009-10-18 21:26:21 -04:00
										 |  |  | 	if(to_boolean(labels.value())) | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 		fixup_labels(labels.as<array>().untagged(),compiled); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-21 21:49:21 -05:00
										 |  |  | 	/* Once we are ready, fill in literal and word references in this code
 | 
					
						
							|  |  |  | 	block's instruction operands. In most cases this is done right after this | 
					
						
							|  |  |  | 	method returns, except when compiling words with the non-optimizing | 
					
						
							|  |  |  | 	compiler at the beginning of bootstrap */ | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 	this->code->uninitialized_blocks.insert(std::make_pair(compiled,literals.value())); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-21 21:49:21 -05:00
										 |  |  | 	/* next time we do a minor GC, we have to trace this code block, since
 | 
					
						
							|  |  |  | 	the fields of the code_block struct might point into nursery or aging */ | 
					
						
							|  |  |  | 	this->code->write_barrier(compiled); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	return compiled; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | } |