cpu.x86.32: update for resumable signal handlers
parent
d6eae2f42d
commit
ff2d480d98
|
@ -4,7 +4,7 @@ USING: bootstrap.image.private kernel kernel.private namespaces
|
||||||
system cpu.x86.assembler cpu.x86.assembler.operands layouts
|
system cpu.x86.assembler cpu.x86.assembler.operands layouts
|
||||||
vocabs parser compiler.constants compiler.codegen.relocation
|
vocabs parser compiler.constants compiler.codegen.relocation
|
||||||
sequences math math.private generic.single.private
|
sequences math math.private generic.single.private
|
||||||
threads.private ;
|
threads.private locals ;
|
||||||
IN: bootstrap.x86
|
IN: bootstrap.x86
|
||||||
|
|
||||||
4 \ cell set
|
4 \ cell set
|
||||||
|
@ -23,6 +23,7 @@ IN: bootstrap.x86
|
||||||
: vm-reg ( -- reg ) EBX ;
|
: vm-reg ( -- reg ) EBX ;
|
||||||
: ctx-reg ( -- reg ) EBP ;
|
: ctx-reg ( -- reg ) EBP ;
|
||||||
: nv-regs ( -- seq ) { ESI EDI EBX } ;
|
: nv-regs ( -- seq ) { ESI EDI EBX } ;
|
||||||
|
: volatile-regs ( -- seq ) { EAX ECX EDX } ;
|
||||||
: nv-reg ( -- reg ) ESI ;
|
: nv-reg ( -- reg ) ESI ;
|
||||||
: ds-reg ( -- reg ) ESI ;
|
: ds-reg ( -- reg ) ESI ;
|
||||||
: rs-reg ( -- reg ) EDI ;
|
: rs-reg ( -- reg ) EDI ;
|
||||||
|
@ -34,12 +35,12 @@ IN: bootstrap.x86
|
||||||
0 CALL f rc-relative rel-dlsym ;
|
0 CALL f rc-relative rel-dlsym ;
|
||||||
|
|
||||||
[
|
[
|
||||||
! store entry point
|
|
||||||
ESP bootstrap-cell 2 * neg [+] 0 MOV rc-absolute-cell rel-this
|
|
||||||
! store stack frame size
|
|
||||||
ESP bootstrap-cell neg [+] stack-frame-size MOV
|
|
||||||
! alignment
|
! alignment
|
||||||
ESP stack-frame-size bootstrap-cell - SUB
|
ESP stack-frame-size bootstrap-cell - SUB
|
||||||
|
! store entry point
|
||||||
|
ESP stack-frame-size 3 bootstrap-cells - [+] 0 MOV rc-absolute-cell rel-this
|
||||||
|
! store stack frame size
|
||||||
|
ESP stack-frame-size 2 bootstrap-cells - [+] stack-frame-size MOV
|
||||||
] jit-prolog jit-define
|
] jit-prolog jit-define
|
||||||
|
|
||||||
[
|
[
|
||||||
|
@ -96,6 +97,36 @@ IN: bootstrap.x86
|
||||||
"end_callback" jit-call
|
"end_callback" jit-call
|
||||||
] \ c-to-factor define-sub-primitive
|
] \ c-to-factor define-sub-primitive
|
||||||
|
|
||||||
|
! The signal-handler and leaf-signal-handler subprimitives are special-cased
|
||||||
|
! in vm/quotations.cpp not to trigger generation of a stack frame, so they can
|
||||||
|
! peform their own prolog/epilog preserving registers.
|
||||||
|
|
||||||
|
:: jit-signal-handler-prolog ( -- frame-size )
|
||||||
|
stack-frame-size 8 bootstrap-cells + :> frame-size
|
||||||
|
ESP frame-size bootstrap-cell - SUB ! minus a cell for return address
|
||||||
|
ESP [] EAX MOV
|
||||||
|
ESP 1 bootstrap-cells [+] ECX MOV
|
||||||
|
ESP 2 bootstrap-cells [+] EDX MOV
|
||||||
|
ESP 3 bootstrap-cells [+] EBX MOV
|
||||||
|
ESP 4 bootstrap-cells [+] EBP MOV
|
||||||
|
ESP 5 bootstrap-cells [+] ESI MOV
|
||||||
|
ESP 6 bootstrap-cells [+] EDI MOV
|
||||||
|
ESP frame-size 3 bootstrap-cells - [+] 0 MOV rc-absolute-cell rel-this
|
||||||
|
ESP frame-size 2 bootstrap-cells - [+] frame-size MOV
|
||||||
|
! subprimitive definition assumes vm's been loaded
|
||||||
|
jit-load-vm
|
||||||
|
frame-size ;
|
||||||
|
|
||||||
|
:: jit-signal-handler-epilog ( frame-size -- )
|
||||||
|
EAX ESP [] MOV
|
||||||
|
ECX ESP 1 bootstrap-cells [+] MOV
|
||||||
|
EDX ESP 2 bootstrap-cells [+] MOV
|
||||||
|
EBX ESP 3 bootstrap-cells [+] MOV
|
||||||
|
EBP ESP 4 bootstrap-cells [+] MOV
|
||||||
|
ESI ESP 5 bootstrap-cells [+] MOV
|
||||||
|
EDI ESP 6 bootstrap-cells [+] MOV
|
||||||
|
ESP frame-size bootstrap-cell - ADD ;
|
||||||
|
|
||||||
[
|
[
|
||||||
EAX ds-reg [] MOV
|
EAX ds-reg [] MOV
|
||||||
ds-reg bootstrap-cell SUB
|
ds-reg bootstrap-cell SUB
|
||||||
|
|
|
@ -4,7 +4,7 @@ USING: bootstrap.image.private kernel kernel.private namespaces
|
||||||
system layouts vocabs parser compiler.constants
|
system layouts vocabs parser compiler.constants
|
||||||
compiler.codegen.relocation math math.private cpu.x86.assembler
|
compiler.codegen.relocation math math.private cpu.x86.assembler
|
||||||
cpu.x86.assembler.operands sequences generic.single.private
|
cpu.x86.assembler.operands sequences generic.single.private
|
||||||
threads.private ;
|
threads.private locals ;
|
||||||
IN: bootstrap.x86
|
IN: bootstrap.x86
|
||||||
|
|
||||||
8 \ cell set
|
8 \ cell set
|
||||||
|
@ -91,9 +91,7 @@ IN: bootstrap.x86
|
||||||
"end_callback" jit-call
|
"end_callback" jit-call
|
||||||
] \ c-to-factor define-sub-primitive
|
] \ c-to-factor define-sub-primitive
|
||||||
|
|
||||||
USE: locals
|
:: jit-signal-handler-prolog ( -- frame-size )
|
||||||
|
|
||||||
:: jit-save-volatile-regs ( -- frame-size )
|
|
||||||
! do we also need to save XMM?
|
! do we also need to save XMM?
|
||||||
volatile-regs length bootstrap-cells 16 align stack-frame-size + :> frame-size
|
volatile-regs length bootstrap-cells 16 align stack-frame-size + :> frame-size
|
||||||
RSP frame-size bootstrap-cell - SUB ! minus a cell for return address
|
RSP frame-size bootstrap-cell - SUB ! minus a cell for return address
|
||||||
|
@ -105,43 +103,11 @@ USE: locals
|
||||||
RSP frame-size 2 bootstrap-cells - [+] frame-size MOV
|
RSP frame-size 2 bootstrap-cells - [+] frame-size MOV
|
||||||
frame-size ;
|
frame-size ;
|
||||||
|
|
||||||
:: jit-restore-volatile-regs ( frame-size -- )
|
:: jit-signal-handler-epilog ( frame-size -- )
|
||||||
volatile-regs
|
volatile-regs
|
||||||
[| r i | r RSP i bootstrap-cells [+] MOV ] each-index
|
[| r i | r RSP i bootstrap-cells [+] MOV ] each-index
|
||||||
RSP frame-size bootstrap-cell - ADD ;
|
RSP frame-size bootstrap-cell - ADD ;
|
||||||
|
|
||||||
! The signal-handler and leaf-signal-handler subprimitives are special-cased
|
|
||||||
! in vm/quotations.cpp not to trigger generation of a stack frame, so they can
|
|
||||||
! peform their own prolog/epilog preserving registers.
|
|
||||||
|
|
||||||
[| |
|
|
||||||
jit-save-volatile-regs :> frame-size
|
|
||||||
jit-save-context
|
|
||||||
RAX vm-reg vm-signal-handler-addr-offset [+] MOV
|
|
||||||
RAX CALL
|
|
||||||
frame-size jit-restore-volatile-regs
|
|
||||||
] \ signal-handler define-sub-primitive
|
|
||||||
|
|
||||||
[| |
|
|
||||||
jit-save-volatile-regs :> frame-size
|
|
||||||
jit-save-context
|
|
||||||
RAX vm-reg vm-signal-handler-addr-offset [+] MOV
|
|
||||||
RAX CALL
|
|
||||||
! Stack at this point has a fake stack frame set up to represent the
|
|
||||||
! leaf procedure we interrupted. We must tear down that frame in
|
|
||||||
! addition to our own before resuming.
|
|
||||||
! Grab our frame's return address and place it just underneath the leaf proc's
|
|
||||||
! return address, since we can't touch any registers once they've been
|
|
||||||
! restored. If we got this far there should be no faults here and we
|
|
||||||
! can get away with corrupting the stack frame.
|
|
||||||
RAX RSP frame-size bootstrap-cell - [+] MOV
|
|
||||||
RSP frame-size 2 bootstrap-cells + [+] RAX MOV
|
|
||||||
|
|
||||||
! Popping 3 extra cells here leaves the resume address at the top of the stack
|
|
||||||
! when we RET.
|
|
||||||
frame-size 3 bootstrap-cells + jit-restore-volatile-regs
|
|
||||||
] \ leaf-signal-handler define-sub-primitive
|
|
||||||
|
|
||||||
[
|
[
|
||||||
arg1 ds-reg [] MOV
|
arg1 ds-reg [] MOV
|
||||||
ds-reg bootstrap-cell SUB
|
ds-reg bootstrap-cell SUB
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
USING: bootstrap.image.private compiler.constants
|
USING: bootstrap.image.private compiler.constants
|
||||||
compiler.codegen.relocation compiler.units cpu.x86.assembler
|
compiler.codegen.relocation compiler.units cpu.x86.assembler
|
||||||
cpu.x86.assembler.operands kernel kernel.private layouts
|
cpu.x86.assembler.operands kernel kernel.private layouts
|
||||||
locals.backend make math math.private namespaces sequences
|
locals locals.backend make math math.private namespaces sequences
|
||||||
slots.private strings.private vocabs ;
|
slots.private strings.private vocabs ;
|
||||||
IN: bootstrap.x86
|
IN: bootstrap.x86
|
||||||
|
|
||||||
|
@ -102,6 +102,38 @@ big-endian off
|
||||||
0 CALL f rc-relative rel-word-pic
|
0 CALL f rc-relative rel-word-pic
|
||||||
] jit-word-call jit-define
|
] jit-word-call jit-define
|
||||||
|
|
||||||
|
! The signal-handler and leaf-signal-handler subprimitives are special-cased
|
||||||
|
! in vm/quotations.cpp not to trigger generation of a stack frame, so they can
|
||||||
|
! peform their own prolog/epilog preserving registers.
|
||||||
|
|
||||||
|
[| |
|
||||||
|
jit-signal-handler-prolog :> frame-size
|
||||||
|
jit-save-context
|
||||||
|
temp0 vm-reg vm-signal-handler-addr-offset [+] MOV
|
||||||
|
temp0 CALL
|
||||||
|
frame-size jit-signal-handler-epilog
|
||||||
|
] \ signal-handler define-sub-primitive
|
||||||
|
|
||||||
|
[| |
|
||||||
|
jit-signal-handler-prolog :> frame-size
|
||||||
|
jit-save-context
|
||||||
|
temp0 vm-reg vm-signal-handler-addr-offset [+] MOV
|
||||||
|
temp0 CALL
|
||||||
|
! Stack at this point has a fake stack frame set up to represent the
|
||||||
|
! leaf procedure we interrupted. We must tear down that frame in
|
||||||
|
! addition to our own before resuming.
|
||||||
|
! Grab our frame's return address and place it just underneath the leaf proc's
|
||||||
|
! return address, since we can't touch any registers once they've been
|
||||||
|
! restored. If we got this far there should be no faults here and we
|
||||||
|
! can get away with corrupting the stack frame.
|
||||||
|
temp0 stack-reg frame-size bootstrap-cell - [+] MOV
|
||||||
|
stack-reg frame-size stack-frame-size + 2 bootstrap-cells - [+] temp0 MOV
|
||||||
|
|
||||||
|
! Pop enough of the fake frame to leave the resume address at the top of the
|
||||||
|
! stack when we RET.
|
||||||
|
frame-size stack-frame-size + bootstrap-cell - jit-signal-handler-epilog
|
||||||
|
] \ leaf-signal-handler define-sub-primitive
|
||||||
|
|
||||||
[
|
[
|
||||||
! load boolean
|
! load boolean
|
||||||
temp0 ds-reg [] MOV
|
temp0 ds-reg [] MOV
|
||||||
|
|
|
@ -102,9 +102,10 @@ void factor_vm::dispatch_signal_handler(cell *sp, cell *pc, cell handler)
|
||||||
// Make a fake frame for the leaf procedure
|
// Make a fake frame for the leaf procedure
|
||||||
cell leaf_word = find_word_for_address(this, *pc);
|
cell leaf_word = find_word_for_address(this, *pc);
|
||||||
|
|
||||||
cell newsp = *sp - 4 * sizeof(cell);
|
// XXX get platform-appropriate stack frame size
|
||||||
*(cell*)(newsp + 3*sizeof(cell)) = 4*sizeof(cell);
|
cell newsp = *sp - 32;
|
||||||
*(cell*)(newsp + 2*sizeof(cell)) = leaf_word;
|
*(cell*)(newsp + 32 - sizeof(cell)) = 32;
|
||||||
|
*(cell*)(newsp + 32 - 2*sizeof(cell)) = leaf_word;
|
||||||
*(cell*) newsp = *pc;
|
*(cell*) newsp = *pc;
|
||||||
*sp = newsp;
|
*sp = newsp;
|
||||||
handler_word = tagged<word>(special_objects[LEAF_SIGNAL_HANDLER_WORD]);
|
handler_word = tagged<word>(special_objects[LEAF_SIGNAL_HANDLER_WORD]);
|
||||||
|
|
Loading…
Reference in New Issue