Revert "lists: Add list literal doc example."
[factor.git] / vm / cpu-x86.cpp
blobc7169d26fd78da25120650321d616c8bf061f339
1 #include "master.hpp"
3 namespace factor {
5 void factor_vm::dispatch_non_resumable_signal(cell* sp, cell* pc,
6 cell handler,
7 cell limit) {
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;
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;
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);
34 ctx->callstack_top = frame_top;
35 *sp = frame_top;
36 *pc = handler;
39 void factor_vm::dispatch_resumable_signal(cell* sp, cell* pc, cell handler) {
41 // Fault came from Factor, and we've got a good callstack. Route the
42 // signal handler through the resumable signal handler
43 // subprimitive.
45 cell offset = *sp % 16;
47 signal_handler_addr = handler;
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);
69 cell new_sp = *sp - delta;
70 *sp = new_sp;
71 *(cell*)new_sp = *pc;
73 *pc = untag<word>(special_objects[index])->entry_point;
76 void factor_vm::dispatch_signal_handler(cell* sp, cell* pc, cell handler) {
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;
82 if (signal_resumable) {
83 dispatch_resumable_signal(sp, pc, handler);
84 } else {
85 dispatch_non_resumable_signal(sp, pc, handler, cs_limit);
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();