2011-10-26 19:22:42 -04:00
|
|
|
#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)
|
|
|
|
{
|
2011-10-27 23:24:51 -04:00
|
|
|
/* Fault came from foreign code or a callstack overflow, or we don't
|
|
|
|
have enough callstack room to try the resumable handler. Cut the
|
2011-10-26 19:22:42 -04:00
|
|
|
callstack down to the shallowest Factor stack frame that leaves room for
|
2011-10-27 23:24:51 -04:00
|
|
|
the signal handler to do its thing, and launch the handler without going
|
2011-10-26 19:22:42 -04:00
|
|
|
through the resumable subprimitive. */
|
|
|
|
signal_resumable = false;
|
2011-12-06 20:53:52 -05:00
|
|
|
void *frame_top = (void*)ctx->callstack_top;
|
2011-10-26 19:22:42 -04:00
|
|
|
|
2011-12-06 20:53:52 -05:00
|
|
|
while(frame_top < ctx->callstack_bottom
|
|
|
|
&& (cell)frame_top < ctx->callstack_seg->start + stack_reserved)
|
2011-10-26 19:22:42 -04:00
|
|
|
{
|
2011-12-06 20:53:52 -05:00
|
|
|
frame_top = frame_predecessor(frame_top);
|
2011-10-26 19:22:42 -04:00
|
|
|
}
|
|
|
|
|
2011-12-06 20:53:52 -05:00
|
|
|
*sp = (cell)frame_top;
|
|
|
|
ctx->callstack_top = frame_top;
|
2011-10-26 19:22:42 -04:00
|
|
|
*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
|
2011-12-13 22:36:05 -05:00
|
|
|
FACTOR_ASSERT(code->code_block_for_address(*pc) != NULL);
|
2011-10-26 19:22:42 -04:00
|
|
|
|
2011-11-25 21:58:21 -05:00
|
|
|
cell newsp = *sp - LEAF_FRAME_SIZE;
|
2011-12-13 22:36:05 -05:00
|
|
|
*(cell*)newsp = *pc;
|
2011-10-26 19:22:42 -04:00
|
|
|
*sp = newsp;
|
|
|
|
handler_word = tagged<word>(special_objects[LEAF_SIGNAL_HANDLER_WORD]);
|
|
|
|
}
|
|
|
|
else
|
2011-11-17 23:42:30 -05:00
|
|
|
FACTOR_ASSERT(false);
|
2011-10-26 19:22:42 -04:00
|
|
|
|
2011-11-10 19:00:47 -05:00
|
|
|
*pc = (cell)handler_word->entry_point;
|
2011-10-26 19:22:42 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|