| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | #include "master.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  | namespace factor { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-13 23:42:44 -05:00
										 |  |  | /* Allocates memory (allot) */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  | callstack* factor_vm::allot_callstack(cell size) { | 
					
						
							|  |  |  |   callstack* stack = allot<callstack>(callstack_object_size(size)); | 
					
						
							|  |  |  |   stack->length = tag_fixnum(size); | 
					
						
							|  |  |  |   return stack; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-15 07:20:09 -05:00
										 |  |  | /* We ignore the two topmost frames, the 'callstack' primitive
 | 
					
						
							|  |  |  | frame itself, and the frame calling the 'callstack' primitive, | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 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. */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  | void* factor_vm::second_from_top_stack_frame(context* ctx) { | 
					
						
							|  |  |  |   void* frame_top = ctx->callstack_top; | 
					
						
							|  |  |  |   for (cell i = 0; i < 2; ++i) { | 
					
						
							|  |  |  |     void* pred = frame_predecessor(frame_top); | 
					
						
							|  |  |  |     if (pred >= ctx->callstack_bottom) | 
					
						
							|  |  |  |       return frame_top; | 
					
						
							|  |  |  |     frame_top = pred; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return frame_top; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-13 23:42:44 -05:00
										 |  |  | /* Allocates memory (allot_callstack) */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  | cell factor_vm::capture_callstack(context* ctx) { | 
					
						
							|  |  |  |   void* top = second_from_top_stack_frame(ctx); | 
					
						
							|  |  |  |   void* bottom = ctx->callstack_bottom; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |   fixnum size = std::max((fixnum)0, (fixnum)bottom - (fixnum)top); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  |   callstack* stack = allot_callstack(size); | 
					
						
							|  |  |  |   memcpy(stack->top(), top, size); | 
					
						
							|  |  |  |   return tag<callstack>(stack); | 
					
						
							| 
									
										
										
										
											2010-03-29 20:40:17 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-13 23:42:44 -05:00
										 |  |  | /* Allocates memory (capture_callstack) */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  | void factor_vm::primitive_callstack() { ctx->push(capture_callstack(ctx)); } | 
					
						
							| 
									
										
										
										
											2010-03-29 20:40:17 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-13 23:42:44 -05:00
										 |  |  | /* Allocates memory (capture_callstack) */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  | void factor_vm::primitive_callstack_for() { | 
					
						
							|  |  |  |   context* other_ctx = (context*)pinned_alien_offset(ctx->peek()); | 
					
						
							|  |  |  |   ctx->replace(capture_callstack(other_ctx)); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  | void* factor_vm::frame_predecessor(void* frame_top) { | 
					
						
							|  |  |  |   void* addr = frame_return_address((void*)frame_top); | 
					
						
							|  |  |  |   FACTOR_ASSERT(addr != 0); | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |   code_block* owner = code->code_block_for_address((cell)addr); | 
					
						
							|  |  |  |   cell frame_size = owner->stack_frame_size_for_address((cell)addr); | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  |   return (void*)((char*)frame_top + frame_size); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-13 01:58:54 -04:00
										 |  |  | struct stack_frame_accumulator { | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  |   factor_vm* parent; | 
					
						
							|  |  |  |   growable_array frames; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-13 23:42:44 -05:00
										 |  |  |   /* Allocates memory (frames is a growable_array, constructor allocates) */ | 
					
						
							| 
									
										
										
										
											2013-05-12 23:20:43 -04:00
										 |  |  |   explicit stack_frame_accumulator(factor_vm* parent) | 
					
						
							|  |  |  |       : parent(parent), frames(parent) {} | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-13 23:42:44 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Allocates memory (frames.add()) */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  |   void operator()(void* frame_top, cell frame_size, code_block* owner, | 
					
						
							|  |  |  |                   void* addr) { | 
					
						
							|  |  |  |     data_root<object> executing_quot(owner->owner_quot(), parent); | 
					
						
							|  |  |  |     data_root<object> executing(owner->owner, parent); | 
					
						
							|  |  |  |     data_root<object> scan(owner->scan(parent, addr), parent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     frames.add(executing.value()); | 
					
						
							|  |  |  |     frames.add(executing_quot.value()); | 
					
						
							|  |  |  |     frames.add(scan.value()); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-05-13 01:58:54 -04:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  | struct stack_frame_in_array { | 
					
						
							|  |  |  |   cell cells[3]; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2011-12-06 17:51:41 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  | void factor_vm::primitive_callstack_to_array() { | 
					
						
							|  |  |  |   data_root<callstack> callstack(ctx->peek(), this); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  |   stack_frame_accumulator accum(this); | 
					
						
							|  |  |  |   iterate_callstack_object(callstack.untagged(), accum); | 
					
						
							| 
									
										
										
										
											2011-12-06 17:51:41 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  |   /* The callstack iterator visits frames in reverse order (top to bottom) */ | 
					
						
							|  |  |  |   std::reverse((stack_frame_in_array*)accum.frames.elements->data(), | 
					
						
							|  |  |  |                (stack_frame_in_array*)(accum.frames.elements->data() + | 
					
						
							|  |  |  |                                        accum.frames.count)); | 
					
						
							| 
									
										
										
										
											2011-12-06 17:51:41 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  |   accum.frames.trim(); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  |   ctx->replace(accum.frames.elements.value()); | 
					
						
							| 
									
										
										
										
											2011-12-06 17:51:41 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Some primitives implementing a limited form of callstack mutation.
 | 
					
						
							|  |  |  | Used by the single stepper. */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  | void factor_vm::primitive_innermost_stack_frame_executing() { | 
					
						
							|  |  |  |   callstack* stack = untag_check<callstack>(ctx->peek()); | 
					
						
							|  |  |  |   void* frame = stack->top(); | 
					
						
							|  |  |  |   void* addr = frame_return_address(frame); | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |   ctx->replace(code->code_block_for_address((cell)addr)->owner_quot()); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  | void factor_vm::primitive_innermost_stack_frame_scan() { | 
					
						
							|  |  |  |   callstack* stack = untag_check<callstack>(ctx->peek()); | 
					
						
							|  |  |  |   void* frame = stack->top(); | 
					
						
							|  |  |  |   void* addr = frame_return_address(frame); | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |   ctx->replace(code->code_block_for_address((cell)addr)->scan(this, addr)); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-13 23:42:44 -05:00
										 |  |  | /* Allocates memory (jit_compile_quot) */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  | void factor_vm::primitive_set_innermost_stack_frame_quot() { | 
					
						
							|  |  |  |   data_root<callstack> stack(ctx->pop(), this); | 
					
						
							|  |  |  |   data_root<quotation> quot(ctx->pop(), this); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  |   stack.untag_check(this); | 
					
						
							|  |  |  |   quot.untag_check(this); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  |   jit_compile_quot(quot.value(), true); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  |   void* inner = stack->top(); | 
					
						
							|  |  |  |   void* addr = frame_return_address(inner); | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |   code_block* block = code->code_block_for_address((cell)addr); | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  |   cell offset = block->offset(addr); | 
					
						
							|  |  |  |   set_frame_return_address(inner, (char*)quot->entry_point + offset); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-05-04 02:00:30 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-13 23:42:44 -05:00
										 |  |  | /* Allocates memory (allot_alien) */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:47:34 -04:00
										 |  |  | void factor_vm::primitive_callstack_bounds() { | 
					
						
							|  |  |  |   ctx->push(allot_alien((void*)ctx->callstack_seg->start)); | 
					
						
							|  |  |  |   ctx->push(allot_alien((void*)ctx->callstack_seg->end)); | 
					
						
							| 
									
										
										
										
											2010-04-19 21:08:15 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | } |