Merge branch 'master' of git://factorcode.org/git/factor
commit
96c4b1a672
|
@ -109,12 +109,11 @@ SYMBOL: jit-relocations
|
||||||
|
|
||||||
SYMBOL: jit-offset
|
SYMBOL: jit-offset
|
||||||
|
|
||||||
: compute-offset ( rc -- offset )
|
: compute-offset ( -- offset )
|
||||||
[ building get length jit-offset get + ] dip
|
building get length jit-offset get + ;
|
||||||
rc-absolute-cell = bootstrap-cell 4 ? - ;
|
|
||||||
|
|
||||||
: jit-rel ( rc rt -- )
|
: jit-rel ( rc rt -- )
|
||||||
over compute-offset 3array jit-relocations get push-all ;
|
compute-offset 3array jit-relocations get push-all ;
|
||||||
|
|
||||||
SYMBOL: jit-parameters
|
SYMBOL: jit-parameters
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
! Copyright (C) 2004, 2009 Slava Pestov.
|
! Copyright (C) 2004, 2010 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: accessors arrays assocs combinators hashtables kernel
|
USING: accessors arrays assocs combinators hashtables kernel
|
||||||
math fry namespaces make sequences words byte-arrays
|
math fry namespaces make sequences words byte-arrays
|
||||||
|
@ -240,9 +240,9 @@ M: #alien-callback emit-node
|
||||||
dup params>> xt>> dup
|
dup params>> xt>> dup
|
||||||
[
|
[
|
||||||
##prologue
|
##prologue
|
||||||
dup [ ##alien-callback ] emit-alien-node
|
[ ##alien-callback ] emit-alien-node
|
||||||
##epilogue
|
##epilogue
|
||||||
params>> ##callback-return
|
##return
|
||||||
] with-cfg-builder ;
|
] with-cfg-builder ;
|
||||||
|
|
||||||
! No-op nodes
|
! No-op nodes
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
! Copyright (C) 2009 Slava Pestov.
|
! Copyright (C) 2009, 2010 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: kernel combinators.short-circuit accessors math sequences
|
USING: kernel combinators.short-circuit accessors math sequences
|
||||||
sets assocs compiler.cfg.instructions compiler.cfg.rpo
|
sets assocs compiler.cfg.instructions compiler.cfg.rpo
|
||||||
|
@ -14,7 +14,7 @@ ERROR: bad-kill-block bb ;
|
||||||
dup instructions>> dup penultimate ##epilogue? [
|
dup instructions>> dup penultimate ##epilogue? [
|
||||||
{
|
{
|
||||||
[ length 2 = ]
|
[ length 2 = ]
|
||||||
[ last { [ ##return? ] [ ##callback-return? ] [ ##jump? ] } 1|| ]
|
[ last { [ ##return? ] [ ##jump? ] } 1|| ]
|
||||||
} 1&&
|
} 1&&
|
||||||
] [ last ##branch? ] if
|
] [ last ##branch? ] if
|
||||||
[ drop ] [ bad-kill-block ] if ;
|
[ drop ] [ bad-kill-block ] if ;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
! Copyright (C) 2008, 2009 Slava Pestov.
|
! Copyright (C) 2008, 2010 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: assocs accessors arrays kernel sequences namespaces words
|
USING: assocs accessors arrays kernel sequences namespaces words
|
||||||
math math.order layouts classes.algebra classes.union
|
math math.order layouts classes.algebra classes.union
|
||||||
|
@ -674,9 +674,6 @@ literal: params stack-frame ;
|
||||||
INSN: ##alien-callback
|
INSN: ##alien-callback
|
||||||
literal: params stack-frame ;
|
literal: params stack-frame ;
|
||||||
|
|
||||||
INSN: ##callback-return
|
|
||||||
literal: params ;
|
|
||||||
|
|
||||||
! Instructions used by CFG IR only.
|
! Instructions used by CFG IR only.
|
||||||
INSN: ##prologue ;
|
INSN: ##prologue ;
|
||||||
INSN: ##epilogue ;
|
INSN: ##epilogue ;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
! Copyright (C) 2008, 2009 Slava Pestov.
|
! Copyright (C) 2008, 2010 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: namespaces make math math.order math.parser sequences accessors
|
USING: namespaces make math math.order math.parser sequences accessors
|
||||||
kernel kernel.private layouts assocs words summary arrays
|
kernel kernel.private layouts assocs words summary arrays
|
||||||
|
@ -496,11 +496,6 @@ TUPLE: callback-context ;
|
||||||
[ callback-context new do-callback ] %
|
[ callback-context new do-callback ] %
|
||||||
] [ ] make ;
|
] [ ] make ;
|
||||||
|
|
||||||
M: ##callback-return generate-insn
|
|
||||||
#! All the extra book-keeping for %unwind is only for x86.
|
|
||||||
#! On other platforms its an alias for %return.
|
|
||||||
params>> %callback-return ;
|
|
||||||
|
|
||||||
M: ##alien-callback generate-insn
|
M: ##alien-callback generate-insn
|
||||||
params>>
|
params>>
|
||||||
[ registers>objects ]
|
[ registers>objects ]
|
||||||
|
|
|
@ -34,13 +34,10 @@ TUPLE: label offset ;
|
||||||
dup label? [ get ] unless
|
dup label? [ get ] unless
|
||||||
compiled-offset >>offset drop ;
|
compiled-offset >>offset drop ;
|
||||||
|
|
||||||
: offset-for-class ( class -- n )
|
|
||||||
rc-absolute-cell = cell 4 ? compiled-offset swap - ;
|
|
||||||
|
|
||||||
TUPLE: label-fixup { label label } { class integer } { offset integer } ;
|
TUPLE: label-fixup { label label } { class integer } { offset integer } ;
|
||||||
|
|
||||||
: label-fixup ( label class -- )
|
: label-fixup ( label class -- )
|
||||||
dup offset-for-class \ label-fixup boa label-table get push ;
|
compiled-offset \ label-fixup boa label-table get push ;
|
||||||
|
|
||||||
! Relocation table
|
! Relocation table
|
||||||
SYMBOL: relocation-table
|
SYMBOL: relocation-table
|
||||||
|
@ -53,7 +50,7 @@ SYMBOL: relocation-table
|
||||||
{ 0 24 28 } bitfield relocation-table get push-4 ;
|
{ 0 24 28 } bitfield relocation-table get push-4 ;
|
||||||
|
|
||||||
: rel-fixup ( class type -- )
|
: rel-fixup ( class type -- )
|
||||||
swap dup offset-for-class add-relocation-entry ;
|
swap compiled-offset add-relocation-entry ;
|
||||||
|
|
||||||
: add-dlsym-parameters ( symbol dll -- )
|
: add-dlsym-parameters ( symbol dll -- )
|
||||||
[ string>symbol add-parameter ] [ add-parameter ] bi* ;
|
[ string>symbol add-parameter ] [ add-parameter ] bi* ;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
! Copyright (C) 2008, 2009 Slava Pestov.
|
! Copyright (C) 2008, 2010 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: math kernel layouts system strings words quotations byte-arrays
|
USING: math kernel layouts system strings words quotations byte-arrays
|
||||||
alien arrays literals sequences ;
|
alien arrays literals sequences ;
|
||||||
|
@ -37,6 +37,7 @@ CONSTANT: rc-relative-ppc-3 6
|
||||||
CONSTANT: rc-relative-arm-3 7
|
CONSTANT: rc-relative-arm-3 7
|
||||||
CONSTANT: rc-indirect-arm 8
|
CONSTANT: rc-indirect-arm 8
|
||||||
CONSTANT: rc-indirect-arm-pc 9
|
CONSTANT: rc-indirect-arm-pc 9
|
||||||
|
CONSTANT: rc-absolute-2 10
|
||||||
|
|
||||||
! Relocation types
|
! Relocation types
|
||||||
CONSTANT: rt-primitive 0
|
CONSTANT: rt-primitive 0
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
! Copyright (C) 2006, 2009 Slava Pestov.
|
! Copyright (C) 2006, 2010 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: accessors arrays assocs generic kernel kernel.private
|
USING: accessors arrays assocs generic kernel kernel.private
|
||||||
math memory namespaces make sequences layouts system hashtables
|
math memory namespaces make sequences layouts system hashtables
|
||||||
|
@ -550,6 +550,8 @@ HOOK: %save-param-reg cpu ( stack reg rep -- )
|
||||||
|
|
||||||
HOOK: %load-param-reg cpu ( stack reg rep -- )
|
HOOK: %load-param-reg cpu ( stack reg rep -- )
|
||||||
|
|
||||||
|
HOOK: %load-context cpu ( temp1 temp2 -- )
|
||||||
|
|
||||||
HOOK: %save-context cpu ( temp1 temp2 -- )
|
HOOK: %save-context cpu ( temp1 temp2 -- )
|
||||||
|
|
||||||
HOOK: %prepare-var-args cpu ( -- )
|
HOOK: %prepare-var-args cpu ( -- )
|
||||||
|
@ -574,7 +576,6 @@ HOOK: %nest-stacks cpu ( -- )
|
||||||
|
|
||||||
HOOK: %unnest-stacks cpu ( -- )
|
HOOK: %unnest-stacks cpu ( -- )
|
||||||
|
|
||||||
! Return to caller with stdcall unwinding (only for x86)
|
HOOK: callback-return-rewind cpu ( params -- n )
|
||||||
HOOK: %callback-return cpu ( params -- )
|
|
||||||
|
|
||||||
M: object %callback-return drop %return ;
|
M: object callback-return-rewind drop 0 ;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
! Copyright (C) 2005, 2009 Slava Pestov.
|
! Copyright (C) 2005, 2010 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: locals alien.c-types alien.libraries alien.syntax arrays
|
USING: locals alien.c-types alien.libraries alien.syntax arrays
|
||||||
kernel fry math namespaces sequences system layouts io
|
kernel fry math namespaces sequences system layouts io
|
||||||
|
@ -20,6 +20,7 @@ M: x86.32 machine-registers
|
||||||
M: x86.32 ds-reg ESI ;
|
M: x86.32 ds-reg ESI ;
|
||||||
M: x86.32 rs-reg EDI ;
|
M: x86.32 rs-reg EDI ;
|
||||||
M: x86.32 stack-reg ESP ;
|
M: x86.32 stack-reg ESP ;
|
||||||
|
M: x86.32 frame-reg EBP ;
|
||||||
M: x86.32 temp-reg ECX ;
|
M: x86.32 temp-reg ECX ;
|
||||||
|
|
||||||
: local@ ( n -- op )
|
: local@ ( n -- op )
|
||||||
|
@ -42,7 +43,7 @@ M: x86.32 %mark-deck
|
||||||
M:: x86.32 %dispatch ( src temp -- )
|
M:: x86.32 %dispatch ( src temp -- )
|
||||||
! Load jump table base.
|
! Load jump table base.
|
||||||
temp src HEX: ffffffff [+] LEA
|
temp src HEX: ffffffff [+] LEA
|
||||||
building get length cell - :> start
|
building get length :> start
|
||||||
0 rc-absolute-cell rel-here
|
0 rc-absolute-cell rel-here
|
||||||
! Go
|
! Go
|
||||||
temp HEX: 7f [+] JMP
|
temp HEX: 7f [+] JMP
|
||||||
|
@ -215,11 +216,7 @@ M:: x86.32 %unbox-large-struct ( n c-type -- )
|
||||||
"to_value_struct" f %alien-invoke ;
|
"to_value_struct" f %alien-invoke ;
|
||||||
|
|
||||||
M: x86.32 %nest-stacks ( -- )
|
M: x86.32 %nest-stacks ( -- )
|
||||||
! Save current frame to ctx->magic_frame.
|
0 save-vm-ptr
|
||||||
! See comment in vm/contexts.hpp.
|
|
||||||
EAX stack-reg stack-frame get total-size>> 3 cells - [+] LEA
|
|
||||||
4 save-vm-ptr
|
|
||||||
0 stack@ EAX MOV
|
|
||||||
"nest_stacks" f %alien-invoke ;
|
"nest_stacks" f %alien-invoke ;
|
||||||
|
|
||||||
M: x86.32 %unnest-stacks ( -- )
|
M: x86.32 %unnest-stacks ( -- )
|
||||||
|
@ -238,10 +235,11 @@ M: x86.32 %alien-indirect ( -- )
|
||||||
EBP CALL ;
|
EBP CALL ;
|
||||||
|
|
||||||
M: x86.32 %alien-callback ( quot -- )
|
M: x86.32 %alien-callback ( quot -- )
|
||||||
|
EAX EDX %load-context
|
||||||
EAX swap %load-reference
|
EAX swap %load-reference
|
||||||
0 stack@ EAX MOV
|
EDX %mov-vm-ptr
|
||||||
4 save-vm-ptr
|
EAX quot-xt-offset [+] CALL
|
||||||
"c_to_factor" f %alien-invoke ;
|
EAX EDX %save-context ;
|
||||||
|
|
||||||
M: x86.32 %callback-value ( ctype -- )
|
M: x86.32 %callback-value ( ctype -- )
|
||||||
%pop-context-stack
|
%pop-context-stack
|
||||||
|
@ -300,20 +298,6 @@ M: x86.32 %cleanup ( params -- )
|
||||||
[ drop ]
|
[ drop ]
|
||||||
} cond ;
|
} cond ;
|
||||||
|
|
||||||
M: x86.32 %callback-return ( n -- )
|
|
||||||
#! a) If the callback is stdcall, we have to clean up the
|
|
||||||
#! caller's stack frame.
|
|
||||||
#! b) If the callback is returning a large struct, we have
|
|
||||||
#! to fix ESP.
|
|
||||||
{
|
|
||||||
{ [ dup abi>> "stdcall" = ] [
|
|
||||||
<alien-stack-frame>
|
|
||||||
[ params>> ] [ return>> ] bi +
|
|
||||||
] }
|
|
||||||
{ [ dup return>> large-struct? ] [ drop 4 ] }
|
|
||||||
[ drop 0 ]
|
|
||||||
} cond RET ;
|
|
||||||
|
|
||||||
M:: x86.32 %call-gc ( gc-root-count temp -- )
|
M:: x86.32 %call-gc ( gc-root-count temp -- )
|
||||||
temp gc-root-base special@ LEA
|
temp gc-root-base special@ LEA
|
||||||
8 save-vm-ptr
|
8 save-vm-ptr
|
||||||
|
@ -327,6 +311,20 @@ M: x86.32 dummy-int-params? f ;
|
||||||
|
|
||||||
M: x86.32 dummy-fp-params? f ;
|
M: x86.32 dummy-fp-params? f ;
|
||||||
|
|
||||||
|
M: x86.32 callback-return-rewind ( params -- n )
|
||||||
|
#! a) If the callback is stdcall, we have to clean up the
|
||||||
|
#! caller's stack frame.
|
||||||
|
#! b) If the callback is returning a large struct, we have
|
||||||
|
#! to fix ESP.
|
||||||
|
{
|
||||||
|
{ [ dup abi>> "stdcall" = ] [
|
||||||
|
<alien-stack-frame>
|
||||||
|
[ params>> ] [ return>> ] bi +
|
||||||
|
] }
|
||||||
|
{ [ dup return>> large-struct? ] [ drop 4 ] }
|
||||||
|
[ drop 0 ]
|
||||||
|
} cond ;
|
||||||
|
|
||||||
! Dreadful
|
! Dreadful
|
||||||
M: object flatten-value-type (flatten-int-type) ;
|
M: object flatten-value-type (flatten-int-type) ;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@ IN: bootstrap.x86
|
||||||
: temp3 ( -- reg ) EBX ;
|
: temp3 ( -- reg ) EBX ;
|
||||||
: safe-reg ( -- reg ) EAX ;
|
: safe-reg ( -- reg ) EAX ;
|
||||||
: stack-reg ( -- reg ) ESP ;
|
: stack-reg ( -- reg ) ESP ;
|
||||||
|
: frame-reg ( -- reg ) EBP ;
|
||||||
|
: nv-regs ( -- seq ) { ESI EDI EBX } ;
|
||||||
: ds-reg ( -- reg ) ESI ;
|
: ds-reg ( -- reg ) ESI ;
|
||||||
: rs-reg ( -- reg ) EDI ;
|
: rs-reg ( -- reg ) EDI ;
|
||||||
: fixnum>slot@ ( -- ) temp0 2 SAR ;
|
: fixnum>slot@ ( -- ) temp0 2 SAR ;
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
! Copyright (C) 2005, 2009 Slava Pestov.
|
! Copyright (C) 2005, 2010 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: accessors arrays kernel math namespaces make sequences system
|
USING: accessors arrays kernel math namespaces make sequences
|
||||||
layouts alien alien.c-types alien.accessors slots
|
system layouts alien alien.c-types alien.accessors slots
|
||||||
splitting assocs combinators locals compiler.constants
|
splitting assocs combinators locals compiler.constants
|
||||||
compiler.codegen compiler.codegen.fixup compiler.cfg.instructions
|
compiler.codegen compiler.codegen.fixup
|
||||||
compiler.cfg.builder compiler.cfg.intrinsics compiler.cfg.stack-frame
|
compiler.cfg.instructions compiler.cfg.builder
|
||||||
cpu.x86.assembler cpu.x86.assembler.operands cpu.x86 cpu.architecture ;
|
compiler.cfg.intrinsics compiler.cfg.stack-frame
|
||||||
|
cpu.x86.assembler cpu.x86.assembler.operands cpu.x86
|
||||||
|
cpu.architecture ;
|
||||||
IN: cpu.x86.64
|
IN: cpu.x86.64
|
||||||
|
|
||||||
: param-reg-1 ( -- reg ) int-regs param-regs first ; inline
|
: param-reg-0 ( -- reg ) 0 int-regs param-reg ; inline
|
||||||
: param-reg-2 ( -- reg ) int-regs param-regs second ; inline
|
: param-reg-1 ( -- reg ) 1 int-regs param-reg ; inline
|
||||||
: param-reg-3 ( -- reg ) int-regs param-regs third ; inline
|
: param-reg-2 ( -- reg ) 2 int-regs param-reg ; inline
|
||||||
: param-reg-4 ( -- reg ) int-regs param-regs fourth ; inline
|
: param-reg-3 ( -- reg ) 3 int-regs param-reg ; inline
|
||||||
|
|
||||||
M: x86.64 pic-tail-reg RBX ;
|
M: x86.64 pic-tail-reg RBX ;
|
||||||
|
|
||||||
|
@ -21,6 +23,7 @@ M: float-regs return-reg drop XMM0 ;
|
||||||
M: x86.64 ds-reg R14 ;
|
M: x86.64 ds-reg R14 ;
|
||||||
M: x86.64 rs-reg R15 ;
|
M: x86.64 rs-reg R15 ;
|
||||||
M: x86.64 stack-reg RSP ;
|
M: x86.64 stack-reg RSP ;
|
||||||
|
M: x86.64 frame-reg RBP ;
|
||||||
|
|
||||||
M: x86.64 extra-stack-space drop 0 ;
|
M: x86.64 extra-stack-space drop 0 ;
|
||||||
|
|
||||||
|
@ -56,9 +59,9 @@ M: x86.64 %mark-deck
|
||||||
[+] card-mark <byte> MOV ;
|
[+] card-mark <byte> MOV ;
|
||||||
|
|
||||||
M:: x86.64 %dispatch ( src temp -- )
|
M:: x86.64 %dispatch ( src temp -- )
|
||||||
building get length :> start
|
|
||||||
! Load jump table base.
|
! Load jump table base.
|
||||||
temp HEX: ffffffff MOV
|
temp HEX: ffffffff MOV
|
||||||
|
building get length :> start
|
||||||
0 rc-absolute-cell rel-here
|
0 rc-absolute-cell rel-here
|
||||||
! Add jump table base
|
! Add jump table base
|
||||||
temp src ADD
|
temp src ADD
|
||||||
|
@ -66,7 +69,7 @@ M:: x86.64 %dispatch ( src temp -- )
|
||||||
building get length :> end
|
building get length :> end
|
||||||
! Fix up the displacement above
|
! Fix up the displacement above
|
||||||
cell code-alignment
|
cell code-alignment
|
||||||
[ end start - 2 - + building get dup pop* push ]
|
[ end start - + building get dup pop* push ]
|
||||||
[ align-code ]
|
[ align-code ]
|
||||||
bi ;
|
bi ;
|
||||||
|
|
||||||
|
@ -89,16 +92,16 @@ M: x86.64 %load-param-reg [ swap param@ ] dip %copy ;
|
||||||
] with-scope ; inline
|
] with-scope ; inline
|
||||||
|
|
||||||
M: x86.64 %pop-stack ( n -- )
|
M: x86.64 %pop-stack ( n -- )
|
||||||
param-reg-1 swap ds-reg reg-stack MOV ;
|
param-reg-0 swap ds-reg reg-stack MOV ;
|
||||||
|
|
||||||
M: x86.64 %pop-context-stack ( -- )
|
M: x86.64 %pop-context-stack ( -- )
|
||||||
temp-reg %load-context-datastack
|
temp-reg %load-context-datastack
|
||||||
param-reg-1 temp-reg [] MOV
|
param-reg-0 temp-reg [] MOV
|
||||||
param-reg-1 param-reg-1 [] MOV
|
param-reg-0 param-reg-0 [] MOV
|
||||||
temp-reg [] bootstrap-cell SUB ;
|
temp-reg [] bootstrap-cell SUB ;
|
||||||
|
|
||||||
M:: x86.64 %unbox ( n rep func -- )
|
M:: x86.64 %unbox ( n rep func -- )
|
||||||
param-reg-2 %mov-vm-ptr
|
param-reg-1 %mov-vm-ptr
|
||||||
! Call the unboxer
|
! Call the unboxer
|
||||||
func f %alien-invoke
|
func f %alien-invoke
|
||||||
! Store the return value on the C stack if this is an
|
! Store the return value on the C stack if this is an
|
||||||
|
@ -110,15 +113,15 @@ M: x86.64 %unbox-long-long ( n func -- )
|
||||||
[ int-rep ] dip %unbox ;
|
[ int-rep ] dip %unbox ;
|
||||||
|
|
||||||
: %unbox-struct-field ( c-type i -- )
|
: %unbox-struct-field ( c-type i -- )
|
||||||
! Alien must be in param-reg-1.
|
! Alien must be in param-reg-0.
|
||||||
R11 swap cells [+] swap rep>> reg-class-of {
|
R11 swap cells [+] swap rep>> reg-class-of {
|
||||||
{ int-regs [ int-regs get pop swap MOV ] }
|
{ int-regs [ int-regs get pop swap MOV ] }
|
||||||
{ float-regs [ float-regs get pop swap MOVSD ] }
|
{ float-regs [ float-regs get pop swap MOVSD ] }
|
||||||
} case ;
|
} case ;
|
||||||
|
|
||||||
M: x86.64 %unbox-small-struct ( c-type -- )
|
M: x86.64 %unbox-small-struct ( c-type -- )
|
||||||
! Alien must be in param-reg-1.
|
! Alien must be in param-reg-0.
|
||||||
param-reg-2 %mov-vm-ptr
|
param-reg-1 %mov-vm-ptr
|
||||||
"alien_offset" f %alien-invoke
|
"alien_offset" f %alien-invoke
|
||||||
! Move alien_offset() return value to R11 so that we don't
|
! Move alien_offset() return value to R11 so that we don't
|
||||||
! clobber it.
|
! clobber it.
|
||||||
|
@ -128,12 +131,12 @@ M: x86.64 %unbox-small-struct ( c-type -- )
|
||||||
] with-return-regs ;
|
] with-return-regs ;
|
||||||
|
|
||||||
M:: x86.64 %unbox-large-struct ( n c-type -- )
|
M:: x86.64 %unbox-large-struct ( n c-type -- )
|
||||||
! Source is in param-reg-1
|
! Source is in param-reg-0
|
||||||
! Load destination address into param-reg-2
|
! Load destination address into param-reg-1
|
||||||
param-reg-2 n param@ LEA
|
param-reg-1 n param@ LEA
|
||||||
! Load structure size into param-reg-3
|
! Load structure size into param-reg-2
|
||||||
param-reg-3 c-type heap-size MOV
|
param-reg-2 c-type heap-size MOV
|
||||||
param-reg-4 %mov-vm-ptr
|
param-reg-3 %mov-vm-ptr
|
||||||
! Copy the struct to the C stack
|
! Copy the struct to the C stack
|
||||||
"to_value_struct" f %alien-invoke ;
|
"to_value_struct" f %alien-invoke ;
|
||||||
|
|
||||||
|
@ -151,7 +154,7 @@ M:: x86.64 %box ( n rep func -- )
|
||||||
] [
|
] [
|
||||||
rep load-return-value
|
rep load-return-value
|
||||||
] if
|
] if
|
||||||
rep int-rep? [ param-reg-2 ] [ param-reg-1 ] if %mov-vm-ptr
|
rep int-rep? [ param-reg-1 ] [ param-reg-0 ] if %mov-vm-ptr
|
||||||
func f %alien-invoke ;
|
func f %alien-invoke ;
|
||||||
|
|
||||||
M: x86.64 %box-long-long ( n func -- )
|
M: x86.64 %box-long-long ( n func -- )
|
||||||
|
@ -169,10 +172,10 @@ M: x86.64 %box-small-struct ( c-type -- )
|
||||||
#! Box a <= 16-byte struct.
|
#! Box a <= 16-byte struct.
|
||||||
[
|
[
|
||||||
[ flatten-value-type [ %box-struct-field ] each-index ]
|
[ flatten-value-type [ %box-struct-field ] each-index ]
|
||||||
[ param-reg-3 swap heap-size MOV ] bi
|
[ param-reg-2 swap heap-size MOV ] bi
|
||||||
param-reg-1 0 box-struct-field@ MOV
|
param-reg-0 0 box-struct-field@ MOV
|
||||||
param-reg-2 1 box-struct-field@ MOV
|
param-reg-1 1 box-struct-field@ MOV
|
||||||
param-reg-4 %mov-vm-ptr
|
param-reg-3 %mov-vm-ptr
|
||||||
"from_small_struct" f %alien-invoke
|
"from_small_struct" f %alien-invoke
|
||||||
] with-return-regs ;
|
] with-return-regs ;
|
||||||
|
|
||||||
|
@ -181,10 +184,10 @@ M: x86.64 %box-small-struct ( c-type -- )
|
||||||
|
|
||||||
M: x86.64 %box-large-struct ( n c-type -- )
|
M: x86.64 %box-large-struct ( n c-type -- )
|
||||||
! Struct size is parameter 2
|
! Struct size is parameter 2
|
||||||
param-reg-2 swap heap-size MOV
|
param-reg-1 swap heap-size MOV
|
||||||
! Compute destination address
|
! Compute destination address
|
||||||
param-reg-1 swap struct-return@ LEA
|
param-reg-0 swap struct-return@ LEA
|
||||||
param-reg-3 %mov-vm-ptr
|
param-reg-2 %mov-vm-ptr
|
||||||
! Copy the struct from the C stack
|
! Copy the struct from the C stack
|
||||||
"from_value_struct" f %alien-invoke ;
|
"from_value_struct" f %alien-invoke ;
|
||||||
|
|
||||||
|
@ -202,19 +205,17 @@ M: x86.64 %alien-invoke
|
||||||
R11 CALL ;
|
R11 CALL ;
|
||||||
|
|
||||||
M: x86.64 %nest-stacks ( -- )
|
M: x86.64 %nest-stacks ( -- )
|
||||||
! Save current frame. See comment in vm/contexts.hpp
|
param-reg-0 %mov-vm-ptr
|
||||||
param-reg-1 stack-reg stack-frame get total-size>> 3 cells - [+] LEA
|
|
||||||
param-reg-2 %mov-vm-ptr
|
|
||||||
"nest_stacks" f %alien-invoke ;
|
"nest_stacks" f %alien-invoke ;
|
||||||
|
|
||||||
M: x86.64 %unnest-stacks ( -- )
|
M: x86.64 %unnest-stacks ( -- )
|
||||||
param-reg-1 %mov-vm-ptr
|
param-reg-0 %mov-vm-ptr
|
||||||
"unnest_stacks" f %alien-invoke ;
|
"unnest_stacks" f %alien-invoke ;
|
||||||
|
|
||||||
M: x86.64 %prepare-alien-indirect ( -- )
|
M: x86.64 %prepare-alien-indirect ( -- )
|
||||||
param-reg-1 ds-reg [] MOV
|
param-reg-0 ds-reg [] MOV
|
||||||
ds-reg 8 SUB
|
ds-reg 8 SUB
|
||||||
param-reg-2 %mov-vm-ptr
|
param-reg-1 %mov-vm-ptr
|
||||||
"pinned_alien_offset" f %alien-invoke
|
"pinned_alien_offset" f %alien-invoke
|
||||||
RBP RAX MOV ;
|
RBP RAX MOV ;
|
||||||
|
|
||||||
|
@ -222,19 +223,21 @@ M: x86.64 %alien-indirect ( -- )
|
||||||
RBP CALL ;
|
RBP CALL ;
|
||||||
|
|
||||||
M: x86.64 %alien-callback ( quot -- )
|
M: x86.64 %alien-callback ( quot -- )
|
||||||
param-reg-1 swap %load-reference
|
param-reg-0 param-reg-1 %load-context
|
||||||
param-reg-2 %mov-vm-ptr
|
param-reg-0 swap %load-reference
|
||||||
"c_to_factor" f %alien-invoke ;
|
param-reg-1 %mov-vm-ptr
|
||||||
|
param-reg-0 quot-xt-offset [+] CALL
|
||||||
|
param-reg-0 param-reg-1 %save-context ;
|
||||||
|
|
||||||
M: x86.64 %callback-value ( ctype -- )
|
M: x86.64 %callback-value ( ctype -- )
|
||||||
%pop-context-stack
|
%pop-context-stack
|
||||||
RSP 8 SUB
|
RSP 8 SUB
|
||||||
param-reg-1 PUSH
|
param-reg-0 PUSH
|
||||||
param-reg-1 %mov-vm-ptr
|
param-reg-0 %mov-vm-ptr
|
||||||
! Restore data/call/retain stacks
|
! Restore data/call/retain stacks
|
||||||
"unnest_stacks" f %alien-invoke
|
"unnest_stacks" f %alien-invoke
|
||||||
! Put former top of data stack in param-reg-1
|
! Put former top of data stack in param-reg-0
|
||||||
param-reg-1 POP
|
param-reg-0 POP
|
||||||
RSP 8 ADD
|
RSP 8 ADD
|
||||||
! Unbox former top of data stack to return registers
|
! Unbox former top of data stack to return registers
|
||||||
unbox-return ;
|
unbox-return ;
|
||||||
|
@ -260,11 +263,11 @@ M:: x86.64 %binary-float-function ( dst src1 src2 func -- )
|
||||||
|
|
||||||
M:: x86.64 %call-gc ( gc-root-count temp -- )
|
M:: x86.64 %call-gc ( gc-root-count temp -- )
|
||||||
! Pass pointer to start of GC roots as first parameter
|
! Pass pointer to start of GC roots as first parameter
|
||||||
param-reg-1 gc-root-base param@ LEA
|
param-reg-0 gc-root-base param@ LEA
|
||||||
! Pass number of roots as second parameter
|
! Pass number of roots as second parameter
|
||||||
param-reg-2 gc-root-count MOV
|
param-reg-1 gc-root-count MOV
|
||||||
! Pass VM ptr as third parameter
|
! Pass VM ptr as third parameter
|
||||||
param-reg-3 %mov-vm-ptr
|
param-reg-2 %mov-vm-ptr
|
||||||
! Call GC
|
! Call GC
|
||||||
"inline_gc" f %alien-invoke ;
|
"inline_gc" f %alien-invoke ;
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ IN: bootstrap.x86
|
||||||
: temp3 ( -- reg ) RBX ;
|
: temp3 ( -- reg ) RBX ;
|
||||||
: safe-reg ( -- reg ) RAX ;
|
: safe-reg ( -- reg ) RAX ;
|
||||||
: stack-reg ( -- reg ) RSP ;
|
: stack-reg ( -- reg ) RSP ;
|
||||||
|
: frame-reg ( -- reg ) RBP ;
|
||||||
: ds-reg ( -- reg ) R14 ;
|
: ds-reg ( -- reg ) R14 ;
|
||||||
: rs-reg ( -- reg ) R15 ;
|
: rs-reg ( -- reg ) R15 ;
|
||||||
: fixnum>slot@ ( -- ) temp0 1 SAR ;
|
: fixnum>slot@ ( -- ) temp0 1 SAR ;
|
||||||
|
|
|
@ -6,9 +6,11 @@ sequences system vocabs ;
|
||||||
IN: bootstrap.x86
|
IN: bootstrap.x86
|
||||||
|
|
||||||
: stack-frame-size ( -- n ) 4 bootstrap-cells ;
|
: stack-frame-size ( -- n ) 4 bootstrap-cells ;
|
||||||
|
: nv-regs ( -- seq ) { RBX R12 R13 R14 R15 } ;
|
||||||
: arg1 ( -- reg ) RDI ;
|
: arg1 ( -- reg ) RDI ;
|
||||||
: arg2 ( -- reg ) RSI ;
|
: arg2 ( -- reg ) RSI ;
|
||||||
: arg3 ( -- reg ) RDX ;
|
: arg3 ( -- reg ) RDX ;
|
||||||
|
: arg4 ( -- reg ) RCX ;
|
||||||
|
|
||||||
<< "vocab:cpu/x86/64/bootstrap.factor" parse-file suffix! >>
|
<< "vocab:cpu/x86/64/bootstrap.factor" parse-file suffix! >>
|
||||||
call
|
call
|
||||||
|
|
|
@ -6,9 +6,11 @@ cpu.x86.assembler.operands ;
|
||||||
IN: bootstrap.x86
|
IN: bootstrap.x86
|
||||||
|
|
||||||
: stack-frame-size ( -- n ) 8 bootstrap-cells ;
|
: stack-frame-size ( -- n ) 8 bootstrap-cells ;
|
||||||
|
: nv-regs ( -- seq ) { RBX RSI RDI R12 R13 R14 R15 } ;
|
||||||
: arg1 ( -- reg ) RCX ;
|
: arg1 ( -- reg ) RCX ;
|
||||||
: arg2 ( -- reg ) RDX ;
|
: arg2 ( -- reg ) RDX ;
|
||||||
: arg3 ( -- reg ) R8 ;
|
: arg3 ( -- reg ) R8 ;
|
||||||
|
: arg4 ( -- reg ) R9 ;
|
||||||
|
|
||||||
<< "vocab:cpu/x86/64/bootstrap.factor" parse-file suffix! >>
|
<< "vocab:cpu/x86/64/bootstrap.factor" parse-file suffix! >>
|
||||||
call
|
call
|
||||||
|
|
|
@ -8,6 +8,49 @@ IN: bootstrap.x86
|
||||||
|
|
||||||
big-endian off
|
big-endian off
|
||||||
|
|
||||||
|
! C to Factor entry point
|
||||||
|
[
|
||||||
|
! Optimizing compiler's side of callback accesses
|
||||||
|
! arguments that are on the stack via the frame pointer.
|
||||||
|
! On x86-64, some arguments are passed in registers, and
|
||||||
|
! so the only register that is safe for use here is safe-reg.
|
||||||
|
frame-reg PUSH
|
||||||
|
frame-reg stack-reg MOV
|
||||||
|
|
||||||
|
! Save all non-volatile registers
|
||||||
|
nv-regs [ PUSH ] each
|
||||||
|
|
||||||
|
! Save old stack pointer and align
|
||||||
|
safe-reg stack-reg MOV
|
||||||
|
stack-reg bootstrap-cell SUB
|
||||||
|
stack-reg -16 AND
|
||||||
|
stack-reg [] safe-reg MOV
|
||||||
|
|
||||||
|
! Register shadow area - only required on Win64, but doesn't
|
||||||
|
! hurt on other platforms
|
||||||
|
stack-reg 32 SUB
|
||||||
|
|
||||||
|
! Call into Factor code
|
||||||
|
safe-reg 0 MOV rc-absolute-cell rt-xt jit-rel
|
||||||
|
safe-reg CALL
|
||||||
|
|
||||||
|
! Tear down register shadow area
|
||||||
|
stack-reg 32 ADD
|
||||||
|
|
||||||
|
! Undo stack alignment
|
||||||
|
stack-reg stack-reg [] MOV
|
||||||
|
|
||||||
|
! Restore non-volatile registers
|
||||||
|
nv-regs <reversed> [ POP ] each
|
||||||
|
|
||||||
|
frame-reg POP
|
||||||
|
|
||||||
|
! Callbacks which return structs, or use stdcall, need a
|
||||||
|
! parameter here. See the comment in callback-return-rewind
|
||||||
|
! in cpu.x86.32
|
||||||
|
HEX: ffff RET rc-absolute-2 rt-untagged jit-rel
|
||||||
|
] callback-stub jit-define
|
||||||
|
|
||||||
[
|
[
|
||||||
! Load word
|
! Load word
|
||||||
temp0 0 MOV rc-absolute-cell rt-literal jit-rel
|
temp0 0 MOV rc-absolute-cell rt-literal jit-rel
|
||||||
|
@ -206,11 +249,6 @@ big-endian off
|
||||||
! fall-through on miss
|
! fall-through on miss
|
||||||
] mega-lookup jit-define
|
] mega-lookup jit-define
|
||||||
|
|
||||||
[
|
|
||||||
safe-reg 0 MOV rc-absolute-cell rt-xt jit-rel
|
|
||||||
safe-reg JMP
|
|
||||||
] callback-stub jit-define
|
|
||||||
|
|
||||||
! ! ! Sub-primitives
|
! ! ! Sub-primitives
|
||||||
|
|
||||||
! Objects
|
! Objects
|
||||||
|
|
|
@ -24,6 +24,8 @@ M: x86 vector-regs float-regs ;
|
||||||
|
|
||||||
HOOK: stack-reg cpu ( -- reg )
|
HOOK: stack-reg cpu ( -- reg )
|
||||||
|
|
||||||
|
HOOK: frame-reg cpu ( -- reg )
|
||||||
|
|
||||||
HOOK: reserved-stack-space cpu ( -- n )
|
HOOK: reserved-stack-space cpu ( -- n )
|
||||||
|
|
||||||
HOOK: extra-stack-space cpu ( stack-frame -- n )
|
HOOK: extra-stack-space cpu ( stack-frame -- n )
|
||||||
|
@ -84,7 +86,7 @@ M: x86 %call ( word -- ) 0 CALL rc-relative rel-word-pic ;
|
||||||
|
|
||||||
: xt-tail-pic-offset ( -- n )
|
: xt-tail-pic-offset ( -- n )
|
||||||
#! See the comment in vm/cpu-x86.hpp
|
#! See the comment in vm/cpu-x86.hpp
|
||||||
cell 4 + 1 + ; inline
|
4 1 + ; inline
|
||||||
|
|
||||||
M: x86 %jump ( word -- )
|
M: x86 %jump ( word -- )
|
||||||
pic-tail-reg 0 MOV xt-tail-pic-offset rc-absolute-cell rel-here
|
pic-tail-reg 0 MOV xt-tail-pic-offset rc-absolute-cell rel-here
|
||||||
|
@ -1408,15 +1410,31 @@ M:: x86 %reload ( dst rep src -- ) dst src rep %copy ;
|
||||||
|
|
||||||
M: x86 %loop-entry 16 code-alignment [ NOP ] times ;
|
M: x86 %loop-entry 16 code-alignment [ NOP ] times ;
|
||||||
|
|
||||||
|
M:: x86 %load-context ( temp1 temp2 -- )
|
||||||
|
#! Load Factor stack pointers on entry from C to Factor.
|
||||||
|
#! Also save callstack bottom!
|
||||||
|
temp1 "ctx" %vm-field-ptr
|
||||||
|
temp1 temp1 [] MOV
|
||||||
|
! callstack_bottom
|
||||||
|
temp2 stack-reg stack-frame get total-size>> cell - [+] LEA
|
||||||
|
temp1 1 cells [+] temp2 MOV
|
||||||
|
! datastack
|
||||||
|
ds-reg temp1 2 cells [+] MOV
|
||||||
|
! retainstack
|
||||||
|
rs-reg temp1 3 cells [+] MOV ;
|
||||||
|
|
||||||
M:: x86 %save-context ( temp1 temp2 -- )
|
M:: x86 %save-context ( temp1 temp2 -- )
|
||||||
#! Save Factor stack pointers in case the C code calls a
|
#! Save Factor stack pointers in case the C code calls a
|
||||||
#! callback which does a GC, which must reliably trace
|
#! callback which does a GC, which must reliably trace
|
||||||
#! all roots.
|
#! all roots.
|
||||||
temp1 "ctx" %vm-field-ptr
|
temp1 "ctx" %vm-field-ptr
|
||||||
temp1 temp1 [] MOV
|
temp1 temp1 [] MOV
|
||||||
|
! callstack_top
|
||||||
temp2 stack-reg cell neg [+] LEA
|
temp2 stack-reg cell neg [+] LEA
|
||||||
temp1 [] temp2 MOV
|
temp1 [] temp2 MOV
|
||||||
|
! datastack
|
||||||
temp1 2 cells [+] ds-reg MOV
|
temp1 2 cells [+] ds-reg MOV
|
||||||
|
! retainstack
|
||||||
temp1 3 cells [+] rs-reg MOV ;
|
temp1 3 cells [+] rs-reg MOV ;
|
||||||
|
|
||||||
M: x86 value-struct? drop t ;
|
M: x86 value-struct? drop t ;
|
||||||
|
@ -1432,7 +1450,7 @@ M: x86 immediate-bitwise? ( n -- ? )
|
||||||
#! input values to callbacks; the callback has its own
|
#! input values to callbacks; the callback has its own
|
||||||
#! stack frame set up, and we want to read the frame
|
#! stack frame set up, and we want to read the frame
|
||||||
#! set up by the caller.
|
#! set up by the caller.
|
||||||
stack-frame get total-size>> + stack@ ;
|
frame-reg swap 2 cells + [+] ;
|
||||||
|
|
||||||
enable-min/max
|
enable-min/max
|
||||||
enable-fixnum-log2
|
enable-fixnum-log2
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
! Copyright (C) 2008, 2009 Slava Pestov.
|
! Copyright (C) 2008, 2010 Slava Pestov.
|
||||||
! See http://factorcode.org/license.txt for BSD license.
|
! See http://factorcode.org/license.txt for BSD license.
|
||||||
USING: kernel sequences accessors combinators math namespaces
|
USING: kernel sequences accessors combinators math namespaces
|
||||||
init sets words assocs alien.libraries alien alien.c-types
|
init sets words assocs alien.libraries alien alien.c-types
|
||||||
stack-checker.backend stack-checker.errors stack-checker.visitor ;
|
cpu.architecture fry stack-checker.backend stack-checker.errors
|
||||||
|
stack-checker.visitor ;
|
||||||
IN: stack-checker.alien
|
IN: stack-checker.alien
|
||||||
|
|
||||||
TUPLE: alien-node-params return parameters abi in-d out-d ;
|
TUPLE: alien-node-params return parameters abi in-d out-d ;
|
||||||
|
@ -49,7 +50,7 @@ TUPLE: alien-callback-params < alien-node-params quot xt ;
|
||||||
pop-literal nip >>parameters
|
pop-literal nip >>parameters
|
||||||
pop-literal nip >>return
|
pop-literal nip >>return
|
||||||
! Quotation which coerces parameters to required types
|
! Quotation which coerces parameters to required types
|
||||||
dup param-prep-quot [ dip ] curry infer-quot-here
|
dup param-prep-quot '[ _ dip ] infer-quot-here
|
||||||
! Magic #: consume the function pointer, too
|
! Magic #: consume the function pointer, too
|
||||||
dup 1 alien-stack
|
dup 1 alien-stack
|
||||||
! Add node to IR
|
! Add node to IR
|
||||||
|
@ -57,11 +58,12 @@ TUPLE: alien-callback-params < alien-node-params quot xt ;
|
||||||
! Quotation which coerces return value to required type
|
! Quotation which coerces return value to required type
|
||||||
return-prep-quot infer-quot-here ;
|
return-prep-quot infer-quot-here ;
|
||||||
|
|
||||||
: callback-xt ( word -- alien )
|
: callback-xt ( word return-rewind -- alien )
|
||||||
callbacks get [ <callback> ] cache ;
|
[ callbacks get ] dip '[ _ <callback> ] cache ;
|
||||||
|
|
||||||
: callback-bottom ( params -- )
|
: callback-bottom ( params -- )
|
||||||
xt>> [ callback-xt ] curry infer-quot-here ;
|
[ xt>> ] [ callback-return-rewind ] bi
|
||||||
|
'[ _ _ callback-xt ] infer-quot-here ;
|
||||||
|
|
||||||
: infer-alien-callback ( -- )
|
: infer-alien-callback ( -- )
|
||||||
alien-callback-params new
|
alien-callback-params new
|
||||||
|
|
|
@ -709,7 +709,7 @@ M: bad-executable summary
|
||||||
|
|
||||||
\ strip-stack-traces { } { } define-primitive
|
\ strip-stack-traces { } { } define-primitive
|
||||||
|
|
||||||
\ <callback> { word } { alien } define-primitive
|
\ <callback> { integer word } { alien } define-primitive
|
||||||
|
|
||||||
\ enable-gc-events { } { } define-primitive
|
\ enable-gc-events { } { } define-primitive
|
||||||
\ disable-gc-events { } { object } define-primitive
|
\ disable-gc-events { } { object } define-primitive
|
||||||
|
|
|
@ -518,7 +518,7 @@ tuple
|
||||||
{ "quot-compiled?" "quotations" (( quot -- ? )) }
|
{ "quot-compiled?" "quotations" (( quot -- ? )) }
|
||||||
{ "vm-ptr" "vm" (( -- ptr )) }
|
{ "vm-ptr" "vm" (( -- ptr )) }
|
||||||
{ "strip-stack-traces" "kernel.private" (( -- )) }
|
{ "strip-stack-traces" "kernel.private" (( -- )) }
|
||||||
{ "<callback>" "alien" (( word -- alien )) }
|
{ "<callback>" "alien" (( return-rewind word -- alien )) }
|
||||||
{ "enable-gc-events" "memory" (( -- )) }
|
{ "enable-gc-events" "memory" (( -- )) }
|
||||||
{ "disable-gc-events" "memory" (( -- events )) }
|
{ "disable-gc-events" "memory" (( -- events )) }
|
||||||
{ "(identity-hashcode)" "kernel.private" (( obj -- code )) }
|
{ "(identity-hashcode)" "kernel.private" (( obj -- code )) }
|
||||||
|
|
|
@ -38,7 +38,7 @@ void callback_heap::update(code_block *stub)
|
||||||
stub->flush_icache();
|
stub->flush_icache();
|
||||||
}
|
}
|
||||||
|
|
||||||
code_block *callback_heap::add(cell owner)
|
code_block *callback_heap::add(cell owner, cell return_rewind)
|
||||||
{
|
{
|
||||||
tagged<array> code_template(parent->special_objects[CALLBACK_STUB]);
|
tagged<array> code_template(parent->special_objects[CALLBACK_STUB]);
|
||||||
tagged<byte_array> insns(array_nth(code_template.untagged(),0));
|
tagged<byte_array> insns(array_nth(code_template.untagged(),0));
|
||||||
|
@ -57,6 +57,24 @@ code_block *callback_heap::add(cell owner)
|
||||||
stub->relocation = false_object;
|
stub->relocation = false_object;
|
||||||
|
|
||||||
memcpy(stub->xt(),insns->data<void>(),size);
|
memcpy(stub->xt(),insns->data<void>(),size);
|
||||||
|
|
||||||
|
/* On x86, the RET instruction takes an argument which depends on
|
||||||
|
the callback's calling convention */
|
||||||
|
if(array_capacity(code_template.untagged()) == 7)
|
||||||
|
{
|
||||||
|
cell rel_class = untag_fixnum(array_nth(code_template.untagged(),4));
|
||||||
|
cell rel_type = untag_fixnum(array_nth(code_template.untagged(),5));
|
||||||
|
cell offset = untag_fixnum(array_nth(code_template.untagged(),6));
|
||||||
|
|
||||||
|
relocation_entry rel(
|
||||||
|
(relocation_type)rel_type,
|
||||||
|
(relocation_class)rel_class,
|
||||||
|
offset);
|
||||||
|
|
||||||
|
instruction_operand op(rel,stub,0);
|
||||||
|
op.store_value(return_rewind);
|
||||||
|
}
|
||||||
|
|
||||||
update(stub);
|
update(stub);
|
||||||
|
|
||||||
return stub;
|
return stub;
|
||||||
|
@ -81,9 +99,11 @@ void callback_heap::update()
|
||||||
|
|
||||||
void factor_vm::primitive_callback()
|
void factor_vm::primitive_callback()
|
||||||
{
|
{
|
||||||
|
cell return_rewind = to_cell(ctx->pop());
|
||||||
tagged<word> w(ctx->pop());
|
tagged<word> w(ctx->pop());
|
||||||
|
|
||||||
w.untag_check(this);
|
w.untag_check(this);
|
||||||
ctx->push(allot_alien(callbacks->add(w.value())->xt()));
|
ctx->push(allot_alien(callbacks->add(w.value(),return_rewind)->xt()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ struct callback_heap {
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(code_block *stub);
|
void update(code_block *stub);
|
||||||
code_block *add(cell owner);
|
code_block *add(cell owner, cell return_rewind);
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ context::context(cell ds_size, cell rs_size) :
|
||||||
callstack_bottom(NULL),
|
callstack_bottom(NULL),
|
||||||
datastack(0),
|
datastack(0),
|
||||||
retainstack(0),
|
retainstack(0),
|
||||||
magic_frame(NULL),
|
|
||||||
datastack_region(new segment(ds_size,false)),
|
datastack_region(new segment(ds_size,false)),
|
||||||
retainstack_region(new segment(rs_size,false)),
|
retainstack_region(new segment(rs_size,false)),
|
||||||
catchstack_save(0),
|
catchstack_save(0),
|
||||||
|
@ -41,15 +40,13 @@ void factor_vm::dealloc_context(context *old_context)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* called on entry into a compiled callback */
|
/* called on entry into a compiled callback */
|
||||||
void factor_vm::nest_stacks(stack_frame *magic_frame)
|
void factor_vm::nest_stacks()
|
||||||
{
|
{
|
||||||
context *new_ctx = alloc_context();
|
context *new_ctx = alloc_context();
|
||||||
|
|
||||||
new_ctx->callstack_bottom = (stack_frame *)-1;
|
new_ctx->callstack_bottom = (stack_frame *)-1;
|
||||||
new_ctx->callstack_top = (stack_frame *)-1;
|
new_ctx->callstack_top = (stack_frame *)-1;
|
||||||
|
|
||||||
new_ctx->magic_frame = magic_frame;
|
|
||||||
|
|
||||||
/* save per-callback special_objects */
|
/* save per-callback special_objects */
|
||||||
new_ctx->current_callback_save = special_objects[OBJ_CURRENT_CALLBACK];
|
new_ctx->current_callback_save = special_objects[OBJ_CURRENT_CALLBACK];
|
||||||
new_ctx->catchstack_save = special_objects[OBJ_CATCHSTACK];
|
new_ctx->catchstack_save = special_objects[OBJ_CATCHSTACK];
|
||||||
|
@ -61,9 +58,9 @@ void factor_vm::nest_stacks(stack_frame *magic_frame)
|
||||||
ctx = new_ctx;
|
ctx = new_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nest_stacks(stack_frame *magic_frame, factor_vm *parent)
|
void nest_stacks(factor_vm *parent)
|
||||||
{
|
{
|
||||||
return parent->nest_stacks(magic_frame);
|
return parent->nest_stacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* called when leaving a compiled callback */
|
/* called when leaving a compiled callback */
|
||||||
|
|
|
@ -13,18 +13,6 @@ struct context {
|
||||||
/* current retain stack top pointer */
|
/* current retain stack top pointer */
|
||||||
cell retainstack;
|
cell retainstack;
|
||||||
|
|
||||||
/* callback-bottom stack frame, or NULL for top-level context.
|
|
||||||
When nest_stacks() is called, callstack layout with callbacks
|
|
||||||
is as follows:
|
|
||||||
|
|
||||||
[ C function ]
|
|
||||||
[ callback stub in code heap ] <-- this is the magic frame
|
|
||||||
[ native frame: c_to_factor() ]
|
|
||||||
[ callback quotation frame ] <-- first call frame in call stack
|
|
||||||
|
|
||||||
magic frame is retained so that it's XT can be traced and forwarded. */
|
|
||||||
stack_frame *magic_frame;
|
|
||||||
|
|
||||||
/* memory region holding current datastack */
|
/* memory region holding current datastack */
|
||||||
segment *datastack_region;
|
segment *datastack_region;
|
||||||
|
|
||||||
|
@ -86,7 +74,7 @@ struct context {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
VM_C_API void nest_stacks(stack_frame *magic_frame, factor_vm *vm);
|
VM_C_API void nest_stacks(factor_vm *vm);
|
||||||
VM_C_API void unnest_stacks(factor_vm *vm);
|
VM_C_API void unnest_stacks(factor_vm *vm);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,9 @@ DEF(void,c_to_factor,(cell quot, void *vm)):
|
||||||
push %edi
|
push %edi
|
||||||
|
|
||||||
/* Save old stack pointer and align */
|
/* Save old stack pointer and align */
|
||||||
mov %esp,%ebp
|
mov %esp,%ebx
|
||||||
and $-16,%esp
|
and $-16,%esp
|
||||||
push %ebp
|
push %ebx
|
||||||
|
|
||||||
/* Set up stack frame for the call to the boot quotation */
|
/* Set up stack frame for the call to the boot quotation */
|
||||||
sub $4,%esp
|
sub $4,%esp
|
||||||
|
@ -49,8 +49,7 @@ DEF(void,c_to_factor,(cell quot, void *vm)):
|
||||||
add $4,%esp
|
add $4,%esp
|
||||||
|
|
||||||
/* Undo stack alignment */
|
/* Undo stack alignment */
|
||||||
pop %ebp
|
mov (%esp),%esp
|
||||||
mov %ebp,%esp
|
|
||||||
|
|
||||||
/* Load context */
|
/* Load context */
|
||||||
mov (%edx),%ecx
|
mov (%edx),%ecx
|
||||||
|
|
|
@ -15,7 +15,7 @@ inline static void flush_icache(cell start, cell len) {}
|
||||||
the offset from the immediate operand to MOV to the instruction after
|
the offset from the immediate operand to MOV to the instruction after
|
||||||
the jump is a cell for the immediate operand, 4 bytes for the JMP
|
the jump is a cell for the immediate operand, 4 bytes for the JMP
|
||||||
destination, and one byte for the JMP opcode. */
|
destination, and one byte for the JMP opcode. */
|
||||||
static const fixnum xt_tail_pic_offset = sizeof(cell) + 4 + 1;
|
static const fixnum xt_tail_pic_offset = 4 + 1;
|
||||||
|
|
||||||
static const unsigned char call_opcode = 0xe8;
|
static const unsigned char call_opcode = 0xe8;
|
||||||
static const unsigned char jmp_opcode = 0xe9;
|
static const unsigned char jmp_opcode = 0xe9;
|
||||||
|
|
|
@ -164,14 +164,14 @@ void factor_vm::start_factor(vm_parameters *p)
|
||||||
{
|
{
|
||||||
if(p->fep) factorbug();
|
if(p->fep) factorbug();
|
||||||
|
|
||||||
nest_stacks(NULL);
|
nest_stacks();
|
||||||
c_to_factor_toplevel(special_objects[OBJ_STARTUP_QUOT]);
|
c_to_factor_toplevel(special_objects[OBJ_STARTUP_QUOT]);
|
||||||
unnest_stacks();
|
unnest_stacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::stop_factor()
|
void factor_vm::stop_factor()
|
||||||
{
|
{
|
||||||
nest_stacks(NULL);
|
nest_stacks();
|
||||||
c_to_factor_toplevel(special_objects[OBJ_SHUTDOWN_QUOT]);
|
c_to_factor_toplevel(special_objects[OBJ_SHUTDOWN_QUOT]);
|
||||||
unnest_stacks();
|
unnest_stacks();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,17 +10,17 @@ instruction_operand::instruction_operand(relocation_entry rel_, code_block *comp
|
||||||
fixnum instruction_operand::load_value_2_2()
|
fixnum instruction_operand::load_value_2_2()
|
||||||
{
|
{
|
||||||
cell *ptr = (cell *)pointer;
|
cell *ptr = (cell *)pointer;
|
||||||
cell hi = (ptr[-1] & 0xffff);
|
cell hi = (ptr[-2] & 0xffff);
|
||||||
cell lo = (ptr[ 0] & 0xffff);
|
cell lo = (ptr[-1] & 0xffff);
|
||||||
return hi << 16 | lo;
|
return hi << 16 | lo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load a value from a bitfield of a PowerPC instruction */
|
/* Load a value from a bitfield of a PowerPC instruction */
|
||||||
fixnum instruction_operand::load_value_masked(cell mask, cell bits, cell shift)
|
fixnum instruction_operand::load_value_masked(cell mask, cell bits, cell shift)
|
||||||
{
|
{
|
||||||
fixnum *ptr = (fixnum *)pointer;
|
s32 *ptr = (s32 *)(pointer - sizeof(u32));
|
||||||
|
|
||||||
return (((*ptr & (fixnum)mask) << bits) >> bits) << shift;
|
return (((*ptr & (s32)mask) << bits) >> bits) << shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
fixnum instruction_operand::load_value(cell relative_to)
|
fixnum instruction_operand::load_value(cell relative_to)
|
||||||
|
@ -28,11 +28,11 @@ fixnum instruction_operand::load_value(cell relative_to)
|
||||||
switch(rel.rel_class())
|
switch(rel.rel_class())
|
||||||
{
|
{
|
||||||
case RC_ABSOLUTE_CELL:
|
case RC_ABSOLUTE_CELL:
|
||||||
return *(cell *)pointer;
|
return *(cell *)(pointer - sizeof(cell));
|
||||||
case RC_ABSOLUTE:
|
case RC_ABSOLUTE:
|
||||||
return *(u32*)pointer;
|
return *(u32 *)(pointer - sizeof(u32));
|
||||||
case RC_RELATIVE:
|
case RC_RELATIVE:
|
||||||
return *(s32*)pointer + relative_to + sizeof(u32);
|
return *(s32 *)(pointer - sizeof(u32)) + relative_to;
|
||||||
case RC_ABSOLUTE_PPC_2_2:
|
case RC_ABSOLUTE_PPC_2_2:
|
||||||
return load_value_2_2();
|
return load_value_2_2();
|
||||||
case RC_ABSOLUTE_PPC_2:
|
case RC_ABSOLUTE_PPC_2:
|
||||||
|
@ -42,11 +42,13 @@ fixnum instruction_operand::load_value(cell relative_to)
|
||||||
case RC_RELATIVE_PPC_3:
|
case RC_RELATIVE_PPC_3:
|
||||||
return load_value_masked(rel_relative_ppc_3_mask,6,0) + relative_to;
|
return load_value_masked(rel_relative_ppc_3_mask,6,0) + relative_to;
|
||||||
case RC_RELATIVE_ARM_3:
|
case RC_RELATIVE_ARM_3:
|
||||||
return load_value_masked(rel_relative_arm_3_mask,6,2) + relative_to + sizeof(cell) * 2;
|
return load_value_masked(rel_relative_arm_3_mask,6,2) + relative_to + sizeof(cell);
|
||||||
case RC_INDIRECT_ARM:
|
case RC_INDIRECT_ARM:
|
||||||
return load_value_masked(rel_indirect_arm_mask,20,0) + relative_to + sizeof(cell);
|
return load_value_masked(rel_indirect_arm_mask,20,0) + relative_to;
|
||||||
case RC_INDIRECT_ARM_PC:
|
case RC_INDIRECT_ARM_PC:
|
||||||
return load_value_masked(rel_indirect_arm_mask,20,0) + relative_to + sizeof(cell) * 2;
|
return load_value_masked(rel_indirect_arm_mask,20,0) + relative_to + sizeof(cell);
|
||||||
|
case RC_ABSOLUTE_2:
|
||||||
|
return *(u16 *)(pointer - sizeof(u16));
|
||||||
default:
|
default:
|
||||||
critical_error("Bad rel class",rel.rel_class());
|
critical_error("Bad rel class",rel.rel_class());
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -72,14 +74,14 @@ code_block *instruction_operand::load_code_block()
|
||||||
void instruction_operand::store_value_2_2(fixnum value)
|
void instruction_operand::store_value_2_2(fixnum value)
|
||||||
{
|
{
|
||||||
cell *ptr = (cell *)pointer;
|
cell *ptr = (cell *)pointer;
|
||||||
ptr[-1] = ((ptr[-1] & ~0xffff) | ((value >> 16) & 0xffff));
|
ptr[-2] = ((ptr[-2] & ~0xffff) | ((value >> 16) & 0xffff));
|
||||||
ptr[ 0] = ((ptr[ 0] & ~0xffff) | (value & 0xffff));
|
ptr[-1] = ((ptr[-1] & ~0xffff) | (value & 0xffff));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store a value into a bitfield of a PowerPC instruction */
|
/* Store a value into a bitfield of a PowerPC instruction */
|
||||||
void instruction_operand::store_value_masked(fixnum value, cell mask, cell shift)
|
void instruction_operand::store_value_masked(fixnum value, cell mask, cell shift)
|
||||||
{
|
{
|
||||||
cell *ptr = (cell *)pointer;
|
u32 *ptr = (u32 *)(pointer - sizeof(u32));
|
||||||
*ptr = ((*ptr & ~mask) | ((value >> shift) & mask));
|
*ptr = ((*ptr & ~mask) | ((value >> shift) & mask));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,13 +92,13 @@ void instruction_operand::store_value(fixnum absolute_value)
|
||||||
switch(rel.rel_class())
|
switch(rel.rel_class())
|
||||||
{
|
{
|
||||||
case RC_ABSOLUTE_CELL:
|
case RC_ABSOLUTE_CELL:
|
||||||
*(cell *)pointer = absolute_value;
|
*(cell *)(pointer - sizeof(cell)) = absolute_value;
|
||||||
break;
|
break;
|
||||||
case RC_ABSOLUTE:
|
case RC_ABSOLUTE:
|
||||||
*(u32*)pointer = absolute_value;
|
*(u32 *)(pointer - sizeof(u32)) = absolute_value;
|
||||||
break;
|
break;
|
||||||
case RC_RELATIVE:
|
case RC_RELATIVE:
|
||||||
*(s32*)pointer = relative_value - sizeof(u32);
|
*(s32 *)(pointer - sizeof(s32)) = relative_value;
|
||||||
break;
|
break;
|
||||||
case RC_ABSOLUTE_PPC_2_2:
|
case RC_ABSOLUTE_PPC_2_2:
|
||||||
store_value_2_2(absolute_value);
|
store_value_2_2(absolute_value);
|
||||||
|
@ -111,13 +113,16 @@ void instruction_operand::store_value(fixnum absolute_value)
|
||||||
store_value_masked(relative_value,rel_relative_ppc_3_mask,0);
|
store_value_masked(relative_value,rel_relative_ppc_3_mask,0);
|
||||||
break;
|
break;
|
||||||
case RC_RELATIVE_ARM_3:
|
case RC_RELATIVE_ARM_3:
|
||||||
store_value_masked(relative_value - sizeof(cell) * 2,rel_relative_arm_3_mask,2);
|
store_value_masked(relative_value - sizeof(cell),rel_relative_arm_3_mask,2);
|
||||||
break;
|
break;
|
||||||
case RC_INDIRECT_ARM:
|
case RC_INDIRECT_ARM:
|
||||||
store_value_masked(relative_value - sizeof(cell),rel_indirect_arm_mask,0);
|
store_value_masked(relative_value,rel_indirect_arm_mask,0);
|
||||||
break;
|
break;
|
||||||
case RC_INDIRECT_ARM_PC:
|
case RC_INDIRECT_ARM_PC:
|
||||||
store_value_masked(relative_value - sizeof(cell) * 2,rel_indirect_arm_mask,0);
|
store_value_masked(relative_value - sizeof(cell),rel_indirect_arm_mask,0);
|
||||||
|
break;
|
||||||
|
case RC_ABSOLUTE_2:
|
||||||
|
*(u16 *)(pointer - sizeof(u16)) = absolute_value;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
critical_error("Bad rel class",rel.rel_class());
|
critical_error("Bad rel class",rel.rel_class());
|
||||||
|
|
|
@ -54,7 +54,9 @@ enum relocation_class {
|
||||||
/* pointer to address in an ARM LDR/STR instruction */
|
/* pointer to address in an ARM LDR/STR instruction */
|
||||||
RC_INDIRECT_ARM,
|
RC_INDIRECT_ARM,
|
||||||
/* pointer to address in an ARM LDR/STR instruction offset by 8 bytes */
|
/* pointer to address in an ARM LDR/STR instruction offset by 8 bytes */
|
||||||
RC_INDIRECT_ARM_PC
|
RC_INDIRECT_ARM_PC,
|
||||||
|
/* absolute address in a 16-bit location */
|
||||||
|
RC_ABSOLUTE_2
|
||||||
};
|
};
|
||||||
|
|
||||||
static const cell rel_absolute_ppc_2_mask = 0xffff;
|
static const cell rel_absolute_ppc_2_mask = 0xffff;
|
||||||
|
|
|
@ -94,7 +94,7 @@ struct factor_vm
|
||||||
// contexts
|
// contexts
|
||||||
context *alloc_context();
|
context *alloc_context();
|
||||||
void dealloc_context(context *old_context);
|
void dealloc_context(context *old_context);
|
||||||
void nest_stacks(stack_frame *magic_frame);
|
void nest_stacks();
|
||||||
void unnest_stacks();
|
void unnest_stacks();
|
||||||
void init_stacks(cell ds_size_, cell rs_size_);
|
void init_stacks(cell ds_size_, cell rs_size_);
|
||||||
bool stack_to_array(cell bottom, cell top);
|
bool stack_to_array(cell bottom, cell top);
|
||||||
|
@ -113,7 +113,6 @@ struct factor_vm
|
||||||
while(ctx)
|
while(ctx)
|
||||||
{
|
{
|
||||||
iterate_callstack(ctx,iter);
|
iterate_callstack(ctx,iter);
|
||||||
if(ctx->magic_frame) iter(ctx->magic_frame);
|
|
||||||
ctx = ctx->next;
|
ctx = ctx->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue