| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | #include "master.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* References to undefined symbols are patched up to call this function on
 | 
					
						
							|  |  |  | image load */ | 
					
						
							|  |  |  | void undefined_symbol(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	general_error(ERROR_UNDEFINED_SYMBOL,F,F,NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define CREF(array,i) ((CELL)(array) + CELLS * (i))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | INLINE CELL get_literal(CELL literals_start, CELL num) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return get(CREF(literals_start,num)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Look up an external library symbol referenced by a compiled code block */ | 
					
						
							|  |  |  | void *get_rel_symbol(F_REL *rel, CELL literals_start) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	CELL arg = REL_ARGUMENT(rel); | 
					
						
							| 
									
										
										
										
											2008-02-16 01:54:54 -05:00
										 |  |  | 	CELL symbol = get_literal(literals_start,arg); | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 	CELL library = get_literal(literals_start,arg + 1); | 
					
						
							| 
									
										
										
										
											2008-02-16 01:54:54 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 	F_DLL *dll = (library == F ? NULL : untag_dll(library)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(dll != NULL && !dll->dll) | 
					
						
							|  |  |  | 		return undefined_symbol; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-16 01:54:54 -05:00
										 |  |  | 	if(type_of(symbol) == BYTE_ARRAY_TYPE) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2008-02-17 19:38:29 -05:00
										 |  |  | 		F_SYMBOL *name = alien_offset(symbol); | 
					
						
							| 
									
										
										
										
											2008-02-16 01:54:54 -05:00
										 |  |  | 		void *sym = ffi_dlsym(dll,name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(sym) | 
					
						
							|  |  |  | 			return sym; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if(type_of(symbol) == ARRAY_TYPE) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		CELL i; | 
					
						
							|  |  |  | 		F_ARRAY *names = untag_object(symbol); | 
					
						
							|  |  |  | 		for(i = 0; i < array_capacity(names); i++) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2008-02-17 19:38:29 -05:00
										 |  |  | 			F_SYMBOL *name = alien_offset(array_nth(names,i)); | 
					
						
							| 
									
										
										
										
											2008-02-16 01:54:54 -05:00
										 |  |  | 			void *sym = ffi_dlsym(dll,name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(sym) | 
					
						
							|  |  |  | 				return sym; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return undefined_symbol; | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Compute an address to store at a relocation */ | 
					
						
							|  |  |  | INLINE CELL compute_code_rel(F_REL *rel, | 
					
						
							| 
									
										
										
										
											2008-01-16 15:45:04 -05:00
										 |  |  | 	CELL code_start, CELL literals_start) | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	switch(REL_TYPE(rel)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	case RT_PRIMITIVE: | 
					
						
							|  |  |  | 		return (CELL)primitives[REL_ARGUMENT(rel)]; | 
					
						
							|  |  |  | 	case RT_DLSYM: | 
					
						
							|  |  |  | 		return (CELL)get_rel_symbol(rel,literals_start); | 
					
						
							|  |  |  | 	case RT_LITERAL: | 
					
						
							|  |  |  | 		return CREF(literals_start,REL_ARGUMENT(rel)); | 
					
						
							| 
									
										
										
										
											2008-07-12 23:27:28 -04:00
										 |  |  | 	case RT_IMMEDIATE: | 
					
						
							|  |  |  | 		return get(CREF(literals_start,REL_ARGUMENT(rel))); | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 	case RT_XT: | 
					
						
							| 
									
										
										
										
											2008-01-16 15:45:04 -05:00
										 |  |  | 		return (CELL)untag_word(get(CREF(literals_start,REL_ARGUMENT(rel))))->xt; | 
					
						
							| 
									
										
										
										
											2008-01-13 17:07:59 -05:00
										 |  |  | 	case RT_HERE: | 
					
						
							|  |  |  | 		return rel->offset + code_start; | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 	case RT_LABEL: | 
					
						
							|  |  |  | 		return code_start + REL_ARGUMENT(rel); | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		critical_error("Bad rel type",rel->type); | 
					
						
							| 
									
										
										
										
											2008-01-02 19:36:36 -05:00
										 |  |  | 		return -1; /* Can't happen */ | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Store a 32-bit value into a PowerPC LIS/ORI sequence */ | 
					
						
							|  |  |  | INLINE void reloc_set_2_2(CELL cell, CELL value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	put(cell - CELLS,((get(cell - CELLS) & ~0xffff) | ((value >> 16) & 0xffff))); | 
					
						
							|  |  |  | 	put(cell,((get(cell) & ~0xffff) | (value & 0xffff))); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Store a value into a bitfield of a PowerPC instruction */ | 
					
						
							|  |  |  | INLINE void reloc_set_masked(CELL cell, F_FIXNUM value, CELL mask, F_FIXNUM shift) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-22 03:49:19 -04:00
										 |  |  | 	/* This is unaccurate but good enough */ | 
					
						
							|  |  |  | 	F_FIXNUM test = (F_FIXNUM)mask >> 1; | 
					
						
							|  |  |  | 	if(value <= -test || value >= test) | 
					
						
							|  |  |  | 		critical_error("Value does not fit inside relocation",0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 	u32 original = *(u32*)cell; | 
					
						
							|  |  |  | 	original &= ~mask; | 
					
						
							|  |  |  | 	*(u32*)cell = (original | ((value >> shift) & mask)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Perform a fixup on a code block */ | 
					
						
							|  |  |  | void apply_relocation(CELL class, CELL offset, F_FIXNUM absolute_value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	F_FIXNUM relative_value = absolute_value - offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch(class) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	case RC_ABSOLUTE_CELL: | 
					
						
							|  |  |  | 		put(offset,absolute_value); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case RC_ABSOLUTE: | 
					
						
							|  |  |  | 		*(u32*)offset = absolute_value; | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case RC_RELATIVE: | 
					
						
							|  |  |  | 		*(u32*)offset = relative_value - sizeof(u32); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case RC_ABSOLUTE_PPC_2_2: | 
					
						
							|  |  |  | 		reloc_set_2_2(offset,absolute_value); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case RC_RELATIVE_PPC_2: | 
					
						
							|  |  |  | 		reloc_set_masked(offset,relative_value,REL_RELATIVE_PPC_2_MASK,0); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case RC_RELATIVE_PPC_3: | 
					
						
							|  |  |  | 		reloc_set_masked(offset,relative_value,REL_RELATIVE_PPC_3_MASK,0); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case RC_RELATIVE_ARM_3: | 
					
						
							|  |  |  | 		reloc_set_masked(offset,relative_value - CELLS * 2, | 
					
						
							|  |  |  | 			REL_RELATIVE_ARM_3_MASK,2); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case RC_INDIRECT_ARM: | 
					
						
							|  |  |  | 		reloc_set_masked(offset,relative_value - CELLS, | 
					
						
							|  |  |  | 			REL_INDIRECT_ARM_MASK,0); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	case RC_INDIRECT_ARM_PC: | 
					
						
							|  |  |  | 		reloc_set_masked(offset,relative_value - CELLS * 2, | 
					
						
							|  |  |  | 			REL_INDIRECT_ARM_MASK,0); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		critical_error("Bad rel class",class); | 
					
						
							|  |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Perform all fixups on a code block */ | 
					
						
							| 
									
										
										
										
											2008-05-30 02:31:05 -04:00
										 |  |  | void relocate_code_block(F_COMPILED *compiled, CELL code_start, CELL literals_start) | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-05-30 02:31:05 -04:00
										 |  |  | 	if(compiled->relocation != F) | 
					
						
							| 
									
										
										
										
											2007-12-26 17:14:33 -05:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2008-05-30 02:31:05 -04:00
										 |  |  | 		F_BYTE_ARRAY *relocation = untag_object(compiled->relocation); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		F_REL *rel = (F_REL *)(relocation + 1); | 
					
						
							|  |  |  | 		F_REL *rel_end = (F_REL *)((char *)rel + byte_array_capacity(relocation)); | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-26 17:14:33 -05:00
										 |  |  | 		while(rel < rel_end) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			CELL offset = rel->offset + code_start; | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-16 15:45:04 -05:00
										 |  |  | 			F_FIXNUM absolute_value = compute_code_rel( | 
					
						
							|  |  |  | 				rel,code_start,literals_start); | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-26 17:14:33 -05:00
										 |  |  | 			apply_relocation(REL_CLASS(rel),offset,absolute_value); | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-26 17:14:33 -05:00
										 |  |  | 			rel++; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-12-26 17:14:33 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-30 02:31:05 -04:00
										 |  |  | 	flush_icache(code_start,literals_start - code_start); | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Fixup labels. This is done at compile time, not image load time */ | 
					
						
							|  |  |  | void fixup_labels(F_ARRAY *labels, CELL code_format, CELL code_start) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	CELL i; | 
					
						
							|  |  |  | 	CELL size = array_capacity(labels); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(i = 0; i < size; i += 3) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		CELL class = to_fixnum(array_nth(labels,i)); | 
					
						
							|  |  |  | 		CELL offset = to_fixnum(array_nth(labels,i + 1)); | 
					
						
							|  |  |  | 		CELL target = to_fixnum(array_nth(labels,i + 2)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		apply_relocation(class, | 
					
						
							|  |  |  | 			offset + code_start, | 
					
						
							|  |  |  | 			target + code_start); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Write a sequence of integers to memory, with 'format' bytes per integer */ | 
					
						
							|  |  |  | void deposit_integers(CELL here, F_ARRAY *array, CELL format) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	CELL count = array_capacity(array); | 
					
						
							|  |  |  | 	CELL i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(i = 0; i < count; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		F_FIXNUM value = to_fixnum(array_nth(array,i)); | 
					
						
							|  |  |  | 		if(format == 1) | 
					
						
							| 
									
										
										
										
											2008-02-01 00:03:10 -05:00
										 |  |  | 			bput(here + i,value); | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 		else if(format == sizeof(unsigned int)) | 
					
						
							|  |  |  | 			*(unsigned int *)(here + format * i) = value; | 
					
						
							|  |  |  | 		else if(format == CELLS) | 
					
						
							|  |  |  | 			put(CREF(here,i),value); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			critical_error("Bad format in deposit_integers()",format); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Write a sequence of tagged pointers to memory */ | 
					
						
							|  |  |  | void deposit_objects(CELL here, F_ARRAY *array) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	memcpy((void*)here,array + 1,array_capacity(array) * CELLS); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-07 16:14:09 -05:00
										 |  |  | bool stack_traces_p(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return to_boolean(userenv[STACK_TRACES_ENV]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | CELL compiled_code_format(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return untag_fixnum_fast(userenv[JIT_CODE_FORMAT]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CELL allot_code_block(CELL size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	CELL start = heap_allot(&code_heap,size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* If allocation failed, do a code GC */ | 
					
						
							|  |  |  | 	if(start == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2008-04-05 05:01:46 -04:00
										 |  |  | 		gc(); | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 		start = heap_allot(&code_heap,size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Insufficient room even after code GC, give up */ | 
					
						
							|  |  |  | 		if(start == 0) | 
					
						
							| 
									
										
										
										
											2008-04-07 21:19:49 -04:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			CELL used, total_free, max_free; | 
					
						
							|  |  |  | 			heap_usage(&code_heap,&used,&total_free,&max_free); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			fprintf(stderr,"Code heap stats:\n"); | 
					
						
							|  |  |  | 			fprintf(stderr,"Used: %ld\n",used); | 
					
						
							|  |  |  | 			fprintf(stderr,"Total free space: %ld\n",total_free); | 
					
						
							|  |  |  | 			fprintf(stderr,"Largest free block: %ld\n",max_free); | 
					
						
							| 
									
										
										
										
											2008-02-25 21:09:52 -05:00
										 |  |  | 			fatal_error("Out of memory in add-compiled-block",0); | 
					
						
							| 
									
										
										
										
											2008-04-07 21:19:49 -04:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return start; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-16 15:17:28 -05:00
										 |  |  | /* Might GC */ | 
					
						
							| 
									
										
										
										
											2007-10-28 04:33:36 -04:00
										 |  |  | F_COMPILED *add_compiled_block( | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 	CELL type, | 
					
						
							|  |  |  | 	F_ARRAY *code, | 
					
						
							|  |  |  | 	F_ARRAY *labels, | 
					
						
							| 
									
										
										
										
											2008-05-30 02:31:05 -04:00
										 |  |  | 	CELL relocation, | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 	F_ARRAY *literals) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	CELL code_format = compiled_code_format(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	CELL code_length = align8(array_capacity(code) * code_format); | 
					
						
							| 
									
										
										
										
											2007-12-26 01:45:16 -05:00
										 |  |  | 	CELL literals_length = array_capacity(literals) * CELLS; | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-30 02:31:05 -04:00
										 |  |  | 	REGISTER_ROOT(relocation); | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 	REGISTER_UNTAGGED(code); | 
					
						
							|  |  |  | 	REGISTER_UNTAGGED(labels); | 
					
						
							|  |  |  | 	REGISTER_UNTAGGED(literals); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-30 02:31:05 -04:00
										 |  |  | 	CELL here = allot_code_block(sizeof(F_COMPILED) + code_length + literals_length); | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	UNREGISTER_UNTAGGED(literals); | 
					
						
							|  |  |  | 	UNREGISTER_UNTAGGED(labels); | 
					
						
							|  |  |  | 	UNREGISTER_UNTAGGED(code); | 
					
						
							| 
									
										
										
										
											2008-05-30 02:31:05 -04:00
										 |  |  | 	UNREGISTER_ROOT(relocation); | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* compiled header */ | 
					
						
							|  |  |  | 	F_COMPILED *header = (void *)here; | 
					
						
							|  |  |  | 	header->type = type; | 
					
						
							|  |  |  | 	header->code_length = code_length; | 
					
						
							|  |  |  | 	header->literals_length = literals_length; | 
					
						
							| 
									
										
										
										
											2008-05-30 02:31:05 -04:00
										 |  |  | 	header->relocation = relocation; | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	here += sizeof(F_COMPILED); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-28 04:33:36 -04:00
										 |  |  | 	CELL code_start = here; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 	/* code */ | 
					
						
							|  |  |  | 	deposit_integers(here,code,code_format); | 
					
						
							|  |  |  | 	here += code_length; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* literals */ | 
					
						
							| 
									
										
										
										
											2007-12-26 01:45:16 -05:00
										 |  |  | 	deposit_objects(here,literals); | 
					
						
							|  |  |  | 	here += literals_length; | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* fixup labels */ | 
					
						
							|  |  |  | 	if(labels) | 
					
						
							| 
									
										
										
										
											2007-10-28 04:33:36 -04:00
										 |  |  | 		fixup_labels(labels,code_format,code_start); | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* next time we do a minor GC, we have to scan the code heap for
 | 
					
						
							|  |  |  | 	literals */ | 
					
						
							|  |  |  | 	last_code_heap_scan = NURSERY; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-28 04:33:36 -04:00
										 |  |  | 	return header; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-02 19:36:36 -05:00
										 |  |  | void set_word_code(F_WORD *word, F_COMPILED *compiled) | 
					
						
							| 
									
										
										
										
											2007-10-28 04:33:36 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-12-16 18:42:56 -05:00
										 |  |  | 	if(compiled->type != WORD_TYPE) | 
					
						
							|  |  |  | 		critical_error("bad param to set_word_xt",(CELL)compiled); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-28 04:33:36 -04:00
										 |  |  | 	word->code = compiled; | 
					
						
							| 
									
										
										
										
											2008-01-02 19:36:36 -05:00
										 |  |  | 	word->compiledp = T; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2007-10-28 04:33:36 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-02 19:36:36 -05:00
										 |  |  | /* Allocates memory */ | 
					
						
							| 
									
										
										
										
											2008-01-09 01:33:40 -05:00
										 |  |  | void default_word_code(F_WORD *word, bool relocate) | 
					
						
							| 
									
										
										
										
											2008-01-02 19:36:36 -05:00
										 |  |  | { | 
					
						
							|  |  |  | 	REGISTER_UNTAGGED(word); | 
					
						
							| 
									
										
										
										
											2008-01-09 01:33:40 -05:00
										 |  |  | 	jit_compile(word->def,relocate); | 
					
						
							| 
									
										
										
										
											2008-01-02 19:36:36 -05:00
										 |  |  | 	UNREGISTER_UNTAGGED(word); | 
					
						
							| 
									
										
										
										
											2007-10-28 04:33:36 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-02 19:36:36 -05:00
										 |  |  | 	word->code = untag_quotation(word->def)->code; | 
					
						
							|  |  |  | 	word->compiledp = F; | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-16 15:17:28 -05:00
										 |  |  | DEFINE_PRIMITIVE(modify_code_heap) | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-02-17 19:38:29 -05:00
										 |  |  | 	bool rescan_code_heap = to_boolean(dpop()); | 
					
						
							| 
									
										
										
										
											2007-12-16 15:17:28 -05:00
										 |  |  | 	F_ARRAY *alist = untag_array(dpop()); | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-16 15:17:28 -05:00
										 |  |  | 	CELL count = untag_fixnum_fast(alist->capacity); | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 	CELL i; | 
					
						
							|  |  |  | 	for(i = 0; i < count; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2007-12-21 21:18:24 -05:00
										 |  |  | 		F_ARRAY *pair = untag_array(array_nth(alist,i)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		F_WORD *word = untag_word(array_nth(pair,0)); | 
					
						
							| 
									
										
										
										
											2007-12-30 21:34:44 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-21 21:18:24 -05:00
										 |  |  | 		CELL data = array_nth(pair,1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(data == F) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2008-01-02 19:36:36 -05:00
										 |  |  | 			REGISTER_UNTAGGED(alist); | 
					
						
							| 
									
										
										
										
											2008-01-07 16:14:09 -05:00
										 |  |  | 			REGISTER_UNTAGGED(word); | 
					
						
							| 
									
										
										
										
											2008-01-09 01:33:40 -05:00
										 |  |  | 			default_word_code(word,false); | 
					
						
							| 
									
										
										
										
											2008-01-07 16:14:09 -05:00
										 |  |  | 			UNREGISTER_UNTAGGED(word); | 
					
						
							| 
									
										
										
										
											2008-01-02 19:36:36 -05:00
										 |  |  | 			UNREGISTER_UNTAGGED(alist); | 
					
						
							| 
									
										
										
										
											2007-12-21 21:18:24 -05:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			F_ARRAY *compiled_code = untag_array(data); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-02 19:36:36 -05:00
										 |  |  | 			F_ARRAY *literals = untag_array(array_nth(compiled_code,0)); | 
					
						
							| 
									
										
										
										
											2008-05-30 02:31:05 -04:00
										 |  |  | 			CELL relocation = array_nth(compiled_code,1); | 
					
						
							| 
									
										
										
										
											2008-01-16 15:45:04 -05:00
										 |  |  | 			F_ARRAY *labels = untag_array(array_nth(compiled_code,2)); | 
					
						
							|  |  |  | 			F_ARRAY *code = untag_array(array_nth(compiled_code,3)); | 
					
						
							| 
									
										
										
										
											2007-12-21 21:18:24 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			REGISTER_UNTAGGED(alist); | 
					
						
							|  |  |  | 			REGISTER_UNTAGGED(word); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			F_COMPILED *compiled = add_compiled_block( | 
					
						
							|  |  |  | 				WORD_TYPE, | 
					
						
							|  |  |  | 				code, | 
					
						
							|  |  |  | 				labels, | 
					
						
							| 
									
										
										
										
											2007-12-25 23:40:36 -05:00
										 |  |  | 				relocation, | 
					
						
							| 
									
										
										
										
											2007-12-21 21:18:24 -05:00
										 |  |  | 				literals); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			UNREGISTER_UNTAGGED(word); | 
					
						
							|  |  |  | 			UNREGISTER_UNTAGGED(alist); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-02 19:36:36 -05:00
										 |  |  | 			set_word_code(word,compiled); | 
					
						
							| 
									
										
										
										
											2007-12-21 21:18:24 -05:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-01-02 19:36:36 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		REGISTER_UNTAGGED(alist); | 
					
						
							|  |  |  | 		update_word_xt(word); | 
					
						
							|  |  |  | 		UNREGISTER_UNTAGGED(alist); | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-30 21:34:44 -05:00
										 |  |  | 	/* If there were any interned words in the set, we relocate all XT
 | 
					
						
							|  |  |  | 	references in the entire code heap. But if all the words are | 
					
						
							|  |  |  | 	uninterned, it is impossible that other words reference them, so we | 
					
						
							|  |  |  | 	only have to relocate the new words. This makes compile-call much | 
					
						
							|  |  |  | 	more efficient */ | 
					
						
							|  |  |  | 	if(rescan_code_heap) | 
					
						
							| 
									
										
										
										
											2007-12-26 17:14:33 -05:00
										 |  |  | 		iterate_code_heap(relocate_code_block); | 
					
						
							| 
									
										
										
										
											2007-12-30 21:34:44 -05:00
										 |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		for(i = 0; i < count; i++) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			F_ARRAY *pair = untag_array(array_nth(alist,i)); | 
					
						
							|  |  |  | 			F_WORD *word = untag_word(array_nth(pair,0)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			iterate_code_heap_step(word->code,relocate_code_block); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | } |