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