| 
									
										
										
										
											2007-10-02 17:53:05 -04:00
										 |  |  | #include "master.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* called before entry into Factor code. */ | 
					
						
							|  |  |  | F_FASTCALL void save_callstack_bottom(F_STACK_FRAME *callstack_bottom) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	stack_chain->callstack_bottom = callstack_bottom; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-06 23:01:41 -04:00
										 |  |  | F_FASTCALL __attribute__((noinline)) void save_callstack_top(F_STACK_FRAME *callstack_top) | 
					
						
							| 
									
										
										
										
											2007-10-06 22:52:55 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	stack_chain->callstack_top = callstack_top; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-05 17:30:10 -04:00
										 |  |  | void iterate_callstack(CELL top, CELL bottom, CALLSTACK_ITER iterator) | 
					
						
							| 
									
										
										
										
											2007-10-02 17:53:05 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	F_STACK_FRAME *frame = (F_STACK_FRAME *)bottom - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-05 04:17:38 -04:00
										 |  |  | 	while((CELL)frame >= top) | 
					
						
							| 
									
										
										
										
											2007-10-02 17:53:05 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2007-10-05 17:30:10 -04:00
										 |  |  | 		F_STACK_FRAME *next = frame_successor(frame); | 
					
						
							| 
									
										
										
										
											2007-10-02 17:53:05 -04:00
										 |  |  | 		iterator(frame); | 
					
						
							|  |  |  | 		frame = next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void iterate_callstack_object(F_CALLSTACK *stack, CALLSTACK_ITER iterator) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-05 17:54:06 -04:00
										 |  |  | 	CELL top = (CELL)FIRST_STACK_FRAME(stack); | 
					
						
							| 
									
										
										
										
											2007-10-02 17:53:05 -04:00
										 |  |  | 	CELL bottom = top + untag_fixnum_fast(stack->length); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-05 17:30:10 -04:00
										 |  |  | 	iterate_callstack(top,bottom,iterator); | 
					
						
							| 
									
										
										
										
											2007-10-02 17:53:05 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | F_CALLSTACK *allot_callstack(CELL size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	F_CALLSTACK *callstack = allot_object( | 
					
						
							|  |  |  | 		CALLSTACK_TYPE, | 
					
						
							|  |  |  | 		callstack_size(size)); | 
					
						
							|  |  |  | 	callstack->length = tag_fixnum(size); | 
					
						
							|  |  |  | 	return callstack; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-06 23:26:43 -04:00
										 |  |  | F_STACK_FRAME *fix_callstack_top(F_STACK_FRAME *top, F_STACK_FRAME *bottom) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	F_STACK_FRAME *frame = bottom - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while(frame >= top) | 
					
						
							|  |  |  | 		frame = frame_successor(frame); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return frame + 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-02 17:53:05 -04:00
										 |  |  | /* We ignore the topmost frame, the one calling 'callstack',
 | 
					
						
							|  |  |  | so that set-callstack doesn't get stuck in an infinite loop. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This means that if 'callstack' is called in tail position, we | 
					
						
							|  |  |  | will have popped a necessary frame... however this word is only | 
					
						
							|  |  |  | called by continuation implementation, and user code shouldn't | 
					
						
							|  |  |  | be calling it at all, so we leave it as it is for now. */ | 
					
						
							|  |  |  | F_STACK_FRAME *capture_start(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	F_STACK_FRAME *frame = stack_chain->callstack_bottom - 1; | 
					
						
							|  |  |  | 	while(frame >= stack_chain->callstack_top | 
					
						
							| 
									
										
										
										
											2007-10-05 17:30:10 -04:00
										 |  |  | 		&& frame_successor(frame) >= stack_chain->callstack_top) | 
					
						
							| 
									
										
										
										
											2007-10-02 17:53:05 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2007-10-05 17:30:10 -04:00
										 |  |  | 		frame = frame_successor(frame); | 
					
						
							| 
									
										
										
										
											2007-10-02 17:53:05 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return frame + 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DEFINE_PRIMITIVE(callstack) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	F_STACK_FRAME *top = capture_start(); | 
					
						
							|  |  |  | 	F_STACK_FRAME *bottom = stack_chain->callstack_bottom; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	F_FIXNUM size = (CELL)bottom - (CELL)top; | 
					
						
							|  |  |  | 	if(size < 0) | 
					
						
							|  |  |  | 		size = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	F_CALLSTACK *callstack = allot_callstack(size); | 
					
						
							|  |  |  | 	memcpy(FIRST_STACK_FRAME(callstack),top,size); | 
					
						
							|  |  |  | 	dpush(tag_object(callstack)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DEFINE_PRIMITIVE(set_callstack) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	F_CALLSTACK *stack = untag_callstack(dpop()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	set_callstack(stack_chain->callstack_bottom, | 
					
						
							|  |  |  | 		FIRST_STACK_FRAME(stack), | 
					
						
							|  |  |  | 		untag_fixnum_fast(stack->length), | 
					
						
							|  |  |  | 		memcpy); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* We cannot return here ... */ | 
					
						
							|  |  |  | 	critical_error("Bug in set_callstack()",0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-28 04:33:36 -04:00
										 |  |  | F_COMPILED *frame_code(F_STACK_FRAME *frame) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return (F_COMPILED *)frame->xt - 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-02 17:53:05 -04:00
										 |  |  | CELL frame_type(F_STACK_FRAME *frame) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-28 04:33:36 -04:00
										 |  |  | 	return frame_code(frame)->type; | 
					
						
							| 
									
										
										
										
											2007-10-02 17:53:05 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CELL frame_executing(F_STACK_FRAME *frame) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-28 04:33:36 -04:00
										 |  |  | 	F_COMPILED *compiled = frame_code(frame); | 
					
						
							| 
									
										
										
										
											2007-10-02 17:53:05 -04:00
										 |  |  | 	CELL code_start = (CELL)(compiled + 1); | 
					
						
							| 
									
										
										
										
											2008-05-30 02:31:05 -04:00
										 |  |  | 	CELL literal_start = code_start + compiled->code_length; | 
					
						
							| 
									
										
										
										
											2007-10-02 17:53:05 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return get(literal_start); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-05 17:30:10 -04:00
										 |  |  | F_STACK_FRAME *frame_successor(F_STACK_FRAME *frame) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return (F_STACK_FRAME *)((CELL)frame - frame->size); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-03 16:56:49 -04:00
										 |  |  | CELL frame_scan(F_STACK_FRAME *frame) | 
					
						
							| 
									
										
										
										
											2007-10-02 17:53:05 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	if(frame_type(frame) == QUOTATION_TYPE) | 
					
						
							| 
									
										
										
										
											2007-12-30 16:54:01 -05:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		CELL quot = frame_executing(frame); | 
					
						
							|  |  |  | 		if(quot == F) | 
					
						
							|  |  |  | 			return F; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			XT return_addr = FRAME_RETURN_ADDRESS(frame); | 
					
						
							|  |  |  | 			XT quot_xt = (XT)(frame_code(frame) + 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return tag_fixnum(quot_code_offset_to_scan( | 
					
						
							|  |  |  | 				quot,(CELL)(return_addr - quot_xt))); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-10-02 17:53:05 -04:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2007-10-03 16:56:49 -04:00
										 |  |  | 		return F; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2007-10-02 17:53:05 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-05 17:54:06 -04:00
										 |  |  | /* C doesn't have closures... */ | 
					
						
							|  |  |  | static CELL frame_count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void count_stack_frame(F_STACK_FRAME *frame) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	frame_count += 2;  | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static CELL frame_index; | 
					
						
							|  |  |  | static F_ARRAY *array; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-03 16:56:49 -04:00
										 |  |  | void stack_frame_to_array(F_STACK_FRAME *frame) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-02 17:53:05 -04:00
										 |  |  | 	set_array_nth(array,frame_index++,frame_executing(frame)); | 
					
						
							| 
									
										
										
										
											2007-10-03 16:56:49 -04:00
										 |  |  | 	set_array_nth(array,frame_index++,frame_scan(frame)); | 
					
						
							| 
									
										
										
										
											2007-10-02 17:53:05 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DEFINE_PRIMITIVE(callstack_to_array) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	F_CALLSTACK *stack = untag_callstack(dpop()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	frame_count = 0; | 
					
						
							|  |  |  | 	iterate_callstack_object(stack,count_stack_frame); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	REGISTER_UNTAGGED(stack); | 
					
						
							|  |  |  | 	array = allot_array_internal(ARRAY_TYPE,frame_count); | 
					
						
							|  |  |  | 	UNREGISTER_UNTAGGED(stack); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	frame_index = 0; | 
					
						
							|  |  |  | 	iterate_callstack_object(stack,stack_frame_to_array); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dpush(tag_object(array)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2007-10-03 16:56:49 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-03 18:53:43 -04:00
										 |  |  | F_STACK_FRAME *innermost_stack_frame(F_CALLSTACK *callstack) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-05 17:54:06 -04:00
										 |  |  | 	F_STACK_FRAME *top = FIRST_STACK_FRAME(callstack); | 
					
						
							|  |  |  | 	CELL bottom = (CELL)top + untag_fixnum_fast(callstack->length); | 
					
						
							| 
									
										
										
										
											2007-10-03 18:53:43 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	F_STACK_FRAME *frame = (F_STACK_FRAME *)bottom - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-05 17:54:06 -04:00
										 |  |  | 	while(frame >= top && frame_successor(frame) >= top) | 
					
						
							| 
									
										
										
										
											2007-10-05 17:30:10 -04:00
										 |  |  | 		frame = frame_successor(frame); | 
					
						
							| 
									
										
										
										
											2007-10-03 18:53:43 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return frame; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-03 16:56:49 -04:00
										 |  |  | /* Some primitives implementing a limited form of callstack mutation.
 | 
					
						
							|  |  |  | Used by the single stepper. */ | 
					
						
							|  |  |  | DEFINE_PRIMITIVE(innermost_stack_frame_quot) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-03 18:53:43 -04:00
										 |  |  | 	F_STACK_FRAME *inner = innermost_stack_frame( | 
					
						
							| 
									
										
										
										
											2007-10-03 16:56:49 -04:00
										 |  |  | 		untag_callstack(dpop())); | 
					
						
							|  |  |  | 	type_check(QUOTATION_TYPE,frame_executing(inner)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dpush(frame_executing(inner)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DEFINE_PRIMITIVE(innermost_stack_frame_scan) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-03 18:53:43 -04:00
										 |  |  | 	F_STACK_FRAME *inner = innermost_stack_frame( | 
					
						
							| 
									
										
										
										
											2007-10-03 16:56:49 -04:00
										 |  |  | 		untag_callstack(dpop())); | 
					
						
							|  |  |  | 	type_check(QUOTATION_TYPE,frame_executing(inner)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dpush(frame_scan(inner)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DEFINE_PRIMITIVE(set_innermost_stack_frame_quot) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-10-03 20:49:17 -04:00
										 |  |  | 	F_CALLSTACK *callstack = untag_callstack(dpop()); | 
					
						
							| 
									
										
										
										
											2007-10-03 16:56:49 -04:00
										 |  |  | 	F_QUOTATION *quot = untag_quotation(dpop()); | 
					
						
							| 
									
										
										
										
											2007-10-03 20:49:17 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	REGISTER_UNTAGGED(callstack); | 
					
						
							| 
									
										
										
										
											2007-10-03 16:56:49 -04:00
										 |  |  | 	REGISTER_UNTAGGED(quot); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-09 01:33:40 -05:00
										 |  |  | 	jit_compile(tag_object(quot),true); | 
					
						
							| 
									
										
										
										
											2007-10-03 16:56:49 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	UNREGISTER_UNTAGGED(quot); | 
					
						
							| 
									
										
										
										
											2007-10-03 20:49:17 -04:00
										 |  |  | 	UNREGISTER_UNTAGGED(callstack); | 
					
						
							| 
									
										
										
										
											2007-10-03 16:56:49 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-03 20:49:17 -04:00
										 |  |  | 	F_STACK_FRAME *inner = innermost_stack_frame(callstack); | 
					
						
							| 
									
										
										
										
											2007-10-03 16:56:49 -04:00
										 |  |  | 	type_check(QUOTATION_TYPE,frame_executing(inner)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-05 17:30:10 -04:00
										 |  |  | 	CELL offset = FRAME_RETURN_ADDRESS(inner) - inner->xt; | 
					
						
							| 
									
										
										
										
											2007-10-03 16:56:49 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	inner->xt = quot->xt; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-05 17:30:10 -04:00
										 |  |  | 	FRAME_RETURN_ADDRESS(inner) = quot->xt + offset; | 
					
						
							| 
									
										
										
										
											2007-10-03 16:56:49 -04:00
										 |  |  | } |