vm: factor out dispatch_signal_handler logic

db4
Joe Groff 2011-10-20 21:30:40 -07:00
parent dc42365007
commit 6e4117035e
4 changed files with 48 additions and 19 deletions

View File

@ -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.

View File

@ -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(

View File

@ -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)

View File

@ -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);