vm: move dispatch_signal_handler to cpu-x86.cpp

The new signal handler dispatch is logic is CISC-centric; defer fixing it until we find someone who cares
db4
Joe Groff 2011-10-26 16:22:42 -07:00
parent a6b80f3efa
commit 5d59faa7d1
8 changed files with 83 additions and 88 deletions

View File

@ -1 +1,2 @@
PLAF_DLL_OBJS += vm/cpu-x86.o

View File

@ -1 +1,2 @@
PLAF_DLL_OBJS += vm/cpu-x86.o

View File

@ -18,75 +18,6 @@ callstack *factor_vm::allot_callstack(cell size)
return stack;
}
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)
{
/* Fault came from foreign code, a callstack overflow, or we would probably
overflow if we tried the resumable handler. We can't resume, so 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. */
signal_resumable = false;
stack_frame *frame = ctx->callstack_bottom - 1;
while((cell)frame >= *sp
&& frame >= ctx->callstack_top
&& (cell)frame >= ctx->callstack_seg->start + stack_reserved)
{
frame = frame_successor(frame);
}
// XXX FRAME_RETURN_ADDRESS
cell newsp = (cell)(frame+1);
*sp = newsp;
ctx->callstack_top = (stack_frame*)newsp;
*pc = handler;
} else {
signal_resumable = true;
// Fault came from Factor, and we've got a good callstack. Route the signal
// handler through the resumable signal handler subprimitive.
cell offset = *sp % 16;
signal_handler_addr = handler;
tagged<word> handler_word = tagged<word>(special_objects[SIGNAL_HANDLER_WORD]);
/* XXX horribly x86-centric */
/* 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))
{
// Make a fake frame for the leaf procedure
code_block *leaf_block = code->code_block_for_address(*pc);
assert(leaf_block != NULL);
// XXX get platform-appropriate stack frame size
cell newsp = *sp - 32;
*(cell*)(newsp + 32 - sizeof(cell)) = 32;
*(cell*)(newsp + 32 - 2*sizeof(cell)) = (cell)leaf_block->entry_point();
*(cell*) newsp = *pc;
*sp = newsp;
handler_word = tagged<word>(special_objects[LEAF_SIGNAL_HANDLER_WORD]);
}
else
{
fatal_error("Invalid stack frame during signal handler", *sp);
}
*pc = (cell)handler_word->code->entry_point();
}
}
/* 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.

72
vm/cpu-x86.cpp Normal file
View File

@ -0,0 +1,72 @@
#include "master.hpp"
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)
{
/* Fault came from foreign code, a callstack overflow, or we would probably
overflow if we tried the resumable handler. We can't resume, so 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. */
signal_resumable = false;
stack_frame *frame = ctx->callstack_bottom - 1;
while((cell)frame >= *sp
&& frame >= ctx->callstack_top
&& (cell)frame >= ctx->callstack_seg->start + stack_reserved)
{
frame = frame_successor(frame);
}
cell newsp = (cell)(frame+1);
*sp = newsp;
ctx->callstack_top = (stack_frame*)newsp;
*pc = handler;
} else {
signal_resumable = true;
// Fault came from Factor, and we've got a good callstack. Route the signal
// handler through the resumable signal handler subprimitive.
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))
{
// Make a fake frame for the leaf procedure
code_block *leaf_block = code->code_block_for_address(*pc);
assert(leaf_block != NULL);
cell newsp = *sp - 32;
*(cell*)(newsp + 32 - sizeof(cell)) = 32;
*(cell*)(newsp + 32 - 2*sizeof(cell)) = (cell)leaf_block->entry_point();
*(cell*) newsp = *pc;
*sp = newsp;
handler_word = tagged<word>(special_objects[LEAF_SIGNAL_HANDLER_WORD]);
}
else
{
fatal_error("Invalid stack frame during signal handler", *sp);
}
*pc = (cell)handler_word->code->entry_point();
}
}
}

View File

@ -63,9 +63,9 @@ void factor_vm::call_fault_handler(
assert(handler != 0);
dispatch_signal_handler(
&MACH_STACK_POINTER(thread_state),
&MACH_PROGRAM_COUNTER(thread_state),
handler
(cell*)&MACH_STACK_POINTER(thread_state),
(cell*)&MACH_PROGRAM_COUNTER(thread_state),
(cell)handler
);
}

View File

@ -18,8 +18,7 @@ void register_vm_with_thread(factor_vm *vm)
factor_vm *current_vm_p()
{
factor_vm *vm = (factor_vm*)pthread_getspecific(current_vm_tls_key);
return vm;
return (factor_vm*)pthread_getspecific(current_vm_tls_key);
}
}

View File

@ -139,9 +139,9 @@ void code_heap::unguard_safepoint()
void factor_vm::dispatch_signal(void *uap, void (handler)())
{
dispatch_signal_handler(
&UAP_STACK_POINTER(uap),
&UAP_PROGRAM_COUNTER(uap),
FUNCTION_CODE_POINTER(handler)
(cell*)&UAP_STACK_POINTER(uap),
(cell*)&UAP_PROGRAM_COUNTER(uap),
(cell)FUNCTION_CODE_POINTER(handler)
);
UAP_SET_TOC_POINTER(uap, (cell)FUNCTION_TOC_POINTER(handler));
}

View File

@ -616,18 +616,9 @@ 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);
void dispatch_signal_handler_from_leaf(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
);
}
// cpu-*
void dispatch_signal_handler(cell *sp, cell *pc, cell newpc);
// alien
char *pinned_alien_offset(cell obj);