cpu.x86.32: update for resumable signal handlers

db4
Joe Groff 2011-10-25 23:25:19 -07:00
parent d6eae2f42d
commit ff2d480d98
4 changed files with 77 additions and 47 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]);