5 void factor_vm::dispatch_non_resumable_signal(cell
* sp
, cell
* pc
,
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
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
;
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
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.
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
;
69 cell new_sp
= *sp
- delta
;
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
);
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.