| 
									
										
										
										
											2011-10-26 19:22:42 -04:00
										 |  |  | #include "master.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-11 21:55:50 -04:00
										 |  |  | namespace factor { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void factor_vm::dispatch_signal_handler(cell* sp, cell* pc, cell handler) { | 
					
						
							|  |  |  |   if (!code->seg->in_segment_p(*pc) || | 
					
						
							|  |  |  |       *sp < ctx->callstack_seg->start + stack_reserved) { | 
					
						
							| 
									
										
										
										
											2014-06-21 19:24:43 -04:00
										 |  |  |     /* Fault came from the VM, foreign code, a callstack overflow, or
 | 
					
						
							|  |  |  |        we don't have enough callstack room to try the resumable | 
					
						
							|  |  |  |        handler. Cut the callstack down to the shallowest Factor stack | 
					
						
							|  |  |  |        frame that leaves room for the signal handler to do its thing, | 
					
						
							|  |  |  |        and launch the handler without going through the resumable | 
					
						
							|  |  |  |        subprimitive. */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:55:50 -04:00
										 |  |  |     signal_resumable = false; | 
					
						
							|  |  |  |     void* frame_top = (void*)ctx->callstack_top; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (frame_top < ctx->callstack_bottom && | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |            (cell)frame_top < ctx->callstack_seg->start + stack_reserved) { | 
					
						
							| 
									
										
										
										
											2013-05-11 21:55:50 -04:00
										 |  |  |       frame_top = frame_predecessor(frame_top); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |     *sp = (cell)frame_top; | 
					
						
							| 
									
										
										
										
											2013-05-11 21:55:50 -04:00
										 |  |  |     ctx->callstack_top = frame_top; | 
					
						
							|  |  |  |     *pc = handler; | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     signal_resumable = true; | 
					
						
							| 
									
										
										
										
											2014-06-21 19:24:43 -04:00
										 |  |  |     /* Fault came from Factor, and we've got a good callstack. Route
 | 
					
						
							|  |  |  |        the signal handler through the resumable signal handler subprimitive. */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:55:50 -04:00
										 |  |  |     cell offset = *sp % 16; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     signal_handler_addr = handler; | 
					
						
							|  |  |  |     tagged<word> handler_word = | 
					
						
							|  |  |  |         tagged<word>(special_objects[SIGNAL_HANDLER_WORD]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* True stack frames are always 16-byte aligned. Leaf procedures
 | 
					
						
							|  |  |  |        that don't create a stack frame will be out of alignment by sizeof(cell) | 
					
						
							|  |  |  |        bytes. */ | 
					
						
							|  |  |  |     /* On architectures with a link register we would have to check for leafness
 | 
					
						
							|  |  |  |        by matching the PC to a word. We should also use FRAME_RETURN_ADDRESS | 
					
						
							|  |  |  |        instead of assuming the stack pointer is the right place to put the | 
					
						
							|  |  |  |        resume address. */ | 
					
						
							|  |  |  |     if (offset == 0) { | 
					
						
							|  |  |  |       cell newsp = *sp - sizeof(cell); | 
					
						
							|  |  |  |       *sp = newsp; | 
					
						
							|  |  |  |       *(cell*)newsp = *pc; | 
					
						
							|  |  |  |     } else if (offset == 16 - sizeof(cell)) { | 
					
						
							| 
									
										
										
										
											2014-06-21 19:24:43 -04:00
										 |  |  |       /* Make a fake frame for the leaf procedure */ | 
					
						
							| 
									
										
										
										
											2013-05-11 21:55:50 -04:00
										 |  |  |       FACTOR_ASSERT(code->code_block_for_address(*pc) != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       cell newsp = *sp - LEAF_FRAME_SIZE; | 
					
						
							|  |  |  |       *(cell*)newsp = *pc; | 
					
						
							|  |  |  |       *sp = newsp; | 
					
						
							|  |  |  |       handler_word = tagged<word>(special_objects[LEAF_SIGNAL_HANDLER_WORD]); | 
					
						
							|  |  |  |     } else | 
					
						
							|  |  |  |       FACTOR_ASSERT(false); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-13 00:53:47 -04:00
										 |  |  |     *pc = (cell)handler_word->entry_point; | 
					
						
							| 
									
										
										
										
											2013-05-11 21:55:50 -04:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-07-23 05:07:49 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Poking with the stack pointer, which the above code does, means
 | 
					
						
							|  |  |  |      that pointers to stack-allocated objects will become | 
					
						
							|  |  |  |      corrupted. Therefore the root vectors needs to be cleared because | 
					
						
							|  |  |  |      their pointers to stack variables are now garbage. */ | 
					
						
							|  |  |  |   data_roots.clear(); | 
					
						
							|  |  |  |   code_roots.clear(); | 
					
						
							| 
									
										
										
										
											2011-10-26 19:22:42 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |