vm: factor out dispatch_signal_handler logic
							parent
							
								
									dc42365007
								
							
						
					
					
						commit
						6e4117035e
					
				| 
						 | 
				
			
			@ -18,6 +18,26 @@ callstack *factor_vm::allot_callstack(cell size)
 | 
			
		|||
	return stack;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void factor_vm::dispatch_signal_handler(cell *sp, cell *pc, cell newpc)
 | 
			
		||||
{
 | 
			
		||||
	/* 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. */
 | 
			
		||||
	cell offset = *sp % 16;
 | 
			
		||||
	if (offset != 0)
 | 
			
		||||
		fatal_error("fault in unaligned frame at", *pc);
 | 
			
		||||
 | 
			
		||||
	/* Nonleaf procedure */
 | 
			
		||||
	cell newsp = *sp - sizeof(cell);
 | 
			
		||||
	*sp = newsp;
 | 
			
		||||
	*(cell*)newsp = *pc;
 | 
			
		||||
	*pc = newpc;
 | 
			
		||||
	ctx->callstack_top = (stack_frame*)newsp;
 | 
			
		||||
 | 
			
		||||
	/* XXX handle leaf procedure */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* We ignore the two topmost frames, the 'callstack' primitive
 | 
			
		||||
frame itself, and the frame calling the 'callstack' primitive,
 | 
			
		||||
so that set-callstack doesn't get stuck in an infinite loop.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,25 +35,18 @@ void factor_vm::call_fault_handler(
 | 
			
		|||
	MACH_THREAD_STATE_TYPE *thread_state,
 | 
			
		||||
	MACH_FLOAT_STATE_TYPE *float_state)
 | 
			
		||||
{
 | 
			
		||||
	cell offset = MACH_STACK_POINTER(thread_state) % 16;
 | 
			
		||||
	if (offset != 0)
 | 
			
		||||
		fatal_error("fault in unaligned frame with offset", offset);
 | 
			
		||||
	MACH_STACK_POINTER(thread_state) -= sizeof(cell);
 | 
			
		||||
	*(cell*)MACH_STACK_POINTER(thread_state) = MACH_PROGRAM_COUNTER(thread_state);
 | 
			
		||||
	cell handler = 0;
 | 
			
		||||
 | 
			
		||||
	ctx->callstack_top = (stack_frame *)MACH_STACK_POINTER(thread_state);
 | 
			
		||||
 | 
			
		||||
	/* Now we point the program counter at the right handler function. */
 | 
			
		||||
	if(exception == EXC_BAD_ACCESS)
 | 
			
		||||
	{
 | 
			
		||||
		signal_fault_addr = MACH_EXC_STATE_FAULT(exc_state);
 | 
			
		||||
		MACH_PROGRAM_COUNTER(thread_state) = (cell)factor::memory_signal_handler_impl;
 | 
			
		||||
		handler = (cell)factor::memory_signal_handler_impl;
 | 
			
		||||
	}
 | 
			
		||||
	else if(exception == EXC_ARITHMETIC && code != MACH_EXC_INTEGER_DIV)
 | 
			
		||||
	{
 | 
			
		||||
		signal_fpu_status = fpu_status(mach_fpu_status(float_state));
 | 
			
		||||
		mach_clear_fpu_status(float_state);
 | 
			
		||||
		MACH_PROGRAM_COUNTER(thread_state) = (cell)factor::fp_signal_handler_impl;
 | 
			
		||||
		handler = (cell)factor::fp_signal_handler_impl;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -64,8 +57,16 @@ void factor_vm::call_fault_handler(
 | 
			
		|||
		default: signal_number = SIGABRT; break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		MACH_PROGRAM_COUNTER(thread_state) = (cell)factor::synchronous_signal_handler_impl;
 | 
			
		||||
		handler = (cell)factor::synchronous_signal_handler_impl;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	assert(handler != 0);
 | 
			
		||||
 | 
			
		||||
	dispatch_signal_handler(
 | 
			
		||||
		&MACH_STACK_POINTER(thread_state),
 | 
			
		||||
		&MACH_PROGRAM_COUNTER(thread_state),
 | 
			
		||||
		handler
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void call_fault_handler(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -138,15 +138,12 @@ void code_heap::unguard_safepoint()
 | 
			
		|||
 | 
			
		||||
void factor_vm::dispatch_signal(void *uap, void (handler)())
 | 
			
		||||
{
 | 
			
		||||
	cell sp = (cell)UAP_STACK_POINTER(uap);
 | 
			
		||||
	cell offset = sp % 16;
 | 
			
		||||
	if (offset != 0)
 | 
			
		||||
		fatal_error("fault in unaligned frame with offset", offset);
 | 
			
		||||
	UAP_STACK_POINTER(uap) = (UAP_STACK_POINTER_TYPE)(sp - sizeof(cell));
 | 
			
		||||
	*(cell*)(UAP_STACK_POINTER(uap)) = (cell)UAP_PROGRAM_COUNTER(uap);
 | 
			
		||||
	UAP_PROGRAM_COUNTER(uap) = (cell)FUNCTION_CODE_POINTER(handler);
 | 
			
		||||
	dispatch_signal_handler(
 | 
			
		||||
		&UAP_STACK_POINTER(uap),
 | 
			
		||||
		&UAP_PROGRAM_COUNTER(uap),
 | 
			
		||||
		FUNCTION_CODE_POINTER(handler)
 | 
			
		||||
	);
 | 
			
		||||
	UAP_SET_TOC_POINTER(uap, (cell)FUNCTION_TOC_POINTER(handler));
 | 
			
		||||
	ctx->callstack_top = (stack_frame *)UAP_STACK_POINTER(uap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void memory_signal_handler(int signal, siginfo_t *siginfo, void *uap)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										11
									
								
								vm/vm.hpp
								
								
								
								
							
							
						
						
									
										11
									
								
								vm/vm.hpp
								
								
								
								
							| 
						 | 
				
			
			@ -604,6 +604,17 @@ struct factor_vm
 | 
			
		|||
	void primitive_set_innermost_stack_frame_quot();
 | 
			
		||||
	void primitive_callstack_bounds();
 | 
			
		||||
	template<typename Iterator> void iterate_callstack(context *ctx, Iterator &iterator);
 | 
			
		||||
	void dispatch_signal_handler(cell *sp, cell *pc, cell newpc);
 | 
			
		||||
 | 
			
		||||
	template<typename CellA, typename CellB, typename CellC>
 | 
			
		||||
	void dispatch_signal_handler(CellA *sp, CellB *pc, CellC newpc)
 | 
			
		||||
	{
 | 
			
		||||
		dispatch_signal_handler(
 | 
			
		||||
			reinterpret_cast<cell*>(sp),
 | 
			
		||||
			reinterpret_cast<cell*>(pc),
 | 
			
		||||
			(cell)newpc
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// alien
 | 
			
		||||
	char *pinned_alien_offset(cell obj);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue