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 caresdb4
parent
a6b80f3efa
commit
5d59faa7d1
|
@ -1 +1,2 @@
|
|||
PLAF_DLL_OBJS += vm/cpu-x86.o
|
||||
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
PLAF_DLL_OBJS += vm/cpu-x86.o
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
13
vm/vm.hpp
13
vm/vm.hpp
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue