]> gitweb.factorcode.org Git - factor.git/blob - vm/cpu-x86.cpp
d3a7bf0b15d740c11a98cc8eb5118cbbccf1b910
[factor.git] / vm / cpu-x86.cpp
1 #include "master.hpp"
2
3 namespace factor
4 {
5
6 void factor_vm::dispatch_signal_handler(cell *sp, cell *pc, cell handler)
7 {
8         if (!code->seg->in_segment_p(*pc) || *sp < ctx->callstack_seg->start + stack_reserved)
9         {
10                 /* Fault came from foreign code or a callstack overflow, or we don't
11                 have enough callstack room to try the resumable handler. Cut the
12                 callstack down to the shallowest Factor stack frame that leaves room for
13                 the signal handler to do its thing, and launch the handler without going
14                 through the resumable subprimitive. */
15                 signal_resumable = false;
16                 stack_frame *frame = ctx->bottom_frame();
17
18                 while((cell)frame >= *sp
19                         && frame >= ctx->callstack_top
20                         && (cell)frame >= ctx->callstack_seg->start + stack_reserved)
21                 {
22                         frame = frame_successor(frame);
23                 }
24
25                 cell newsp = (cell)(frame+1);
26                 *sp = newsp;
27                 ctx->callstack_top = (stack_frame*)newsp;
28                 *pc = handler;
29         } else {
30                 signal_resumable = true;
31                 // Fault came from Factor, and we've got a good callstack. Route the signal
32                 // handler through the resumable signal handler subprimitive.
33                 cell offset = *sp % 16;
34
35                 signal_handler_addr = handler;
36                 tagged<word> handler_word = tagged<word>(special_objects[SIGNAL_HANDLER_WORD]);
37
38                 /* True stack frames are always 16-byte aligned. Leaf procedures
39                 that don't create a stack frame will be out of alignment by sizeof(cell)
40                 bytes. */
41                 /* On architectures with a link register we would have to check for leafness
42                 by matching the PC to a word. We should also use FRAME_RETURN_ADDRESS instead
43                 of assuming the stack pointer is the right place to put the resume address. */
44                 if (offset == 0)
45                 {
46                         cell newsp = *sp - sizeof(cell);
47                         *sp = newsp;
48                         *(cell*)newsp = *pc;
49                 }
50                 else if (offset == 16 - sizeof(cell))
51                 {
52                         // Make a fake frame for the leaf procedure
53                         code_block *leaf_block = code->code_block_for_address(*pc);
54                         assert(leaf_block != NULL);
55
56                         cell newsp = *sp - 4*sizeof(cell);
57                         *(cell*)(newsp + 3*sizeof(cell)) = 4*sizeof(cell);
58                         *(cell*)(newsp + 2*sizeof(cell)) = (cell)leaf_block->entry_point();
59                         *(cell*) newsp                   = *pc;
60                         *sp = newsp;
61                         handler_word = tagged<word>(special_objects[LEAF_SIGNAL_HANDLER_WORD]);
62                 }
63                 else
64                         assert(false);
65
66                 *pc = (cell)handler_word->code->entry_point();
67         }
68 }
69
70 }