Next: machinery call arguments, Previous: machinery continuations, Up: machinery [Index]
Let’s recall how the Scheme stack segment looks, machinery stack overflow. Function call frames are put on the stack starting from high memory addresses, stack usage grows towards low memory addresses; at some point the stack runs out of space.
high memory
| |
|----------------------|
| | <- pcb->frame_base
|----------------------| --
| ik_underflow_handler | .
|----------------------| .
. .
. .
. .
|----------------------| .
| | <- pcb->frame_redline . stack
|----------------------| . segment
. . size
. .
. .
|----------------------| .
| | <- pcb->stack_base .
|----------------------| --
| |
low memory
Figure 16.49: Stack boundaries as represented by the PCB.
To detect stack usage approaching the end of available stack space: the PCB contains a field referencing a machine word 2 memory chunks (4096 bytes each) above the lower boundary; whenever stack usage crosses this “red line”: a new stack segment needs to be allocated and call frames must be put on the new stack; machinery stack overflow.
high memory
| | <- pcb->frame_base
|----------------------|
| ik_underflow_handler |
|----------------------|
.
.
.
|----------------------| --
| local value | .
|----------------------| .
| local value | <- pcb->frame_redline .
|----------------------| . framesize
| local value | .
|----------------------| .
| return address | <- FPR .
|----------------------| --
| function argument |
|----------------------|
| function argument |
|----------------------|
.
.
.
|----------------------|
| | <- pcb->stack_base
|----------------------|
| |
low memory
Figure 16.50: Scenario on the Scheme stack that triggers the stack overflow;
we see that: FPR < pcb->frame_redline.
Scheme functions can be partitioned in: those that may use more stack space, those that do not; Vicare recognises this partition and inserts a stack overflow check at the beginning of each of the former. The pseudo–Assembly performing the check is as follows:
(label function_entry_point) (cmpl FPR pcb->frame_redline) (jb L0) (label L1) ... the function body ... (ret) (label L0) (forcall "ik_stack_overflow") (jmp L1)
When stack overflow happens the C function ik_stack_overflow() is
called through the forcall primitive instruction and the Assembly
subroutine ik_foreign_call; forcall creates a new stack
frame and then calls ik_foreign_call which in turn calls the C
function, machinery stack overflow.
high memory
| |
|----------------------| --
| local value | .
|----------------------| .
| local value | <- pcb->frame_redline .
|----------------------| . framesize
| local value | .
|----------------------| .
| return address | .
|----------------------| --
| function argument | .
|----------------------| . frame of
| function argument | . forcall
|----------------------| .
| return address | <- FPR .
|----------------------| --
| |
low memory
Figure 16.51: Call frame of forcall on top of the call frame that
caused the stack underflow.
ik_stack_overflow() does the following:
Upon returning to the caller ik_foreign_call performs a
ret Assembly instruction with the FPR referencing the
underflow handler; so returning from a stack reallocation is exactly
like returning to the next PCB continuation.
Next: machinery call arguments, Previous: machinery continuations, Up: machinery [Index]