]> gitweb.factorcode.org Git - factor.git/blob - vm/cpu-x86.cpp
webapps.wiki: adding search bar
[factor.git] / vm / cpu-x86.cpp
1 #include "master.hpp"
2
3 namespace factor {
4
5 void factor_vm::dispatch_non_resumable_signal(cell* sp, cell* pc,
6                                               cell handler,
7                                               cell limit) {
8
9   // Fault came from the VM or foreign code. We don't try to fix the
10   // call stack from *sp and instead use the last saved "good value"
11   // which we get from ctx->callstack_top. Then launch the handler
12   // without going through the resumable subprimitive.
13   cell frame_top = ctx->callstack_top;
14   cell seg_start = ctx->callstack_seg->start;
15
16   if (frame_top < seg_start) {
17     // The saved callstack pointer is outside the callstack
18     // segment. That means that we need to carefully cut off one frame
19     // first which hopefully should put the pointer within the
20     // callstack's bounds.
21     code_block *block = code->code_block_for_address(*pc);
22     cell frame_size = block->stack_frame_size_for_address(*pc);
23     frame_top += frame_size;
24   }
25
26   // Cut the callstack down to the shallowest Factor stack
27   // frame that leaves room for the signal handler to do its thing,
28   // and launch the handler without going through the resumable
29   // subprimitive.
30   FACTOR_ASSERT(seg_start <= frame_top);
31   while (frame_top < ctx->callstack_bottom && frame_top < limit) {
32     frame_top = code->frame_predecessor(frame_top);
33   }
34   ctx->callstack_top = frame_top;
35   *sp = frame_top;
36   *pc = handler;
37 }
38
39 void factor_vm::dispatch_resumable_signal(cell* sp, cell* pc, cell handler) {
40
41   // Fault came from Factor, and we've got a good callstack. Route the
42   // signal handler through the resumable signal handler
43   // subprimitive.
44
45   cell offset = *sp % 16;
46
47   signal_handler_addr = handler;
48
49   // True stack frames are always 16-byte aligned. Leaf procedures
50   // that don't create a stack frame will be out of alignment by
51   // sizeof(cell) bytes.
52   // On architectures with a link register we would have to check for
53   // leafness by matching the PC to a word. We should also use
54   // FRAME_RETURN_ADDRESS instead of assuming the stack pointer is the
55   // right place to put the resume address.
56   cell index = 0;
57   cell delta = 0;
58   if (offset == 0) {
59     delta = sizeof(cell);
60     index = SIGNAL_HANDLER_WORD;
61   } else if (offset == 16 - sizeof(cell)) {
62     // Make a fake frame for the leaf procedure
63     FACTOR_ASSERT(code->code_block_for_address(*pc) != NULL);
64     delta = LEAF_FRAME_SIZE;
65     index = LEAF_SIGNAL_HANDLER_WORD;
66   } else {
67     FACTOR_ASSERT(false);
68   }
69   cell new_sp = *sp - delta;
70   *sp = new_sp;
71   *(cell*)new_sp = *pc;
72
73   *pc = untag<word>(special_objects[index])->entry_point;
74 }
75
76 void factor_vm::dispatch_signal_handler(cell* sp, cell* pc, cell handler) {
77
78   bool in_code_seg = code->seg->in_segment_p(*pc);
79   cell cs_limit = ctx->callstack_seg->start + stack_reserved;
80   signal_resumable = in_code_seg && *sp >= cs_limit;
81
82   if (signal_resumable) {
83     dispatch_resumable_signal(sp, pc, handler);
84   } else {
85     dispatch_non_resumable_signal(sp, pc, handler, cs_limit);
86   }
87
88   // Poking with the stack pointer, which the above code does, means
89   // that pointers to stack-allocated objects will become
90   // corrupted. Therefore the root vectors needs to be cleared because
91   // their pointers to stack variables are now garbage.
92   data_roots.clear();
93   code_roots.clear();
94 }
95
96 }