Merge branch 'eliminating_register_variables'

db4
Slava Pestov 2009-12-27 01:29:53 +13:00
commit 4d70649914
74 changed files with 1079 additions and 959 deletions

View File

@ -344,7 +344,7 @@ SYMBOLS:
bootstrap-cell >>align bootstrap-cell >>align
bootstrap-cell >>align-first bootstrap-cell >>align-first
[ >c-ptr ] >>unboxer-quot [ >c-ptr ] >>unboxer-quot
"box_alien" >>boxer "allot_alien" >>boxer
"alien_offset" >>unboxer "alien_offset" >>unboxer
\ void* define-primitive-type \ void* define-primitive-type
@ -355,7 +355,7 @@ SYMBOLS:
[ set-alien-signed-8 ] >>setter [ set-alien-signed-8 ] >>setter
8 >>size 8 >>size
8-byte-alignment 8-byte-alignment
"box_signed_8" >>boxer "from_signed_8" >>boxer
"to_signed_8" >>unboxer "to_signed_8" >>unboxer
\ longlong define-primitive-type \ longlong define-primitive-type
@ -366,7 +366,7 @@ SYMBOLS:
[ set-alien-unsigned-8 ] >>setter [ set-alien-unsigned-8 ] >>setter
8 >>size 8 >>size
8-byte-alignment 8-byte-alignment
"box_unsigned_8" >>boxer "from_unsigned_8" >>boxer
"to_unsigned_8" >>unboxer "to_unsigned_8" >>unboxer
\ ulonglong define-primitive-type \ ulonglong define-primitive-type
@ -378,7 +378,7 @@ SYMBOLS:
bootstrap-cell >>size bootstrap-cell >>size
bootstrap-cell >>align bootstrap-cell >>align
bootstrap-cell >>align-first bootstrap-cell >>align-first
"box_signed_cell" >>boxer "from_signed_cell" >>boxer
"to_fixnum" >>unboxer "to_fixnum" >>unboxer
\ long define-primitive-type \ long define-primitive-type
@ -390,7 +390,7 @@ SYMBOLS:
bootstrap-cell >>size bootstrap-cell >>size
bootstrap-cell >>align bootstrap-cell >>align
bootstrap-cell >>align-first bootstrap-cell >>align-first
"box_unsigned_cell" >>boxer "from_unsigned_cell" >>boxer
"to_cell" >>unboxer "to_cell" >>unboxer
\ ulong define-primitive-type \ ulong define-primitive-type
@ -402,7 +402,7 @@ SYMBOLS:
4 >>size 4 >>size
4 >>align 4 >>align
4 >>align-first 4 >>align-first
"box_signed_4" >>boxer "from_signed_4" >>boxer
"to_fixnum" >>unboxer "to_fixnum" >>unboxer
\ int define-primitive-type \ int define-primitive-type
@ -414,7 +414,7 @@ SYMBOLS:
4 >>size 4 >>size
4 >>align 4 >>align
4 >>align-first 4 >>align-first
"box_unsigned_4" >>boxer "from_unsigned_4" >>boxer
"to_cell" >>unboxer "to_cell" >>unboxer
\ uint define-primitive-type \ uint define-primitive-type
@ -426,7 +426,7 @@ SYMBOLS:
2 >>size 2 >>size
2 >>align 2 >>align
2 >>align-first 2 >>align-first
"box_signed_2" >>boxer "from_signed_2" >>boxer
"to_fixnum" >>unboxer "to_fixnum" >>unboxer
\ short define-primitive-type \ short define-primitive-type
@ -438,7 +438,7 @@ SYMBOLS:
2 >>size 2 >>size
2 >>align 2 >>align
2 >>align-first 2 >>align-first
"box_unsigned_2" >>boxer "from_unsigned_2" >>boxer
"to_cell" >>unboxer "to_cell" >>unboxer
\ ushort define-primitive-type \ ushort define-primitive-type
@ -450,7 +450,7 @@ SYMBOLS:
1 >>size 1 >>size
1 >>align 1 >>align
1 >>align-first 1 >>align-first
"box_signed_1" >>boxer "from_signed_1" >>boxer
"to_fixnum" >>unboxer "to_fixnum" >>unboxer
\ char define-primitive-type \ char define-primitive-type
@ -462,7 +462,7 @@ SYMBOLS:
1 >>size 1 >>size
1 >>align 1 >>align
1 >>align-first 1 >>align-first
"box_unsigned_1" >>boxer "from_unsigned_1" >>boxer
"to_cell" >>unboxer "to_cell" >>unboxer
\ uchar define-primitive-type \ uchar define-primitive-type
@ -473,7 +473,7 @@ SYMBOLS:
4 >>size 4 >>size
4 >>align 4 >>align
4 >>align-first 4 >>align-first
"box_boolean" >>boxer "from_boolean" >>boxer
"to_boolean" >>unboxer "to_boolean" >>unboxer
] [ ] [
<c-type> <c-type>
@ -482,7 +482,7 @@ SYMBOLS:
1 >>size 1 >>size
1 >>align 1 >>align
1 >>align-first 1 >>align-first
"box_boolean" >>boxer "from_boolean" >>boxer
"to_boolean" >>unboxer "to_boolean" >>unboxer
] if ] if
\ bool define-primitive-type \ bool define-primitive-type
@ -495,7 +495,7 @@ SYMBOLS:
4 >>size 4 >>size
4 >>align 4 >>align
4 >>align-first 4 >>align-first
"box_float" >>boxer "from_float" >>boxer
"to_float" >>unboxer "to_float" >>unboxer
float-rep >>rep float-rep >>rep
[ >float ] >>unboxer-quot [ >float ] >>unboxer-quot
@ -508,7 +508,7 @@ SYMBOLS:
[ [ >float ] 2dip set-alien-double ] >>setter [ [ >float ] 2dip set-alien-double ] >>setter
8 >>size 8 >>size
8-byte-alignment 8-byte-alignment
"box_double" >>boxer "from_double" >>boxer
"to_double" >>unboxer "to_double" >>unboxer
double-rep >>rep double-rep >>rep
[ >float ] >>unboxer-quot [ >float ] >>unboxer-quot

View File

@ -748,8 +748,7 @@ temp: temp1/int-rep temp2/int-rep
literal: size data-values tagged-values uninitialized-locs ; literal: size data-values tagged-values uninitialized-locs ;
INSN: ##save-context INSN: ##save-context
temp: temp1/int-rep temp2/int-rep temp: temp1/int-rep temp2/int-rep ;
literal: callback-allowed? ;
! Instructions used by machine IR only. ! Instructions used by machine IR only.
INSN: _prologue INSN: _prologue

View File

@ -15,7 +15,7 @@ V{
[ [
V{ V{
T{ ##save-context f 1 2 f } T{ ##save-context f 1 2 }
T{ ##unary-float-function f 2 3 "sqrt" } T{ ##unary-float-function f 2 3 "sqrt" }
T{ ##branch } T{ ##branch }
} }

View File

@ -17,19 +17,10 @@ IN: compiler.cfg.save-contexts
} 1|| } 1||
] any? ; ] any? ;
: needs-callback-context? ( insns -- ? )
[
{
[ ##alien-invoke? ]
[ ##alien-indirect? ]
} 1||
] any? ;
: insert-save-context ( bb -- ) : insert-save-context ( bb -- )
dup instructions>> dup needs-save-context? [ dup instructions>> dup needs-save-context? [
int-rep next-vreg-rep int-rep next-vreg-rep
int-rep next-vreg-rep int-rep next-vreg-rep
pick needs-callback-context?
\ ##save-context new-insn prefix \ ##save-context new-insn prefix
>>instructions drop >>instructions drop
] [ 2drop ] if ; ] [ 2drop ] if ;

View File

@ -283,7 +283,7 @@ M: ##gc generate-insn
[ [ uninitialized-locs>> ] [ temp1>> ] bi wipe-locs ] [ [ uninitialized-locs>> ] [ temp1>> ] bi wipe-locs ]
[ data-values>> save-data-regs ] [ data-values>> save-data-regs ]
[ [ tagged-values>> ] [ temp1>> ] bi save-gc-roots ] [ [ tagged-values>> ] [ temp1>> ] bi save-gc-roots ]
[ [ temp1>> ] [ temp2>> ] bi t %save-context ] [ [ temp1>> ] [ temp2>> ] bi %save-context ]
[ [ tagged-values>> length ] [ temp1>> ] bi %call-gc ] [ [ tagged-values>> length ] [ temp1>> ] bi %call-gc ]
[ [ tagged-values>> ] [ temp1>> ] bi load-gc-roots ] [ [ tagged-values>> ] [ temp1>> ] bi load-gc-roots ]
[ data-values>> load-data-regs ] [ data-values>> load-data-regs ]
@ -384,7 +384,7 @@ M: c-type-name flatten-value-type c-type flatten-value-type ;
: unbox-parameters ( offset node -- ) : unbox-parameters ( offset node -- )
parameters>> swap parameters>> swap
'[ prepare-unbox-parameters [ %prepare-unbox [ _ + ] dip unbox-parameter ] 3each ] '[ prepare-unbox-parameters [ %pop-stack [ _ + ] dip unbox-parameter ] 3each ]
[ length neg %inc-d ] [ length neg %inc-d ]
bi ; bi ;
@ -407,7 +407,7 @@ M: c-type-name flatten-value-type c-type flatten-value-type ;
] with-param-regs ; ] with-param-regs ;
: box-return* ( node -- ) : box-return* ( node -- )
return>> [ ] [ box-return ] if-void ; return>> [ ] [ box-return %push-stack ] if-void ;
: check-dlsym ( symbols dll -- ) : check-dlsym ( symbols dll -- )
dup dll-valid? [ dup dll-valid? [
@ -452,7 +452,7 @@ M: ##alien-indirect generate-insn
! ##alien-callback ! ##alien-callback
: box-parameters ( params -- ) : box-parameters ( params -- )
alien-parameters [ box-parameter ] each-parameter ; alien-parameters [ box-parameter %push-context-stack ] each-parameter ;
: registers>objects ( node -- ) : registers>objects ( node -- )
! Generate code for boxing input parameters in a callback. ! Generate code for boxing input parameters in a callback.

View File

@ -94,6 +94,8 @@ FUNCTION: TINY ffi_test_17 int x ;
{ 1 1 } [ indirect-test-1 ] must-infer-as { 1 1 } [ indirect-test-1 ] must-infer-as
[ B{ } indirect-test-1 ] [ { "kernel-error" 3 6 B{ } } = ] must-fail-with
[ 3 ] [ &: ffi_test_1 indirect-test-1 ] unit-test [ 3 ] [ &: ffi_test_1 indirect-test-1 ] unit-test
: indirect-test-1' ( ptr -- ) : indirect-test-1' ( ptr -- )

View File

@ -503,8 +503,27 @@ HOOK: dummy-int-params? cpu ( -- ? )
! If t, all int parameters are shadowed by dummy FP parameters ! If t, all int parameters are shadowed by dummy FP parameters
HOOK: dummy-fp-params? cpu ( -- ? ) HOOK: dummy-fp-params? cpu ( -- ? )
HOOK: %prepare-unbox cpu ( n -- ) ! Load a value (from the data stack in the ds register).
! The value is then passed as a parameter to a VM to_*() function
HOOK: %pop-stack cpu ( n -- )
! Store a value (to the data stack in the VM's current context)
! The value is passed to a VM to_*() function -- used for
! callback returns
HOOK: %pop-context-stack cpu ( -- )
! Store a value (to the data stack in the ds register).
! The value was returned from a VM from_*() function
HOOK: %push-stack cpu ( -- )
! Store a value (to the data stack in the VM's current context)
! The value is returned from a VM from_*() function -- used for
! callback parameters
HOOK: %push-context-stack cpu ( -- )
! Call a function to convert a tagged pointer returned by
! %pop-stack or %pop-context-stack into a value that can be
! passed to a C function, or returned from a callback
HOOK: %unbox cpu ( n rep func -- ) HOOK: %unbox cpu ( n rep func -- )
HOOK: %unbox-long-long cpu ( n func -- ) HOOK: %unbox-long-long cpu ( n func -- )
@ -513,6 +532,10 @@ HOOK: %unbox-small-struct cpu ( c-type -- )
HOOK: %unbox-large-struct cpu ( n c-type -- ) HOOK: %unbox-large-struct cpu ( n c-type -- )
! Call a function to convert a value into a tagged pointer,
! possibly allocating a bignum, float, or alien instance,
! which is then pushed on the data stack by %push-stack or
! %push-context-stack
HOOK: %box cpu ( n rep func -- ) HOOK: %box cpu ( n rep func -- )
HOOK: %box-long-long cpu ( n func -- ) HOOK: %box-long-long cpu ( n func -- )
@ -527,7 +550,7 @@ 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: %save-context cpu ( temp1 temp2 callback-allowed? -- ) HOOK: %save-context cpu ( temp1 temp2 -- )
HOOK: %prepare-var-args cpu ( -- ) HOOK: %prepare-var-args cpu ( -- )

View File

@ -590,7 +590,7 @@ M:: ppc %save-param-reg ( stack reg rep -- )
M:: ppc %load-param-reg ( stack reg rep -- ) M:: ppc %load-param-reg ( stack reg rep -- )
reg stack local@ rep load-from-frame ; reg stack local@ rep load-from-frame ;
M: ppc %prepare-unbox ( n -- ) M: ppc %pop-stack ( n -- )
[ 3 ] dip <ds-loc> loc>operand LWZ ; [ 3 ] dip <ds-loc> loc>operand LWZ ;
M: ppc %unbox ( n rep func -- ) M: ppc %unbox ( n rep func -- )
@ -650,13 +650,13 @@ M: ppc %box-large-struct ( n c-type -- )
[ [ 3 1 ] dip struct-return@ ADDI ] [ heap-size 4 LI ] bi* [ [ 3 1 ] dip struct-return@ ADDI ] [ heap-size 4 LI ] bi*
5 %load-vm-addr 5 %load-vm-addr
! Call the function ! Call the function
"box_value_struct" f %alien-invoke ; "from_value_struct" f %alien-invoke ;
M:: ppc %save-context ( temp1 temp2 callback-allowed? -- ) M:: ppc %save-context ( temp1 temp2 callback-allowed? -- )
#! 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 "stack_chain" %load-vm-field-addr temp1 "ctx" %load-vm-field-addr
temp1 temp1 0 LWZ temp1 temp1 0 LWZ
1 temp1 0 STW 1 temp1 0 STW
callback-allowed? [ callback-allowed? [
@ -703,7 +703,7 @@ M: ppc %box-small-struct ( c-type -- )
#! Box a <= 16-byte struct returned in r3:r4:r5:r6 #! Box a <= 16-byte struct returned in r3:r4:r5:r6
heap-size 7 LI heap-size 7 LI
8 %load-vm-addr 8 %load-vm-addr
"box_medium_struct" f %alien-invoke ; "from_medium_struct" f %alien-invoke ;
: %unbox-struct-1 ( -- ) : %unbox-struct-1 ( -- )
! Alien must be in r3. ! Alien must be in r3.

View File

@ -53,10 +53,6 @@ M:: x86.32 %dispatch ( src temp -- )
[ align-code ] [ align-code ]
bi ; bi ;
! Registers for fastcall
: param-reg-1 ( -- reg ) EAX ;
: param-reg-2 ( -- reg ) EDX ;
M: x86.32 pic-tail-reg EBX ; M: x86.32 pic-tail-reg EBX ;
M: x86.32 reserved-stack-space 4 cells ; M: x86.32 reserved-stack-space 4 cells ;
@ -136,7 +132,7 @@ M:: x86.32 %box-large-struct ( n c-type -- )
8 save-vm-ptr 8 save-vm-ptr
4 stack@ c-type heap-size MOV 4 stack@ c-type heap-size MOV
0 stack@ EDX MOV 0 stack@ EDX MOV
"box_value_struct" f %alien-invoke ; "from_value_struct" f %alien-invoke ;
M: x86.32 %prepare-box-struct ( -- ) M: x86.32 %prepare-box-struct ( -- )
! Compute target address for value struct return ! Compute target address for value struct return
@ -150,11 +146,17 @@ M: x86.32 %box-small-struct ( c-type -- )
8 stack@ swap heap-size MOV 8 stack@ swap heap-size MOV
4 stack@ EDX MOV 4 stack@ EDX MOV
0 stack@ EAX MOV 0 stack@ EAX MOV
"box_small_struct" f %alien-invoke ; "from_small_struct" f %alien-invoke ;
M: x86.32 %prepare-unbox ( -- ) M: x86.32 %pop-stack ( n -- )
EAX swap ds-reg reg-stack MOV ; EAX swap ds-reg reg-stack MOV ;
M: x86.32 %pop-context-stack ( -- )
temp-reg %load-context-datastack
EAX temp-reg [] MOV
EAX EAX [] MOV
temp-reg [] bootstrap-cell SUB ;
: call-unbox-func ( func -- ) : call-unbox-func ( func -- )
4 save-vm-ptr 4 save-vm-ptr
0 stack@ EAX MOV 0 stack@ EAX MOV
@ -213,7 +215,8 @@ 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. See comment in vm/contexts.hpp ! Save current frame to ctx->magic_frame.
! See comment in vm/contexts.hpp.
EAX stack-reg stack-frame get total-size>> 3 cells - [+] LEA EAX stack-reg stack-frame get total-size>> 3 cells - [+] LEA
4 save-vm-ptr 4 save-vm-ptr
0 stack@ EAX MOV 0 stack@ EAX MOV
@ -224,21 +227,24 @@ M: x86.32 %unnest-stacks ( -- )
"unnest_stacks" f %alien-invoke ; "unnest_stacks" f %alien-invoke ;
M: x86.32 %prepare-alien-indirect ( -- ) M: x86.32 %prepare-alien-indirect ( -- )
0 save-vm-ptr EAX ds-reg [] MOV
"unbox_alien" f %alien-invoke ds-reg 4 SUB
4 save-vm-ptr
0 stack@ EAX MOV
"pinned_alien_offset" f %alien-invoke
EBP EAX MOV ; EBP EAX MOV ;
M: x86.32 %alien-indirect ( -- ) M: x86.32 %alien-indirect ( -- )
EBP CALL ; EBP CALL ;
M: x86.32 %alien-callback ( quot -- ) M: x86.32 %alien-callback ( quot -- )
! Fastcall EAX swap %load-reference
param-reg-1 swap %load-reference 0 stack@ EAX MOV
param-reg-2 %mov-vm-ptr 4 save-vm-ptr
"c_to_factor" f %alien-invoke ; "c_to_factor" f %alien-invoke ;
M: x86.32 %callback-value ( ctype -- ) M: x86.32 %callback-value ( ctype -- )
0 %prepare-unbox %pop-context-stack
4 stack@ EAX MOV 4 stack@ EAX MOV
0 save-vm-ptr 0 save-vm-ptr
! Restore data/call/retain stacks ! Restore data/call/retain stacks

View File

@ -1,7 +1,7 @@
! Copyright (C) 2007, 2009 Slava Pestov. ! Copyright (C) 2007, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: bootstrap.image.private kernel namespaces system USING: bootstrap.image.private kernel kernel.private namespaces
cpu.x86.assembler cpu.x86.assembler.operands layouts system cpu.x86.assembler cpu.x86.assembler.operands layouts
vocabs parser compiler.constants sequences math math.private vocabs parser compiler.constants sequences math math.private
generic.single.private ; generic.single.private ;
IN: bootstrap.x86 IN: bootstrap.x86
@ -12,8 +12,6 @@ IN: bootstrap.x86
: shift-arg ( -- reg ) ECX ; : shift-arg ( -- reg ) ECX ;
: div-arg ( -- reg ) EAX ; : div-arg ( -- reg ) EAX ;
: mod-arg ( -- reg ) EDX ; : mod-arg ( -- reg ) EDX ;
: arg1 ( -- reg ) EAX ;
: arg2 ( -- reg ) EDX ;
: temp0 ( -- reg ) EAX ; : temp0 ( -- reg ) EAX ;
: temp1 ( -- reg ) EDX ; : temp1 ( -- reg ) EDX ;
: temp2 ( -- reg ) ECX ; : temp2 ( -- reg ) ECX ;
@ -34,20 +32,51 @@ IN: bootstrap.x86
ESP stack-frame-size 3 bootstrap-cells - SUB ESP stack-frame-size 3 bootstrap-cells - SUB
] jit-prolog jit-define ] jit-prolog jit-define
: jit-load-vm ( -- )
EBP 0 MOV 0 rc-absolute-cell jit-vm ;
: jit-save-context ( -- ) : jit-save-context ( -- )
EAX 0 [] MOV rc-absolute-cell rt-context jit-rel ! VM pointer must be in EBP already
! save stack pointer ECX EBP [] MOV
ECX ESP -4 [+] LEA ! save ctx->callstack_top
EAX [] ECX MOV ; EAX ESP -4 [+] LEA
ECX [] EAX MOV
! save ctx->datastack
ECX 8 [+] ds-reg MOV
! save ctx->retainstack
ECX 12 [+] rs-reg MOV ;
: jit-restore-context ( -- )
! VM pointer must be in EBP already
ECX EBP [] MOV
! restore ctx->datastack
ds-reg ECX 8 [+] MOV
! restore ctx->retainstack
rs-reg ECX 12 [+] MOV ;
[ [
jit-load-vm
! save ds, rs registers
jit-save-context jit-save-context
! pass vm ptr to primitive
EAX 0 MOV rc-absolute-cell rt-vm jit-rel
! call the primitive ! call the primitive
ESP [] EBP MOV
0 CALL rc-relative rt-primitive jit-rel 0 CALL rc-relative rt-primitive jit-rel
! restore ds, rs registers
jit-restore-context
] jit-primitive jit-define ] jit-primitive jit-define
[
! load from stack
EAX ds-reg [] MOV
! pop stack
ds-reg bootstrap-cell SUB
! load VM pointer
EDX 0 MOV 0 rc-absolute-cell jit-vm
]
[ EAX quot-xt-offset [+] CALL ]
[ EAX quot-xt-offset [+] JMP ]
\ (call) define-sub-primitive*
! Inline cache miss entry points ! Inline cache miss entry points
: jit-load-return-address ( -- ) : jit-load-return-address ( -- )
EBX ESP stack-frame-size bootstrap-cell - [+] MOV ; EBX ESP stack-frame-size bootstrap-cell - [+] MOV ;
@ -55,10 +84,12 @@ IN: bootstrap.x86
! These are always in tail position with an existing stack ! These are always in tail position with an existing stack
! frame, and the stack. The frame setup takes this into account. ! frame, and the stack. The frame setup takes this into account.
: jit-inline-cache-miss ( -- ) : jit-inline-cache-miss ( -- )
jit-load-vm
jit-save-context jit-save-context
ESP 4 [+] 0 MOV 0 rc-absolute-cell jit-vm ESP 4 [+] EBP MOV
ESP [] EBX MOV ESP [] EBX MOV
0 CALL "inline_cache_miss" f rc-relative jit-dlsym ; 0 CALL "inline_cache_miss" f rc-relative jit-dlsym
jit-restore-context ;
[ jit-load-return-address jit-inline-cache-miss ] [ jit-load-return-address jit-inline-cache-miss ]
[ EAX CALL ] [ EAX CALL ]
@ -72,16 +103,19 @@ IN: bootstrap.x86
! Overflowing fixnum arithmetic ! Overflowing fixnum arithmetic
: jit-overflow ( insn func -- ) : jit-overflow ( insn func -- )
jit-save-context
EAX ds-reg -4 [+] MOV
EDX ds-reg [] MOV
ds-reg 4 SUB ds-reg 4 SUB
jit-load-vm
jit-save-context
EAX ds-reg [] MOV
EDX ds-reg 4 [+] MOV
ECX EAX MOV ECX EAX MOV
[ [ ECX EDX ] dip call( dst src -- ) ] dip [ [ ECX EDX ] dip call( dst src -- ) ] dip
ds-reg [] ECX MOV ds-reg [] ECX MOV
[ JNO ] [ JNO ]
[ [
ECX 0 MOV 0 rc-absolute-cell jit-vm ESP [] EAX MOV
ESP 4 [+] EDX MOV
ESP 8 [+] EBP MOV
[ 0 CALL ] dip f rc-relative jit-dlsym [ 0 CALL ] dip f rc-relative jit-dlsym
] ]
jit-conditional ; jit-conditional ;
@ -91,20 +125,21 @@ IN: bootstrap.x86
[ [ SUB ] "overflow_fixnum_subtract" jit-overflow ] \ fixnum- define-sub-primitive [ [ SUB ] "overflow_fixnum_subtract" jit-overflow ] \ fixnum- define-sub-primitive
[ [
jit-save-context
ECX ds-reg -4 [+] MOV
EBX ds-reg [] MOV
EBX tag-bits get SAR
ds-reg 4 SUB ds-reg 4 SUB
jit-load-vm
jit-save-context
ECX ds-reg [] MOV
EAX ECX MOV EAX ECX MOV
EBX ds-reg 4 [+] MOV
EBX tag-bits get SAR
EBX IMUL EBX IMUL
ds-reg [] EAX MOV ds-reg [] EAX MOV
[ JNO ] [ JNO ]
[ [
EAX ECX MOV ECX tag-bits get SAR
EAX tag-bits get SAR ESP [] ECX MOV
EDX EBX MOV ESP 4 [+] EBX MOV
ECX 0 MOV 0 rc-absolute-cell jit-vm ESP 8 [+] EBP MOV
0 CALL "overflow_fixnum_multiply" f rc-relative jit-dlsym 0 CALL "overflow_fixnum_multiply" f rc-relative jit-dlsym
] ]
jit-conditional jit-conditional

View File

@ -77,9 +77,9 @@ M: stack-params copy-register*
{ [ over integer? ] [ R11 swap MOV param@ R11 MOV ] } { [ over integer? ] [ R11 swap MOV param@ R11 MOV ] }
} cond ; } cond ;
M: x86 %save-param-reg [ param@ ] 2dip %copy ; M: x86.64 %save-param-reg [ param@ ] 2dip %copy ;
M: x86 %load-param-reg [ swap param@ ] dip %copy ; M: x86.64 %load-param-reg [ swap param@ ] dip %copy ;
: with-return-regs ( quot -- ) : with-return-regs ( quot -- )
[ [
@ -88,9 +88,15 @@ M: x86 %load-param-reg [ swap param@ ] dip %copy ;
call call
] with-scope ; inline ] with-scope ; inline
M: x86.64 %prepare-unbox ( n -- ) M: x86.64 %pop-stack ( n -- )
param-reg-1 swap ds-reg reg-stack MOV ; param-reg-1 swap ds-reg reg-stack MOV ;
M: x86.64 %pop-context-stack ( -- )
temp-reg %load-context-datastack
param-reg-1 temp-reg [] MOV
param-reg-1 param-reg-1 [] MOV
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-2 %mov-vm-ptr
! Call the unboxer ! Call the unboxer
@ -167,7 +173,7 @@ M: x86.64 %box-small-struct ( c-type -- )
param-reg-1 0 box-struct-field@ MOV param-reg-1 0 box-struct-field@ MOV
param-reg-2 1 box-struct-field@ MOV param-reg-2 1 box-struct-field@ MOV
param-reg-4 %mov-vm-ptr param-reg-4 %mov-vm-ptr
"box_small_struct" f %alien-invoke "from_small_struct" f %alien-invoke
] with-return-regs ; ] with-return-regs ;
: struct-return@ ( n -- operand ) : struct-return@ ( n -- operand )
@ -180,7 +186,7 @@ M: x86.64 %box-large-struct ( n c-type -- )
param-reg-1 swap struct-return@ LEA param-reg-1 swap struct-return@ LEA
param-reg-3 %mov-vm-ptr param-reg-3 %mov-vm-ptr
! Copy the struct from the C stack ! Copy the struct from the C stack
"box_value_struct" f %alien-invoke ; "from_value_struct" f %alien-invoke ;
M: x86.64 %prepare-box-struct ( -- ) M: x86.64 %prepare-box-struct ( -- )
! Compute target address for value struct return ! Compute target address for value struct return
@ -206,8 +212,10 @@ M: x86.64 %unnest-stacks ( -- )
"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 %mov-vm-ptr param-reg-1 ds-reg [] MOV
"unbox_alien" f %alien-invoke ds-reg 8 SUB
param-reg-2 %mov-vm-ptr
"pinned_alien_offset" f %alien-invoke
RBP RAX MOV ; RBP RAX MOV ;
M: x86.64 %alien-indirect ( -- ) M: x86.64 %alien-indirect ( -- )
@ -219,7 +227,7 @@ M: x86.64 %alien-callback ( quot -- )
"c_to_factor" f %alien-invoke ; "c_to_factor" f %alien-invoke ;
M: x86.64 %callback-value ( ctype -- ) M: x86.64 %callback-value ( ctype -- )
0 %prepare-unbox %pop-context-stack
RSP 8 SUB RSP 8 SUB
param-reg-1 PUSH param-reg-1 PUSH
param-reg-1 %mov-vm-ptr param-reg-1 %mov-vm-ptr

View File

@ -1,9 +1,9 @@
! Copyright (C) 2007, 2009 Slava Pestov. ! Copyright (C) 2007, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: bootstrap.image.private kernel namespaces system USING: bootstrap.image.private kernel kernel.private namespaces
layouts vocabs parser compiler.constants math math.private system layouts vocabs parser compiler.constants math
cpu.x86.assembler cpu.x86.assembler.operands sequences math.private cpu.x86.assembler cpu.x86.assembler.operands
generic.single.private ; sequences generic.single.private ;
IN: bootstrap.x86 IN: bootstrap.x86
8 \ cell set 8 \ cell set
@ -33,23 +33,52 @@ IN: bootstrap.x86
RSP stack-frame-size 3 bootstrap-cells - SUB RSP stack-frame-size 3 bootstrap-cells - SUB
] jit-prolog jit-define ] jit-prolog jit-define
: jit-load-vm ( -- )
RBP 0 MOV 0 rc-absolute-cell jit-vm ;
: jit-save-context ( -- ) : jit-save-context ( -- )
temp0 0 MOV rc-absolute-cell rt-context jit-rel ! VM pointer must be in RBP already
temp0 temp0 [] MOV RCX RBP [] MOV
! save stack pointer ! save ctx->callstack_top
temp1 stack-reg bootstrap-cell neg [+] LEA RAX RSP -8 [+] LEA
temp0 [] temp1 MOV ; RCX [] RAX MOV
! save ctx->datastack
RCX 16 [+] ds-reg MOV
! save ctx->retainstack
RCX 24 [+] rs-reg MOV ;
: jit-restore-context ( -- )
! VM pointer must be in EBP already
RCX RBP [] MOV
! restore ctx->datastack
ds-reg RCX 16 [+] MOV
! restore ctx->retainstack
rs-reg RCX 24 [+] MOV ;
[ [
jit-load-vm
! save ds, rs registers
jit-save-context jit-save-context
! load vm ptr ! call the primitive
arg1 0 MOV rc-absolute-cell rt-vm jit-rel arg1 RBP MOV
! load XT RAX 0 MOV rc-absolute-cell rt-primitive jit-rel
temp1 0 MOV rc-absolute-cell rt-primitive jit-rel RAX CALL
! go ! restore ds, rs registers
temp1 CALL jit-restore-context
] jit-primitive jit-define ] jit-primitive jit-define
[
! load from stack
arg1 ds-reg [] MOV
! pop stack
ds-reg bootstrap-cell SUB
! load VM pointer
arg2 0 MOV 0 rc-absolute-cell jit-vm
]
[ arg1 quot-xt-offset [+] CALL ]
[ arg1 quot-xt-offset [+] JMP ]
\ (call) define-sub-primitive*
! Inline cache miss entry points ! Inline cache miss entry points
: jit-load-return-address ( -- ) : jit-load-return-address ( -- )
RBX RSP stack-frame-size bootstrap-cell - [+] MOV ; RBX RSP stack-frame-size bootstrap-cell - [+] MOV ;
@ -57,10 +86,13 @@ IN: bootstrap.x86
! These are always in tail position with an existing stack ! These are always in tail position with an existing stack
! frame, and the stack. The frame setup takes this into account. ! frame, and the stack. The frame setup takes this into account.
: jit-inline-cache-miss ( -- ) : jit-inline-cache-miss ( -- )
jit-load-vm
jit-save-context jit-save-context
arg1 RBX MOV arg1 RBX MOV
arg2 0 MOV 0 rc-absolute-cell jit-vm arg2 RBP MOV
0 CALL "inline_cache_miss" f rc-relative jit-dlsym ; RAX 0 MOV "inline_cache_miss" f rc-absolute-cell jit-dlsym
RAX CALL
jit-restore-context ;
[ jit-load-return-address jit-inline-cache-miss ] [ jit-load-return-address jit-inline-cache-miss ]
[ RAX CALL ] [ RAX CALL ]
@ -74,17 +106,19 @@ IN: bootstrap.x86
! Overflowing fixnum arithmetic ! Overflowing fixnum arithmetic
: jit-overflow ( insn func -- ) : jit-overflow ( insn func -- )
ds-reg 8 SUB
jit-load-vm
jit-save-context jit-save-context
arg1 ds-reg bootstrap-cell neg [+] MOV arg1 ds-reg [] MOV
arg2 ds-reg [] MOV arg2 ds-reg 8 [+] MOV
ds-reg bootstrap-cell SUB
arg3 arg1 MOV arg3 arg1 MOV
[ [ arg3 arg2 ] dip call ] dip [ [ arg3 arg2 ] dip call ] dip
ds-reg [] arg3 MOV ds-reg [] arg3 MOV
[ JNO ] [ JNO ]
[ [
arg3 0 MOV 0 rc-absolute-cell jit-vm arg3 RBP MOV
[ 0 CALL ] dip f rc-relative jit-dlsym RAX 0 MOV f rc-absolute-cell jit-dlsym
RAX CALL
] ]
jit-conditional ; inline jit-conditional ; inline
@ -93,11 +127,12 @@ IN: bootstrap.x86
[ [ SUB ] "overflow_fixnum_subtract" jit-overflow ] \ fixnum- define-sub-primitive [ [ SUB ] "overflow_fixnum_subtract" jit-overflow ] \ fixnum- define-sub-primitive
[ [
ds-reg 8 SUB
jit-load-vm
jit-save-context jit-save-context
RCX ds-reg bootstrap-cell neg [+] MOV RCX ds-reg [] MOV
RBX ds-reg [] MOV RBX ds-reg 8 [+] MOV
RBX tag-bits get SAR RBX tag-bits get SAR
ds-reg bootstrap-cell SUB
RAX RCX MOV RAX RCX MOV
RBX IMUL RBX IMUL
ds-reg [] RAX MOV ds-reg [] RAX MOV
@ -106,8 +141,9 @@ IN: bootstrap.x86
arg1 RCX MOV arg1 RCX MOV
arg1 tag-bits get SAR arg1 tag-bits get SAR
arg2 RBX MOV arg2 RBX MOV
arg3 0 MOV 0 rc-absolute-cell jit-vm arg3 RBP MOV
0 CALL "overflow_fixnum_multiply" f rc-relative jit-dlsym RAX 0 MOV "overflow_fixnum_multiply" f rc-absolute-cell jit-dlsym
RAX CALL
] ]
jit-conditional jit-conditional
] \ fixnum* define-sub-primitive ] \ fixnum* define-sub-primitive

View File

@ -120,30 +120,18 @@ big-endian off
[ [
! load from stack ! load from stack
arg1 ds-reg [] MOV temp0 ds-reg [] MOV
! pop stack
ds-reg bootstrap-cell SUB
! pass vm pointer
arg2 0 MOV 0 rc-absolute-cell jit-vm
]
[ arg1 quot-xt-offset [+] CALL ]
[ arg1 quot-xt-offset [+] JMP ]
\ (call) define-sub-primitive*
[
! load from stack
arg1 ds-reg [] MOV
! pop stack ! pop stack
ds-reg bootstrap-cell SUB ds-reg bootstrap-cell SUB
] ]
[ arg1 word-xt-offset [+] CALL ] [ temp0 word-xt-offset [+] CALL ]
[ arg1 word-xt-offset [+] JMP ] [ temp0 word-xt-offset [+] JMP ]
\ (execute) define-sub-primitive* \ (execute) define-sub-primitive*
[ [
arg1 ds-reg [] MOV temp0 ds-reg [] MOV
ds-reg bootstrap-cell SUB ds-reg bootstrap-cell SUB
arg1 word-xt-offset [+] JMP temp0 word-xt-offset [+] JMP
] jit-execute jit-define ] jit-execute jit-define
[ [

View File

@ -472,6 +472,23 @@ M: x86 %load-gc-root ( gc-root register -- ) swap gc-root@ MOV ;
M: x86 %alien-global ( dst symbol library -- ) M: x86 %alien-global ( dst symbol library -- )
[ 0 MOV ] 2dip rc-absolute-cell rel-dlsym ; [ 0 MOV ] 2dip rc-absolute-cell rel-dlsym ;
M: x86 %push-stack ( -- )
ds-reg cell ADD
ds-reg [] int-regs return-reg MOV ;
:: %load-context-datastack ( dst -- )
! Load context struct
dst "ctx" %vm-field-ptr
dst dst [] MOV
! Load context datastack pointer
dst "datastack" context-field-offset ADD ;
M: x86 %push-context-stack ( -- )
temp-reg %load-context-datastack
temp-reg [] bootstrap-cell ADD
temp-reg temp-reg [] MOV
temp-reg [] int-regs return-reg MOV ;
M: x86 %epilogue ( n -- ) cell - incr-stack-reg ; M: x86 %epilogue ( n -- ) cell - incr-stack-reg ;
:: %boolean ( dst temp word -- ) :: %boolean ( dst temp word -- )
@ -649,43 +666,6 @@ M: x86 %fill-vector-reps
{ sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } } { sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep longlong-2-rep ulonglong-2-rep } }
} available-reps ; } available-reps ;
! M:: x86 %broadcast-vector ( dst src rep -- )
! rep signed-rep {
! { float-4-rep [
! dst src float-4-rep %copy
! dst dst { 0 0 0 0 } SHUFPS
! ] }
! { double-2-rep [
! dst src MOVDDUP
! ] }
! { longlong-2-rep [
! dst src =
! [ dst dst PUNPCKLQDQ ]
! [ dst src { 0 1 0 1 } PSHUFD ]
! if
! ] }
! { int-4-rep [
! dst src { 0 0 0 0 } PSHUFD
! ] }
! { short-8-rep [
! dst src { 0 0 0 0 } PSHUFLW
! dst dst PUNPCKLQDQ
! ] }
! { char-16-rep [
! dst src char-16-rep %copy
! dst dst PUNPCKLBW
! dst dst { 0 0 0 0 } PSHUFLW
! dst dst PUNPCKLQDQ
! ] }
! } case ;
!
! M: x86 %broadcast-vector-reps
! {
! ! Can't do this with sse1 since it will want to unbox
! ! a double-precision float and convert to single precision
! { sse2? { float-4-rep double-2-rep longlong-2-rep ulonglong-2-rep int-4-rep uint-4-rep short-8-rep ushort-8-rep char-16-rep uchar-16-rep } }
! } available-reps ;
M:: x86 %gather-vector-4 ( dst src1 src2 src3 src4 rep -- ) M:: x86 %gather-vector-4 ( dst src1 src2 src3 src4 rep -- )
rep signed-rep { rep signed-rep {
{ float-4-rep [ { float-4-rep [
@ -883,6 +863,7 @@ M: x86 %float>integer-vector-reps
: (%compare-float-vector) ( dst src rep double single -- ) : (%compare-float-vector) ( dst src rep double single -- )
[ double-2-rep eq? ] 2dip if ; inline [ double-2-rep eq? ] 2dip if ; inline
: %compare-float-vector ( dst src rep cc -- ) : %compare-float-vector ( dst src rep cc -- )
{ {
{ cc< [ [ CMPLTPD ] [ CMPLTPS ] (%compare-float-vector) ] } { cc< [ [ CMPLTPD ] [ CMPLTPS ] (%compare-float-vector) ] }
@ -903,6 +884,7 @@ M: x86 %float>integer-vector-reps
{ short-8-rep [ int16 call ] } { short-8-rep [ int16 call ] }
{ char-16-rep [ int8 call ] } { char-16-rep [ int8 call ] }
} case ; inline } case ; inline
: %compare-int-vector ( dst src rep cc -- ) : %compare-int-vector ( dst src rep cc -- )
{ {
{ cc= [ [ PCMPEQQ ] [ PCMPEQD ] [ PCMPEQW ] [ PCMPEQB ] (%compare-int-vector) ] } { cc= [ [ PCMPEQQ ] [ PCMPEQD ] [ PCMPEQW ] [ PCMPEQB ] (%compare-int-vector) ] }
@ -921,6 +903,7 @@ M: x86 %compare-vector ( dst src1 src2 rep cc -- )
{ sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep } } { sse2? { double-2-rep char-16-rep uchar-16-rep short-8-rep ushort-8-rep int-4-rep uint-4-rep } }
{ sse4.1? { longlong-2-rep ulonglong-2-rep } } { sse4.1? { longlong-2-rep ulonglong-2-rep } }
} available-reps ; } available-reps ;
: %compare-vector-ord-reps ( -- reps ) : %compare-vector-ord-reps ( -- reps )
{ {
{ sse? { float-4-rep } } { sse? { float-4-rep } }
@ -1409,6 +1392,7 @@ M: x86 %integer>scalar drop MOVD ;
} case ; } case ;
M: x86.32 %scalar>integer ( dst src rep -- ) %scalar>integer-32 ; M: x86.32 %scalar>integer ( dst src rep -- ) %scalar>integer-32 ;
M: x86.64 %scalar>integer ( dst src rep -- ) M: x86.64 %scalar>integer ( dst src rep -- )
{ {
{ longlong-scalar-rep [ MOVD ] } { longlong-scalar-rep [ MOVD ] }
@ -1424,18 +1408,16 @@ 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 %save-context ( temp1 temp2 callback-allowed? -- ) 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 "stack_chain" %vm-field-ptr temp1 "ctx" %vm-field-ptr
temp1 temp1 [] MOV temp1 temp1 [] MOV
temp2 stack-reg cell neg [+] LEA temp2 stack-reg cell neg [+] LEA
temp1 [] temp2 MOV temp1 [] temp2 MOV
callback-allowed? [ temp1 2 cells [+] ds-reg MOV
temp1 2 cells [+] ds-reg MOV temp1 3 cells [+] rs-reg MOV ;
temp1 3 cells [+] rs-reg MOV
] when ;
M: x86 value-struct? drop t ; M: x86 value-struct? drop t ;

View File

@ -2,7 +2,7 @@
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: io.backend system namespaces io.backend.unix.bsd USING: io.backend system namespaces io.backend.unix.bsd
io.backend.unix.multiplexers io.backend.unix.multiplexers.run-loop ; io.backend.unix.multiplexers io.backend.unix.multiplexers.run-loop ;
IN: io.backend.macosx IN: io.backend.unix.macosx
M: macosx init-io ( -- ) M: macosx init-io ( -- )
<run-loop-mx> mx set-global ; <run-loop-mx> mx set-global ;

View File

@ -4,7 +4,20 @@ USING: classes.struct alien.c-types alien.syntax ;
IN: vm IN: vm
TYPEDEF: uintptr_t cell TYPEDEF: uintptr_t cell
C-TYPE: context
STRUCT: context
{ callstack-top void* }
{ callstack-bottom void* }
{ datastack cell }
{ callstack cell }
{ magic-frame void* }
{ datastack-region void* }
{ retainstack-region void* }
{ catchstack-save cell }
{ current-callback-save cell }
{ next context* } ;
: context-field-offset ( field -- offset ) context offset-of ; inline
STRUCT: zone STRUCT: zone
{ start cell } { start cell }
@ -13,10 +26,10 @@ STRUCT: zone
{ end cell } ; { end cell } ;
STRUCT: vm STRUCT: vm
{ stack_chain context* } { ctx context* }
{ nursery zone } { nursery zone }
{ cards_offset cell } { cards-offset cell }
{ decks_offset cell } { decks-offset cell }
{ userenv cell[70] } ; { userenv cell[70] } ;
: vm-field-offset ( field -- offset ) vm offset-of ; inline : vm-field-offset ( field -- offset ) vm offset-of ; inline

View File

@ -63,20 +63,6 @@ check_ret() {
fi fi
} }
check_gcc_version() {
$ECHO -n "Checking gcc version..."
GCC_VERSION=`$CC --version`
check_ret gcc
if [[ $GCC_VERSION == *3.3.* ]] ; then
$ECHO "You have a known buggy version of gcc (3.3)"
$ECHO "Install gcc 3.4 or higher and try again."
exit_script 3
elif [[ $GCC_VERSION == *4.3.* ]] ; then
MAKE_OPTS="$MAKE_OPTS SITE_CFLAGS=-fno-forward-propagate"
fi
$ECHO "ok."
}
set_downloader() { set_downloader() {
test_program_installed wget curl test_program_installed wget curl
if [[ $? -ne 0 ]] ; then if [[ $? -ne 0 ]] ; then
@ -124,7 +110,6 @@ check_installed_programs() {
ensure_program_installed make gmake ensure_program_installed make gmake
ensure_program_installed md5sum md5 ensure_program_installed md5sum md5
ensure_program_installed cut ensure_program_installed cut
check_gcc_version
} }
check_library_exists() { check_library_exists() {

View File

@ -430,7 +430,7 @@ tuple
{ "callstack" "kernel" (( -- cs )) } { "callstack" "kernel" (( -- cs )) }
{ "set-datastack" "kernel" (( ds -- )) } { "set-datastack" "kernel" (( ds -- )) }
{ "set-retainstack" "kernel" (( rs -- )) } { "set-retainstack" "kernel" (( rs -- )) }
{ "set-callstack" "kernel" (( cs -- )) } { "set-callstack" "kernel" (( cs -- * )) }
{ "(exit)" "system" (( n -- )) } { "(exit)" "system" (( n -- )) }
{ "data-room" "memory" (( -- data-room )) } { "data-room" "memory" (( -- data-room )) }
{ "code-room" "memory" (( -- code-room )) } { "code-room" "memory" (( -- code-room )) }
@ -503,7 +503,7 @@ tuple
{ "innermost-frame-executing" "kernel.private" (( callstack -- obj )) } { "innermost-frame-executing" "kernel.private" (( callstack -- obj )) }
{ "innermost-frame-scan" "kernel.private" (( callstack -- n )) } { "innermost-frame-scan" "kernel.private" (( callstack -- n )) }
{ "set-innermost-frame-quot" "kernel.private" (( n callstack -- )) } { "set-innermost-frame-quot" "kernel.private" (( n callstack -- )) }
{ "call-clear" "kernel" (( quot -- )) } { "call-clear" "kernel.private" (( quot -- * )) }
{ "resize-byte-array" "byte-arrays" (( n byte-array -- newbyte-array )) } { "resize-byte-array" "byte-arrays" (( n byte-array -- newbyte-array )) }
{ "dll-valid?" "alien.libraries" (( dll -- ? )) } { "dll-valid?" "alien.libraries" (( dll -- ? )) }
{ "unimplemented" "kernel.private" (( -- * )) } { "unimplemented" "kernel.private" (( -- * )) }

View File

@ -46,7 +46,7 @@ HELP: callstack ( -- cs )
{ $values { "cs" callstack } } { $values { "cs" callstack } }
{ $description "Outputs a copy of the call stack contents, with the top of the stack at the end of the vector. The stack frame of the caller word is " { $emphasis "not" } " included." } ; { $description "Outputs a copy of the call stack contents, with the top of the stack at the end of the vector. The stack frame of the caller word is " { $emphasis "not" } " included." } ;
HELP: set-callstack ( cs -- ) HELP: set-callstack ( cs -- * )
{ $values { "cs" callstack } } { $values { "cs" callstack } }
{ $description "Replaces the call stack contents. The end of the vector becomes the top of the stack. Control flow is transferred immediately to the new call stack." } ; { $description "Replaces the call stack contents. The end of the vector becomes the top of the stack. Control flow is transferred immediately to the new call stack." } ;
@ -208,7 +208,7 @@ HELP: call
{ call POSTPONE: call( } related-words { call POSTPONE: call( } related-words
HELP: call-clear ( quot -- ) HELP: call-clear ( quot -- * )
{ $values { "quot" callable } } { $values { "quot" callable } }
{ $description "Calls a quotation with an empty call stack. If the quotation returns, Factor will exit.." } { $description "Calls a quotation with an empty call stack. If the quotation returns, Factor will exit.." }
{ $notes "Used to implement " { $link "threads" } "." } ; { $notes "Used to implement " { $link "threads" } "." } ;

View File

@ -164,6 +164,11 @@ IN: kernel.tests
last-frame last-frame
] unit-test ] unit-test
: throw-frame-test ( c -- * ) [ gc gc continue ] call-clear ;
: throw-frame-test' ( -- ) [ throw-frame-test ] callcc0 ;
[ ] [ throw-frame-test' ] unit-test
[ 10 2 3 4 5 ] [ 1 2 3 4 5 [ 10 * ] 4dip ] unit-test [ 10 2 3 4 5 ] [ 1 2 3 4 5 [ 10 * ] 4dip ] unit-test
[ 3 -1 5/6 ] [ 1 2 3 4 5 6 [ + ] [ - ] [ / ] 2tri* ] unit-test [ 3 -1 5/6 ] [ 1 2 3 4 5 6 [ + ] [ - ] [ / ] 2tri* ] unit-test

View File

@ -2,6 +2,5 @@ include vm/Config.unix
PLAF_DLL_OBJS += vm/os-genunix.o vm/os-openbsd.o PLAF_DLL_OBJS += vm/os-genunix.o vm/os-openbsd.o
CC = egcc CC = egcc
CPP = eg++ CPP = eg++
# -fno-inline-functions works around a gcc 4.2.0 bug CFLAGS += -export-dynamic
CFLAGS += -export-dynamic -fno-inline-functions
LIBS = -L/usr/local/lib/ -lm $(X11_UI_LIBS) -lz -lssl -lcrypto -lpthread LIBS = -L/usr/local/lib/ -lm $(X11_UI_LIBS) -lz -lssl -lcrypto -lpthread

View File

@ -1,5 +1,2 @@
BOOT_ARCH = x86 BOOT_ARCH = x86
PLAF_DLL_OBJS += vm/cpu-x86.32.o PLAF_DLL_OBJS += vm/cpu-x86.32.o
# gcc bug workaround
CFLAGS += -fno-builtin-strlen -fno-builtin-strcat

View File

@ -49,8 +49,7 @@ void factor_vm::collect_aging()
collector.cheneys_algorithm(); collector.cheneys_algorithm();
data->reset_generation(&nursery); data->reset_generation(&nursery);
code->points_to_nursery.clear(); code->clear_remembered_set();
code->points_to_aging.clear();
} }
} }

View File

@ -27,9 +27,17 @@ char *factor_vm::pinned_alien_offset(cell obj)
} }
} }
VM_C_API char *pinned_alien_offset(cell obj, factor_vm *parent)
{
return parent->pinned_alien_offset(obj);
}
/* make an alien */ /* make an alien */
cell factor_vm::allot_alien(cell delegate_, cell displacement) cell factor_vm::allot_alien(cell delegate_, cell displacement)
{ {
if(delegate_ == false_object && displacement == 0)
return false_object;
data_root<object> delegate(delegate_,this); data_root<object> delegate(delegate_,this);
data_root<alien> new_alien(allot<alien>(sizeof(alien)),this); data_root<alien> new_alien(allot<alien>(sizeof(alien)),this);
@ -49,27 +57,32 @@ cell factor_vm::allot_alien(cell delegate_, cell displacement)
return new_alien.value(); return new_alien.value();
} }
cell factor_vm::allot_alien(void *address)
{
return allot_alien(false_object,(cell)address);
}
VM_C_API cell allot_alien(void *address, factor_vm *vm)
{
return vm->allot_alien(address);
}
/* make an alien pointing at an offset of another alien */ /* make an alien pointing at an offset of another alien */
void factor_vm::primitive_displaced_alien() void factor_vm::primitive_displaced_alien()
{ {
cell alien = dpop(); cell alien = ctx->pop();
cell displacement = to_cell(dpop()); cell displacement = to_cell(ctx->pop());
if(!to_boolean(alien) && displacement == 0) switch(tagged<object>(alien).type())
dpush(false_object);
else
{ {
switch(tagged<object>(alien).type()) case BYTE_ARRAY_TYPE:
{ case ALIEN_TYPE:
case BYTE_ARRAY_TYPE: case F_TYPE:
case ALIEN_TYPE: ctx->push(allot_alien(alien,displacement));
case F_TYPE: break;
dpush(allot_alien(alien,displacement)); default:
break; type_error(ALIEN_TYPE,alien);
default: break;
type_error(ALIEN_TYPE,alien);
break;
}
} }
} }
@ -77,59 +90,59 @@ void factor_vm::primitive_displaced_alien()
if the object is a byte array, as a sanity check. */ if the object is a byte array, as a sanity check. */
void factor_vm::primitive_alien_address() void factor_vm::primitive_alien_address()
{ {
box_unsigned_cell((cell)pinned_alien_offset(dpop())); ctx->push(allot_cell((cell)pinned_alien_offset(ctx->pop())));
} }
/* pop ( alien n ) from datastack, return alien's address plus n */ /* pop ( alien n ) from datastack, return alien's address plus n */
void *factor_vm::alien_pointer() void *factor_vm::alien_pointer()
{ {
fixnum offset = to_fixnum(dpop()); fixnum offset = to_fixnum(ctx->pop());
return unbox_alien() + offset; return alien_offset(ctx->pop()) + offset;
} }
/* define words to read/write values at an alien address */ /* define words to read/write values at an alien address */
#define DEFINE_ALIEN_ACCESSOR(name,type,boxer,to) \ #define DEFINE_ALIEN_ACCESSOR(name,type,from,to) \
PRIMITIVE(alien_##name) \ PRIMITIVE(alien_##name) \
{ \ { \
parent->boxer(*(type*)(parent->alien_pointer())); \ parent->ctx->push(from(*(type*)(parent->alien_pointer()),parent)); \
} \ } \
PRIMITIVE(set_alien_##name) \ PRIMITIVE(set_alien_##name) \
{ \ { \
type *ptr = (type *)parent->alien_pointer(); \ type *ptr = (type *)parent->alien_pointer(); \
type value = parent->to(dpop()); \ type value = to(parent->ctx->pop(),parent); \
*ptr = value; \ *ptr = value; \
} }
DEFINE_ALIEN_ACCESSOR(signed_cell,fixnum,box_signed_cell,to_fixnum) DEFINE_ALIEN_ACCESSOR(signed_cell,fixnum,from_signed_cell,to_fixnum)
DEFINE_ALIEN_ACCESSOR(unsigned_cell,cell,box_unsigned_cell,to_cell) DEFINE_ALIEN_ACCESSOR(unsigned_cell,cell,from_unsigned_cell,to_cell)
DEFINE_ALIEN_ACCESSOR(signed_8,s64,box_signed_8,to_signed_8) DEFINE_ALIEN_ACCESSOR(signed_8,s64,from_signed_8,to_signed_8)
DEFINE_ALIEN_ACCESSOR(unsigned_8,u64,box_unsigned_8,to_unsigned_8) DEFINE_ALIEN_ACCESSOR(unsigned_8,u64,from_unsigned_8,to_unsigned_8)
DEFINE_ALIEN_ACCESSOR(signed_4,s32,box_signed_4,to_fixnum) DEFINE_ALIEN_ACCESSOR(signed_4,s32,from_signed_4,to_fixnum)
DEFINE_ALIEN_ACCESSOR(unsigned_4,u32,box_unsigned_4,to_cell) DEFINE_ALIEN_ACCESSOR(unsigned_4,u32,from_unsigned_4,to_cell)
DEFINE_ALIEN_ACCESSOR(signed_2,s16,box_signed_2,to_fixnum) DEFINE_ALIEN_ACCESSOR(signed_2,s16,from_signed_2,to_fixnum)
DEFINE_ALIEN_ACCESSOR(unsigned_2,u16,box_unsigned_2,to_cell) DEFINE_ALIEN_ACCESSOR(unsigned_2,u16,from_unsigned_2,to_cell)
DEFINE_ALIEN_ACCESSOR(signed_1,s8,box_signed_1,to_fixnum) DEFINE_ALIEN_ACCESSOR(signed_1,s8,from_signed_1,to_fixnum)
DEFINE_ALIEN_ACCESSOR(unsigned_1,u8,box_unsigned_1,to_cell) DEFINE_ALIEN_ACCESSOR(unsigned_1,u8,from_unsigned_1,to_cell)
DEFINE_ALIEN_ACCESSOR(float,float,box_float,to_float) DEFINE_ALIEN_ACCESSOR(float,float,from_float,to_float)
DEFINE_ALIEN_ACCESSOR(double,double,box_double,to_double) DEFINE_ALIEN_ACCESSOR(double,double,from_double,to_double)
DEFINE_ALIEN_ACCESSOR(cell,void *,box_alien,pinned_alien_offset) DEFINE_ALIEN_ACCESSOR(cell,void *,allot_alien,pinned_alien_offset)
/* open a native library and push a handle */ /* open a native library and push a handle */
void factor_vm::primitive_dlopen() void factor_vm::primitive_dlopen()
{ {
data_root<byte_array> path(dpop(),this); data_root<byte_array> path(ctx->pop(),this);
path.untag_check(this); path.untag_check(this);
data_root<dll> library(allot<dll>(sizeof(dll)),this); data_root<dll> library(allot<dll>(sizeof(dll)),this);
library->path = path.value(); library->path = path.value();
ffi_dlopen(library.untagged()); ffi_dlopen(library.untagged());
dpush(library.value()); ctx->push(library.value());
} }
/* look up a symbol in a native library */ /* look up a symbol in a native library */
void factor_vm::primitive_dlsym() void factor_vm::primitive_dlsym()
{ {
data_root<object> library(dpop(),this); data_root<object> library(ctx->pop(),this);
data_root<byte_array> name(dpop(),this); data_root<byte_array> name(ctx->pop(),this);
name.untag_check(this); name.untag_check(this);
symbol_char *sym = name->data<symbol_char>(); symbol_char *sym = name->data<symbol_char>();
@ -139,29 +152,29 @@ void factor_vm::primitive_dlsym()
dll *d = untag_check<dll>(library.value()); dll *d = untag_check<dll>(library.value());
if(d->dll == NULL) if(d->dll == NULL)
dpush(false_object); ctx->push(false_object);
else else
box_alien(ffi_dlsym(d,sym)); ctx->push(allot_alien(ffi_dlsym(d,sym)));
} }
else else
box_alien(ffi_dlsym(NULL,sym)); ctx->push(allot_alien(ffi_dlsym(NULL,sym)));
} }
/* close a native library handle */ /* close a native library handle */
void factor_vm::primitive_dlclose() void factor_vm::primitive_dlclose()
{ {
dll *d = untag_check<dll>(dpop()); dll *d = untag_check<dll>(ctx->pop());
if(d->dll != NULL) if(d->dll != NULL)
ffi_dlclose(d); ffi_dlclose(d);
} }
void factor_vm::primitive_dll_validp() void factor_vm::primitive_dll_validp()
{ {
cell library = dpop(); cell library = ctx->pop();
if(to_boolean(library)) if(to_boolean(library))
dpush(tag_boolean(untag_check<dll>(library)->dll != NULL)); ctx->push(tag_boolean(untag_check<dll>(library)->dll != NULL));
else else
dpush(true_object); ctx->push(true_object);
} }
/* gets the address of an object representing a C pointer */ /* gets the address of an object representing a C pointer */
@ -186,32 +199,7 @@ VM_C_API char *alien_offset(cell obj, factor_vm *parent)
return parent->alien_offset(obj); return parent->alien_offset(obj);
} }
/* pop an object representing a C pointer */ /* For FFI calls passing structs by value. Cannot allocate */
char *factor_vm::unbox_alien()
{
return alien_offset(dpop());
}
VM_C_API char *unbox_alien(factor_vm *parent)
{
return parent->unbox_alien();
}
/* make an alien and push */
void factor_vm::box_alien(void *ptr)
{
if(ptr == NULL)
dpush(false_object);
else
dpush(allot_alien(false_object,(cell)ptr));
}
VM_C_API void box_alien(void *ptr, factor_vm *parent)
{
return parent->box_alien(ptr);
}
/* for FFI calls passing structs by value */
void factor_vm::to_value_struct(cell src, void *dest, cell size) void factor_vm::to_value_struct(cell src, void *dest, cell size)
{ {
memcpy(dest,alien_offset(src),size); memcpy(dest,alien_offset(src),size);
@ -222,52 +210,52 @@ VM_C_API void to_value_struct(cell src, void *dest, cell size, factor_vm *parent
return parent->to_value_struct(src,dest,size); return parent->to_value_struct(src,dest,size);
} }
/* for FFI callbacks receiving structs by value */ /* For FFI callbacks receiving structs by value */
void factor_vm::box_value_struct(void *src, cell size) cell factor_vm::from_value_struct(void *src, cell size)
{ {
byte_array *bytes = allot_byte_array(size); byte_array *bytes = allot_byte_array(size);
memcpy(bytes->data<void>(),src,size); memcpy(bytes->data<void>(),src,size);
dpush(tag<byte_array>(bytes)); return tag<byte_array>(bytes);
} }
VM_C_API void box_value_struct(void *src, cell size,factor_vm *parent) VM_C_API cell from_value_struct(void *src, cell size, factor_vm *parent)
{ {
return parent->box_value_struct(src,size); return parent->from_value_struct(src,size);
} }
/* On some x86 OSes, structs <= 8 bytes are returned in registers. */ /* On some x86 OSes, structs <= 8 bytes are returned in registers. */
void factor_vm::box_small_struct(cell x, cell y, cell size) cell factor_vm::from_small_struct(cell x, cell y, cell size)
{ {
cell data[2]; cell data[2];
data[0] = x; data[0] = x;
data[1] = y; data[1] = y;
box_value_struct(data,size); return from_value_struct(data,size);
} }
VM_C_API void box_small_struct(cell x, cell y, cell size, factor_vm *parent) VM_C_API cell from_small_struct(cell x, cell y, cell size, factor_vm *parent)
{ {
return parent->box_small_struct(x,y,size); return parent->from_small_struct(x,y,size);
} }
/* On OS X/PPC, complex numbers are returned in registers. */ /* On OS X/PPC, complex numbers are returned in registers. */
void factor_vm::box_medium_struct(cell x1, cell x2, cell x3, cell x4, cell size) cell factor_vm::from_medium_struct(cell x1, cell x2, cell x3, cell x4, cell size)
{ {
cell data[4]; cell data[4];
data[0] = x1; data[0] = x1;
data[1] = x2; data[1] = x2;
data[2] = x3; data[2] = x3;
data[3] = x4; data[3] = x4;
box_value_struct(data,size); return from_value_struct(data,size);
} }
VM_C_API void box_medium_struct(cell x1, cell x2, cell x3, cell x4, cell size, factor_vm *parent) VM_C_API cell from_medium_struct(cell x1, cell x2, cell x3, cell x4, cell size, factor_vm *parent)
{ {
return parent->box_medium_struct(x1, x2, x3, x4, size); return parent->from_medium_struct(x1, x2, x3, x4, size);
} }
void factor_vm::primitive_vm_ptr() void factor_vm::primitive_vm_ptr()
{ {
box_alien(this); ctx->push(allot_alien(this));
} }
} }

View File

@ -2,11 +2,11 @@ namespace factor
{ {
VM_C_API char *alien_offset(cell object, factor_vm *vm); VM_C_API char *alien_offset(cell object, factor_vm *vm);
VM_C_API char *unbox_alien(factor_vm *vm); VM_C_API char *pinned_alien_offset(cell object, factor_vm *vm);
VM_C_API void box_alien(void *ptr, factor_vm *vm); VM_C_API cell allot_alien(void *address, factor_vm *vm);
VM_C_API void to_value_struct(cell src, void *dest, cell size, factor_vm *vm); VM_C_API void to_value_struct(cell src, void *dest, cell size, factor_vm *vm);
VM_C_API void box_value_struct(void *src, cell size,factor_vm *vm); VM_C_API cell from_value_struct(void *src, cell size, factor_vm *vm);
VM_C_API void box_small_struct(cell x, cell y, cell size,factor_vm *vm); VM_C_API cell from_small_struct(cell x, cell y, cell size, factor_vm *vm);
VM_C_API void box_medium_struct(cell x1, cell x2, cell x3, cell x4, cell size,factor_vm *vm); VM_C_API cell from_medium_struct(cell x1, cell x2, cell x3, cell x4, cell size, factor_vm *vm);
} }

View File

@ -13,11 +13,11 @@ array *factor_vm::allot_array(cell capacity, cell fill_)
void factor_vm::primitive_array() void factor_vm::primitive_array()
{ {
data_root<object> fill(dpop(),this); data_root<object> fill(ctx->pop(),this);
cell capacity = unbox_array_size(); cell capacity = unbox_array_size();
array *new_array = allot_uninitialized_array<array>(capacity); array *new_array = allot_uninitialized_array<array>(capacity);
memset_cell(new_array->data(),fill.value(),capacity * sizeof(cell)); memset_cell(new_array->data(),fill.value(),capacity * sizeof(cell));
dpush(tag<array>(new_array)); ctx->push(tag<array>(new_array));
} }
cell factor_vm::allot_array_1(cell obj_) cell factor_vm::allot_array_1(cell obj_)
@ -54,10 +54,10 @@ cell factor_vm::allot_array_4(cell v1_, cell v2_, cell v3_, cell v4_)
void factor_vm::primitive_resize_array() void factor_vm::primitive_resize_array()
{ {
data_root<array> a(dpop(),this); data_root<array> a(ctx->pop(),this);
a.untag_check(this); a.untag_check(this);
cell capacity = unbox_array_size(); cell capacity = unbox_array_size();
dpush(tag<array>(reallot_array(a.untagged(),capacity))); ctx->push(tag<array>(reallot_array(a.untagged(),capacity)));
} }
void growable_array::add(cell elt_) void growable_array::add(cell elt_)

View File

@ -329,6 +329,7 @@ bignum *factor_vm::bignum_remainder(bignum * numerator, bignum * denominator)
} }
} }
/* allocates memory */
#define FOO_TO_BIGNUM(name,type,utype) \ #define FOO_TO_BIGNUM(name,type,utype) \
bignum * factor_vm::name##_to_bignum(type n) \ bignum * factor_vm::name##_to_bignum(type n) \
{ \ { \
@ -358,13 +359,13 @@ bignum * factor_vm::name##_to_bignum(type n) \
return (result); \ return (result); \
} \ } \
} }
/* all below allocate memory */
FOO_TO_BIGNUM(cell,cell,cell) FOO_TO_BIGNUM(cell,cell,cell)
FOO_TO_BIGNUM(fixnum,fixnum,cell) FOO_TO_BIGNUM(fixnum,fixnum,cell)
FOO_TO_BIGNUM(long_long,s64,u64) FOO_TO_BIGNUM(long_long,s64,u64)
FOO_TO_BIGNUM(ulong_long,u64,u64) FOO_TO_BIGNUM(ulong_long,u64,u64)
/* cannot allocate memory */
#define BIGNUM_TO_FOO(name,type,utype) \ #define BIGNUM_TO_FOO(name,type,utype) \
type factor_vm::bignum_to_##name(bignum * bignum) \ type factor_vm::bignum_to_##name(bignum * bignum) \
{ \ { \
@ -380,7 +381,6 @@ FOO_TO_BIGNUM(ulong_long,u64,u64)
} \ } \
} }
/* all of the below allocate memory */
BIGNUM_TO_FOO(cell,cell,cell); BIGNUM_TO_FOO(cell,cell,cell);
BIGNUM_TO_FOO(fixnum,fixnum,cell); BIGNUM_TO_FOO(fixnum,fixnum,cell);
BIGNUM_TO_FOO(long_long,s64,u64) BIGNUM_TO_FOO(long_long,s64,u64)

View File

@ -3,19 +3,14 @@
namespace factor namespace factor
{ {
void factor_vm::box_boolean(bool value)
{
dpush(tag_boolean(value));
}
VM_C_API void box_boolean(bool value, factor_vm *parent)
{
return parent->box_boolean(value);
}
VM_C_API bool to_boolean(cell value, factor_vm *parent) VM_C_API bool to_boolean(cell value, factor_vm *parent)
{ {
return to_boolean(value); return to_boolean(value);
} }
VM_C_API cell from_boolean(bool value, factor_vm *parent)
{
return parent->tag_boolean(value);
}
} }

View File

@ -1,9 +1,10 @@
namespace factor namespace factor
{ {
VM_C_API void box_boolean(bool value, factor_vm *vm);
VM_C_API bool to_boolean(cell value, factor_vm *vm); VM_C_API bool to_boolean(cell value, factor_vm *vm);
VM_C_API cell from_boolean(bool value, factor_vm *vm);
/* Cannot allocate */
inline static bool to_boolean(cell value) inline static bool to_boolean(cell value)
{ {
return value != false_object; return value != false_object;

View File

@ -13,21 +13,21 @@ byte_array *factor_vm::allot_byte_array(cell size)
void factor_vm::primitive_byte_array() void factor_vm::primitive_byte_array()
{ {
cell size = unbox_array_size(); cell size = unbox_array_size();
dpush(tag<byte_array>(allot_byte_array(size))); ctx->push(tag<byte_array>(allot_byte_array(size)));
} }
void factor_vm::primitive_uninitialized_byte_array() void factor_vm::primitive_uninitialized_byte_array()
{ {
cell size = unbox_array_size(); cell size = unbox_array_size();
dpush(tag<byte_array>(allot_uninitialized_array<byte_array>(size))); ctx->push(tag<byte_array>(allot_uninitialized_array<byte_array>(size)));
} }
void factor_vm::primitive_resize_byte_array() void factor_vm::primitive_resize_byte_array()
{ {
data_root<byte_array> array(dpop(),this); data_root<byte_array> array(ctx->pop(),this);
array.untag_check(this); array.untag_check(this);
cell capacity = unbox_array_size(); cell capacity = unbox_array_size();
dpush(tag<byte_array>(reallot_array(array.untagged(),capacity))); ctx->push(tag<byte_array>(reallot_array(array.untagged(),capacity)));
} }
void growable_byte_array::append_bytes(void *elts, cell len) void growable_byte_array::append_bytes(void *elts, cell len)

View File

@ -81,9 +81,9 @@ void callback_heap::update()
void factor_vm::primitive_callback() void factor_vm::primitive_callback()
{ {
tagged<word> w(dpop()); tagged<word> w(ctx->pop());
w.untag_check(this); w.untag_check(this);
box_alien(callbacks->add(w.value())->xt()); ctx->push(allot_alien(callbacks->add(w.value())->xt()));
} }
} }

View File

@ -57,14 +57,15 @@ void factor_vm::primitive_callstack()
callstack *stack = allot_callstack(size); callstack *stack = allot_callstack(size);
memcpy(stack->top(),top,size); memcpy(stack->top(),top,size);
dpush(tag<callstack>(stack)); ctx->push(tag<callstack>(stack));
} }
void factor_vm::primitive_set_callstack() void factor_vm::primitive_set_callstack()
{ {
callstack *stack = untag_check<callstack>(dpop()); callstack *stack = untag_check<callstack>(ctx->pop());
set_callstack(ctx->callstack_bottom, set_callstack(this,
ctx->callstack_bottom,
stack->top(), stack->top(),
untag_fixnum(stack->length), untag_fixnum(stack->length),
memcpy); memcpy);
@ -157,13 +158,13 @@ struct stack_frame_accumulator {
void factor_vm::primitive_callstack_to_array() void factor_vm::primitive_callstack_to_array()
{ {
data_root<callstack> callstack(dpop(),this); data_root<callstack> callstack(ctx->pop(),this);
stack_frame_accumulator accum(this); stack_frame_accumulator accum(this);
iterate_callstack_object(callstack.untagged(),accum); iterate_callstack_object(callstack.untagged(),accum);
accum.frames.trim(); accum.frames.trim();
dpush(accum.frames.elements.value()); ctx->push(accum.frames.elements.value());
} }
stack_frame *factor_vm::innermost_stack_frame(callstack *stack) stack_frame *factor_vm::innermost_stack_frame(callstack *stack)
@ -182,20 +183,20 @@ stack_frame *factor_vm::innermost_stack_frame(callstack *stack)
Used by the single stepper. */ Used by the single stepper. */
void factor_vm::primitive_innermost_stack_frame_executing() void factor_vm::primitive_innermost_stack_frame_executing()
{ {
stack_frame *frame = innermost_stack_frame(untag_check<callstack>(dpop())); stack_frame *frame = innermost_stack_frame(untag_check<callstack>(ctx->pop()));
dpush(frame_executing_quot(frame)); ctx->push(frame_executing_quot(frame));
} }
void factor_vm::primitive_innermost_stack_frame_scan() void factor_vm::primitive_innermost_stack_frame_scan()
{ {
stack_frame *frame = innermost_stack_frame(untag_check<callstack>(dpop())); stack_frame *frame = innermost_stack_frame(untag_check<callstack>(ctx->pop()));
dpush(frame_scan(frame)); ctx->push(frame_scan(frame));
} }
void factor_vm::primitive_set_innermost_stack_frame_quot() void factor_vm::primitive_set_innermost_stack_frame_quot()
{ {
data_root<callstack> callstack(dpop(),this); data_root<callstack> callstack(ctx->pop(),this);
data_root<quotation> quot(dpop(),this); data_root<quotation> quot(ctx->pop(),this);
callstack.untag_check(this); callstack.untag_check(this);
quot.untag_check(this); quot.untag_check(this);
@ -208,15 +209,4 @@ void factor_vm::primitive_set_innermost_stack_frame_quot()
FRAME_RETURN_ADDRESS(inner,this) = (char *)quot->xt + offset; FRAME_RETURN_ADDRESS(inner,this) = (char *)quot->xt + offset;
} }
/* called before entry into Factor code. */
void factor_vm::save_callstack_bottom(stack_frame *callstack_bottom)
{
ctx->callstack_bottom = callstack_bottom;
}
VM_ASM_API void save_callstack_bottom(stack_frame *callstack_bottom, factor_vm *parent)
{
return parent->save_callstack_bottom(callstack_bottom);
}
} }

View File

@ -6,8 +6,6 @@ inline static cell callstack_size(cell size)
return sizeof(callstack) + size; return sizeof(callstack) + size;
} }
VM_ASM_API void save_callstack_bottom(stack_frame *callstack_bottom, factor_vm *parent);
/* This is a little tricky. The iterator may allocate memory, so we /* This is a little tricky. The iterator may allocate memory, so we
keep the callstack in a GC root and use relative offsets */ keep the callstack in a GC root and use relative offsets */
template<typename Iterator> void factor_vm::iterate_callstack_object(callstack *stack_, Iterator &iterator) template<typename Iterator> void factor_vm::iterate_callstack_object(callstack *stack_, Iterator &iterator)

View File

@ -73,7 +73,7 @@ void code_block_visitor<Visitor>::visit_object_code_block(object *obj)
if(q->code) if(q->code)
parent->set_quot_xt(q,visitor(q->code)); parent->set_quot_xt(q,visitor(q->code));
else else
q->xt = (void *)lazy_jit_compile; q->xt = (void *)lazy_jit_compile_impl;
break; break;
} }
case CALLSTACK_TYPE: case CALLSTACK_TYPE:

View File

@ -36,7 +36,11 @@ struct code_block
cell size() const cell size() const
{ {
return header & ~7; cell size = header & ~7;
#ifdef FACTOR_DEBUG
assert(size > 0);
#endif
return size;
} }
void *xt() const void *xt() const

View File

@ -96,7 +96,7 @@ void factor_vm::update_code_heap_words()
void factor_vm::primitive_modify_code_heap() void factor_vm::primitive_modify_code_heap()
{ {
data_root<array> alist(dpop(),this); data_root<array> alist(ctx->pop(),this);
cell count = array_capacity(alist.untagged()); cell count = array_capacity(alist.untagged());
@ -163,7 +163,7 @@ code_heap_room factor_vm::code_room()
void factor_vm::primitive_code_room() void factor_vm::primitive_code_room()
{ {
code_heap_room room = code_room(); code_heap_room room = code_room();
dpush(tag<byte_array>(byte_array_from_value(&room))); ctx->push(tag<byte_array>(byte_array_from_value(&room)));
} }
struct stack_trace_stripper { struct stack_trace_stripper {

View File

@ -155,6 +155,34 @@ struct code_block_compaction_updater {
} }
}; };
/* After a compaction, invalidate any code heap roots which are not
marked, and also slide the valid roots up so that call sites can be updated
correctly in case an inline cache compilation triggered compaction. */
void factor_vm::update_code_roots_for_compaction()
{
std::vector<code_root *>::const_iterator iter = code_roots.begin();
std::vector<code_root *>::const_iterator end = code_roots.end();
mark_bits<code_block> *state = &code->allocator->state;
for(; iter < end; iter++)
{
code_root *root = *iter;
code_block *block = (code_block *)(root->value & -data_alignment);
/* Offset of return address within 16-byte allocation line */
cell offset = root->value - (cell)block;
if(root->valid && state->marked_p(block))
{
block = state->forward_block(block);
root->value = (cell)block + offset;
}
else
root->valid = false;
}
}
/* Compact data and code heaps */ /* Compact data and code heaps */
void factor_vm::collect_compact_impl(bool trace_contexts_p) void factor_vm::collect_compact_impl(bool trace_contexts_p)
{ {

View File

@ -8,42 +8,15 @@ context::context(cell ds_size, cell rs_size) :
callstack_bottom(NULL), callstack_bottom(NULL),
datastack(0), datastack(0),
retainstack(0), retainstack(0),
datastack_save(0),
retainstack_save(0),
magic_frame(NULL), 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),
current_callback_save(0), current_callback_save(0),
next(NULL) {} next(NULL)
void factor_vm::reset_datastack()
{ {
ds = ds_bot - sizeof(cell); reset_datastack();
} reset_retainstack();
void factor_vm::reset_retainstack()
{
rs = rs_bot - sizeof(cell);
}
static const cell stack_reserved = (64 * sizeof(cell));
void factor_vm::fix_stacks()
{
if(ds + sizeof(cell) < ds_bot || ds + stack_reserved >= ds_top) reset_datastack();
if(rs + sizeof(cell) < rs_bot || rs + stack_reserved >= rs_top) reset_retainstack();
}
/* called before entry into foreign C code. Note that ds and rs might
be stored in registers, so callbacks must save and restore the correct values */
void factor_vm::save_stacks()
{
if(ctx)
{
ctx->datastack = ds;
ctx->retainstack = rs;
}
} }
context *factor_vm::alloc_context() context *factor_vm::alloc_context()
@ -75,30 +48,17 @@ void factor_vm::nest_stacks(stack_frame *magic_frame)
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;
/* note that these register values are not necessarily valid stack
pointers. they are merely saved non-volatile registers, and are
restored in unnest_stacks(). consider this scenario:
- factor code calls C function
- C function saves ds/cs registers (since they're non-volatile)
- C function clobbers them
- C function calls Factor callback
- Factor callback returns
- C function restores registers
- C function returns to Factor code */
new_ctx->datastack_save = ds;
new_ctx->retainstack_save = rs;
new_ctx->magic_frame = magic_frame; 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];
new_ctx->reset_datastack();
new_ctx->reset_retainstack();
new_ctx->next = ctx; new_ctx->next = ctx;
ctx = new_ctx; ctx = new_ctx;
reset_datastack();
reset_retainstack();
} }
void nest_stacks(stack_frame *magic_frame, factor_vm *parent) void nest_stacks(stack_frame *magic_frame, factor_vm *parent)
@ -109,9 +69,6 @@ void nest_stacks(stack_frame *magic_frame, factor_vm *parent)
/* called when leaving a compiled callback */ /* called when leaving a compiled callback */
void factor_vm::unnest_stacks() void factor_vm::unnest_stacks()
{ {
ds = ctx->datastack_save;
rs = ctx->retainstack_save;
/* restore per-callback special_objects */ /* restore per-callback special_objects */
special_objects[OBJ_CURRENT_CALLBACK] = ctx->current_callback_save; special_objects[OBJ_CURRENT_CALLBACK] = ctx->current_callback_save;
special_objects[OBJ_CATCHSTACK] = ctx->catchstack_save; special_objects[OBJ_CATCHSTACK] = ctx->catchstack_save;
@ -145,20 +102,20 @@ bool factor_vm::stack_to_array(cell bottom, cell top)
{ {
array *a = allot_uninitialized_array<array>(depth / sizeof(cell)); array *a = allot_uninitialized_array<array>(depth / sizeof(cell));
memcpy(a + 1,(void*)bottom,depth); memcpy(a + 1,(void*)bottom,depth);
dpush(tag<array>(a)); ctx->push(tag<array>(a));
return true; return true;
} }
} }
void factor_vm::primitive_datastack() void factor_vm::primitive_datastack()
{ {
if(!stack_to_array(ds_bot,ds)) if(!stack_to_array(ctx->datastack_region->start,ctx->datastack))
general_error(ERROR_DS_UNDERFLOW,false_object,false_object,NULL); general_error(ERROR_DS_UNDERFLOW,false_object,false_object,NULL);
} }
void factor_vm::primitive_retainstack() void factor_vm::primitive_retainstack()
{ {
if(!stack_to_array(rs_bot,rs)) if(!stack_to_array(ctx->retainstack_region->start,ctx->retainstack))
general_error(ERROR_RS_UNDERFLOW,false_object,false_object,NULL); general_error(ERROR_RS_UNDERFLOW,false_object,false_object,NULL);
} }
@ -172,46 +129,48 @@ cell factor_vm::array_to_stack(array *array, cell bottom)
void factor_vm::primitive_set_datastack() void factor_vm::primitive_set_datastack()
{ {
ds = array_to_stack(untag_check<array>(dpop()),ds_bot); ctx->datastack = array_to_stack(untag_check<array>(ctx->pop()),ctx->datastack_region->start);
} }
void factor_vm::primitive_set_retainstack() void factor_vm::primitive_set_retainstack()
{ {
rs = array_to_stack(untag_check<array>(dpop()),rs_bot); ctx->retainstack = array_to_stack(untag_check<array>(ctx->pop()),ctx->retainstack_region->start);
} }
/* Used to implement call( */ /* Used to implement call( */
void factor_vm::primitive_check_datastack() void factor_vm::primitive_check_datastack()
{ {
fixnum out = to_fixnum(dpop()); fixnum out = to_fixnum(ctx->pop());
fixnum in = to_fixnum(dpop()); fixnum in = to_fixnum(ctx->pop());
fixnum height = out - in; fixnum height = out - in;
array *saved_datastack = untag_check<array>(dpop()); array *saved_datastack = untag_check<array>(ctx->pop());
fixnum saved_height = array_capacity(saved_datastack); fixnum saved_height = array_capacity(saved_datastack);
fixnum current_height = (ds - ds_bot + sizeof(cell)) / sizeof(cell); fixnum current_height = (ctx->datastack - ctx->datastack_region->start + sizeof(cell)) / sizeof(cell);
if(current_height - height != saved_height) if(current_height - height != saved_height)
dpush(false_object); ctx->push(false_object);
else else
{ {
fixnum i; cell *ds_bot = (cell *)ctx->datastack_region->start;
for(i = 0; i < saved_height - in; i++) for(fixnum i = 0; i < saved_height - in; i++)
{ {
if(((cell *)ds_bot)[i] != array_nth(saved_datastack,i)) if(ds_bot[i] != array_nth(saved_datastack,i))
{ {
dpush(false_object); ctx->push(false_object);
return; return;
} }
} }
dpush(true_object); ctx->push(true_object);
} }
} }
void factor_vm::primitive_load_locals() void factor_vm::primitive_load_locals()
{ {
fixnum count = untag_fixnum(dpop()); fixnum count = untag_fixnum(ctx->pop());
memcpy((cell *)(rs + sizeof(cell)),(cell *)(ds - sizeof(cell) * (count - 1)),sizeof(cell) * count); memcpy((cell *)(ctx->retainstack + sizeof(cell)),
ds -= sizeof(cell) * count; (cell *)(ctx->datastack - sizeof(cell) * (count - 1)),
rs += sizeof(cell) * count; sizeof(cell) * count);
ctx->datastack -= sizeof(cell) * count;
ctx->retainstack += sizeof(cell) * count;
} }
} }

View File

@ -1,11 +1,7 @@
namespace factor namespace factor
{ {
/* Assembly code makes assumptions about the layout of this struct: /* Assembly code makes assumptions about the layout of this struct */
- callstack_top field is 0
- callstack_bottom field is 1
- datastack field is 2
- retainstack field is 3 */
struct context { struct context {
/* C stack pointer on entry */ /* C stack pointer on entry */
stack_frame *callstack_top; stack_frame *callstack_top;
@ -17,12 +13,6 @@ struct context {
/* current retain stack top pointer */ /* current retain stack top pointer */
cell retainstack; cell retainstack;
/* saved contents of ds register on entry to callback */
cell datastack_save;
/* saved contents of rs register on entry to callback */
cell retainstack_save;
/* callback-bottom stack frame, or NULL for top-level context. /* callback-bottom stack frame, or NULL for top-level context.
When nest_stacks() is called, callstack layout with callbacks When nest_stacks() is called, callstack layout with callbacks
is as follows: is as follows:
@ -48,36 +38,54 @@ struct context {
context *next; context *next;
context(cell ds_size, cell rs_size); context(cell ds_size, cell rs_size);
cell peek()
{
return *(cell *)datastack;
}
void replace(cell tagged)
{
*(cell *)datastack = tagged;
}
cell pop()
{
cell value = peek();
datastack -= sizeof(cell);
return value;
}
void push(cell tagged)
{
datastack += sizeof(cell);
replace(tagged);
}
void reset_datastack()
{
datastack = datastack_region->start - sizeof(cell);
}
void reset_retainstack()
{
retainstack = retainstack_region->start - sizeof(cell);
}
static const cell stack_reserved = (64 * sizeof(cell));
void fix_stacks()
{
if(datastack + sizeof(cell) < datastack_region->start
|| datastack + stack_reserved >= datastack_region->end)
reset_datastack();
if(retainstack + sizeof(cell) < retainstack_region->start
|| retainstack + stack_reserved >= retainstack_region->end)
reset_retainstack();
}
}; };
#define ds_bot (ctx->datastack_region->start)
#define ds_top (ctx->datastack_region->end)
#define rs_bot (ctx->retainstack_region->start)
#define rs_top (ctx->retainstack_region->end)
inline cell dpeek()
{
return *(cell *)ds;
}
inline void drepl(cell tagged)
{
*(cell *)ds = tagged;
}
inline cell dpop()
{
cell value = dpeek();
ds -= sizeof(cell);
return value;
}
inline void dpush(cell tagged)
{
ds += sizeof(cell);
drepl(tagged);
}
VM_C_API void nest_stacks(stack_frame *magic_frame, factor_vm *vm); VM_C_API void nest_stacks(stack_frame *magic_frame, factor_vm *vm);
VM_C_API void unnest_stacks(factor_vm *vm); VM_C_API void unnest_stacks(factor_vm *vm);

View File

@ -225,11 +225,11 @@ DEF(void,throw_impl,(cell quot, F_STACK_FRAME *rewind_to, void *vm)):
mtlr r0 mtlr r0
JUMP_QUOT /* call the quotation */ JUMP_QUOT /* call the quotation */
DEF(void,lazy_jit_compile,(cell quot, void *vm)): DEF(void,lazy_jit_compile_impl,(cell quot, void *vm)):
mr r5,r4 /* vm ptr is 3rd arg */ mr r5,r4 /* vm ptr is 3rd arg */
mr r4,r1 /* save stack pointer */ mr r4,r1 /* save stack pointer */
PROLOGUE PROLOGUE
bl MANGLE(lazy_jit_compile_impl) bl MANGLE(lazy_jit_compile)
EPILOGUE EPILOGUE
JUMP_QUOT /* call the quotation */ JUMP_QUOT /* call the quotation */

View File

@ -2,10 +2,6 @@ namespace factor
{ {
#define FACTOR_CPU_STRING "ppc" #define FACTOR_CPU_STRING "ppc"
#define VM_ASM_API VM_C_API
register cell ds asm("r13");
register cell rs asm("r14");
/* In the instruction sequence: /* In the instruction sequence:
@ -81,14 +77,16 @@ inline static unsigned int fpu_status(unsigned int status)
} }
/* Defined in assembly */ /* Defined in assembly */
VM_ASM_API void c_to_factor(cell quot, void *vm); VM_C_API void c_to_factor(cell quot, void *vm);
VM_ASM_API void throw_impl(cell quot, stack_frame *rewind, void *vm); VM_C_API void throw_impl(cell quot, void *new_stack, void *vm);
VM_ASM_API void lazy_jit_compile(cell quot, void *vm); VM_C_API void lazy_jit_compile_impl(cell quot, void *vm);
VM_ASM_API void flush_icache(cell start, cell len); VM_C_API void flush_icache(cell start, cell len);
VM_ASM_API void set_callstack(stack_frame *to, VM_C_API void set_callstack(
stack_frame *from, void *vm,
cell length, stack_frame *to,
void *(*memcpy)(void*,const void*, size_t)); stack_frame *from,
cell length,
void *(*memcpy)(void*,const void*, size_t));
} }

View File

@ -1,66 +1,148 @@
#include "asm.h" #include "asm.h"
#define ARG0 %eax
#define ARG1 %edx
#define ARG2 %ecx
#define STACK_REG %esp
#define DS_REG %esi #define DS_REG %esi
#define RS_REG %edi
#define RETURN_REG %eax #define RETURN_REG %eax
#define NV0 %ebx
#define NV1 %ebp
#define CELL_SIZE 4
#define STACK_PADDING 12
#define PUSH_NONVOLATILE \
push %ebx ; \
push %ebp
#define POP_NONVOLATILE \
pop %ebp ; \
pop %ebx
#define QUOT_XT_OFFSET 12 #define QUOT_XT_OFFSET 12
/* We pass a function pointer to memcpy to work around a Mac OS X DEF(void,c_to_factor,(cell quot, void *vm)):
ABI limitation which would otherwise require us to do a bizzaro PC-relative /* Load parameters */
trampoline to retrieve the function address */ mov 4(%esp),%eax
DEF(void,set_callstack,(F_STACK_FRAME *to, F_STACK_FRAME *from, CELL length, void *memcpy)): mov 8(%esp),%edx
mov 4(%esp),%ebp /* to */
mov 8(%esp),%edx /* from */ /* Save non-volatile registers */
mov 12(%esp),%ecx /* length */ push %ebx
mov 16(%esp),%eax /* memcpy */ push %ebp
sub %ecx,%ebp /* compute new stack pointer */ push %esi
push %edi
/* Save old stack pointer and align */
mov %esp,%ebp
and $-16,%esp
push %ebp
/* Set up stack frame for the call to the boot quotation */
sub $4,%esp
push %edx
push %eax
/* Load context */
mov (%edx),%ecx
/* Load ctx->datastack */
mov 8(%ecx),DS_REG
/* Load ctx->retainstack */
mov 12(%ecx),RS_REG
/* Save ctx->callstack_bottom */
lea -4(%esp),%ebx
mov %ebx,4(%ecx)
/* Call quot-xt */
call *QUOT_XT_OFFSET(%eax)
/* Tear down stack frame for the call to the boot quotation */
pop %eax
pop %edx
add $4,%esp
/* Undo stack alignment */
pop %ebp
mov %ebp,%esp mov %ebp,%esp
push %ecx /* pass length */
push %edx /* pass src */
push %ebp /* pass dst */
call *%eax /* call memcpy */
add $12,%esp /* pop args from the stack */
ret /* return _with new stack_ */
DEF(F_FASTCALL void,throw_impl,(CELL quot, F_STACK_FRAME *rewind_to, void *vm)): /* Load context */
mov ARG2,NV0 /* remember vm ptr in case quot_xt = lazy_jit_compile */ mov (%edx),%ecx
/* Save ctx->datastack */
mov DS_REG,8(%ecx)
/* Save ctx->retainstack */
mov RS_REG,12(%ecx)
/* Restore non-volatile registers */
pop %edi
pop %esi
pop %ebp
pop %ebx
ret
DEF(void,set_callstack,(void *vm, stack_frame *to, stack_frame *from, cell length, void *memcpy)):
/* load arguments */
mov 4(%esp),%ebx /* vm - to non-volatile register */
mov 8(%esp),%ebp /* to */
mov 12(%esp),%edx /* from */
mov 16(%esp),%ecx /* length */
mov 20(%esp),%eax /* memcpy */
/* compute new stack pointer */
sub %ecx,%ebp
mov %ebp,%esp
/* call memcpy */
push %ecx /* pass length */
push %edx /* pass src */
push %ebp /* pass dst */
call *%eax
add $12,%esp
/* load context */
mov (%ebx),%ecx
/* load datastack */
mov 8(%ecx),DS_REG
/* load retainstack */
mov 12(%ecx),RS_REG
/* return with new stack */
ret
DEF(void,throw_impl,(cell quot, void *new_stack, void *vm)):
/* clear x87 stack, but preserve rounding mode and exception flags */ /* clear x87 stack, but preserve rounding mode and exception flags */
sub $2,STACK_REG sub $2,%esp
fnstcw (STACK_REG) fnstcw (%esp)
fninit fninit
fldcw (STACK_REG) fldcw (%esp)
/* rewind_to */ add $2,%esp
mov ARG1,STACK_REG
mov NV0,ARG1
jmp *QUOT_XT_OFFSET(ARG0)
DEF(F_FASTCALL void,lazy_jit_compile,(CELL quot, void *vm)): /* load quotation and vm parameters */
mov ARG1,ARG2 mov 4(%esp),%eax
mov STACK_REG,ARG1 /* Save stack pointer */ mov 12(%esp),%edx
sub $STACK_PADDING,STACK_REG
call MANGLE(lazy_jit_compile_impl)
mov RETURN_REG,ARG0 /* No-op on 32-bit */
add $STACK_PADDING,STACK_REG
jmp *QUOT_XT_OFFSET(ARG0) /* Call the quotation */
/* load new stack pointer */
mov 8(%esp),%esp
/* load context */
mov (%edx),%ecx
/* load datastack */
mov 8(%ecx),DS_REG
/* load retainstack */
mov 12(%ecx),RS_REG
/* call the error handler */
jmp *QUOT_XT_OFFSET(%eax)
DEF(void,lazy_jit_compile_impl,(cell quot, void *vm)):
/* load context */
mov (%edx),%ecx
/* save datastack */
mov DS_REG,8(%ecx)
/* save retainstack */
mov RS_REG,12(%ecx)
/* save callstack */
lea -4(%esp),%ebp
mov %ebp,(%ecx)
/* compile quotation */
sub $4,%esp
push %edx
push %eax
call MANGLE(lazy_jit_compile)
add $12,%esp
/* call quotation */
jmp *QUOT_XT_OFFSET(%eax)
DEF(long long,read_timestamp_counter,(void)): DEF(long long,read_timestamp_counter,(void)):
rdtsc rdtsc

View File

@ -3,8 +3,4 @@ namespace factor
#define FACTOR_CPU_STRING "x86.32" #define FACTOR_CPU_STRING "x86.32"
register cell ds asm("esi");
register cell rs asm("edi");
#define VM_ASM_API VM_C_API __attribute__ ((regparm (3)))
} }

View File

@ -1,14 +1,10 @@
#include "asm.h" #include "asm.h"
#define STACK_REG %rsp
#define DS_REG %r14 #define DS_REG %r14
#define RS_REG %r15
#define RETURN_REG %rax #define RETURN_REG %rax
#define CELL_SIZE 8 #define QUOT_XT_OFFSET 28
#define STACK_PADDING 56
#define NV0 %rbp
#define NV1 %r12
#ifdef WINDOWS #ifdef WINDOWS
@ -18,6 +14,8 @@
#define ARG3 %r9 #define ARG3 %r9
#define PUSH_NONVOLATILE \ #define PUSH_NONVOLATILE \
push %r15 ; \
push %r14 ; \
push %r12 ; \ push %r12 ; \
push %r13 ; \ push %r13 ; \
push %rdi ; \ push %rdi ; \
@ -31,7 +29,9 @@
pop %rsi ; \ pop %rsi ; \
pop %rdi ; \ pop %rdi ; \
pop %r13 ; \ pop %r13 ; \
pop %r12 pop %r12 ; \
pop %r14 ; \
pop %r15
#else #else
@ -44,9 +44,13 @@
push %rbx ; \ push %rbx ; \
push %rbp ; \ push %rbp ; \
push %r12 ; \ push %r12 ; \
push %r13 push %r13 ; \
push %r14 ; \
push %r15
#define POP_NONVOLATILE \ #define POP_NONVOLATILE \
pop %r15 ; \
pop %r14 ; \
pop %r13 ; \ pop %r13 ; \
pop %r12 ; \ pop %r12 ; \
pop %rbp ; \ pop %rbp ; \
@ -54,36 +58,122 @@
#endif #endif
#define QUOT_XT_OFFSET 28 DEF(void,c_to_factor,(cell quot, void *vm)):
PUSH_NONVOLATILE
/* We pass a function pointer to memcpy to work around a Mac OS X /* Save old stack pointer and align */
ABI limitation which would otherwise require us to do a bizzaro PC-relative mov %rsp,%rbp
trampoline to retrieve the function address */ and $-16,%rsp
DEF(void,set_callstack,(F_STACK_FRAME *to, F_STACK_FRAME *from, CELL length, void *memcpy)): push %rbp
sub ARG2,ARG0 /* compute new stack pointer */
mov ARG0,%rsp
call *ARG3 /* call memcpy */
ret /* return _with new stack_ */
DEF(F_FASTCALL void,throw_impl,(CELL quot, F_STACK_FRAME *rewind_to, void *vm)): /* Set up stack frame for the call to the boot quotation */
push ARG0
push ARG1
/* Create register shadow area (required for Win64 only) */
sub $40,%rsp
/* Load context */
mov (ARG1),ARG2
/* Save ctx->callstack_bottom */
lea -8(%rsp),ARG3
mov ARG3,8(ARG2)
/* Load ctx->datastack */
mov 16(ARG2),DS_REG
/* Load ctx->retainstack */
mov 24(ARG2),RS_REG
/* Call quot-xt */
call *QUOT_XT_OFFSET(ARG0)
/* Tear down register shadow area */
add $40,%rsp
/* Tear down stack frame for the call to the boot quotation */
pop ARG1
pop ARG0
/* Undo stack alignment */
pop %rbp
mov %rbp,%rsp
/* Load context */
mov (ARG1),ARG2
/* Save ctx->datastack */
mov DS_REG,16(ARG2)
/* Save ctx->retainstack */
mov RS_REG,24(ARG2)
POP_NONVOLATILE
ret
DEF(void,set_callstack,(void *vm, stack_frame *to, stack_frame *from, cell length)):
/* save VM pointer in non-volatile register */
mov ARG0,%rbp
/* compute new stack pointer */
sub ARG3,ARG1
mov ARG1,%rsp
/* call memcpy */
mov ARG1,ARG0
mov ARG2,ARG1
mov ARG3,ARG2
call MANGLE(memcpy)
/* load context */
mov (%rbp),ARG2
/* load datastack */
mov 16(ARG2),DS_REG
/* load retainstack */
mov 24(ARG2),RS_REG
/* return with new stack */
ret
DEF(void,throw_impl,(cell quot, void *new_stack, void *vm)):
/* clear x87 stack, but preserve rounding mode and exception flags */ /* clear x87 stack, but preserve rounding mode and exception flags */
sub $2,STACK_REG sub $2,%rsp
fnstcw (STACK_REG) fnstcw (%rsp)
fninit fninit
fldcw (STACK_REG) fldcw (%rsp)
/* rewind_to */
mov ARG1,STACK_REG /* shuffle args */
mov ARG2,ARG1 /* make vm ptr 2nd arg in case quot_xt = lazy_jit_compile */ mov ARG1,%rsp
mov ARG2,ARG1
/* load context */
mov (ARG1),ARG2
/* load datastack */
mov 16(ARG2),DS_REG
/* load retainstack */
mov 24(ARG2),RS_REG
jmp *QUOT_XT_OFFSET(ARG0) jmp *QUOT_XT_OFFSET(ARG0)
DEF(F_FASTCALL void,lazy_jit_compile,(CELL quot, void *vm)): DEF(void,lazy_jit_compile_impl,(cell quot, void *vm)):
mov ARG1,ARG2 /* vm is 3rd arg */ /* load context */
mov STACK_REG,ARG1 /* Save stack pointer */ mov (ARG1),ARG2
sub $STACK_PADDING,STACK_REG /* save datastack */
call MANGLE(lazy_jit_compile_impl) mov DS_REG,16(ARG2)
mov RETURN_REG,ARG0 /* No-op on 32-bit */ /* save retainstack */
add $STACK_PADDING,STACK_REG mov RS_REG,24(ARG2)
jmp *QUOT_XT_OFFSET(ARG0) /* Call the quotation */ /* save callstack */
lea -8(%rsp),%rbp
mov %rbp,(ARG2)
/* compile quotation */
sub $8,%rsp
call MANGLE(lazy_jit_compile)
add $8,%rsp
/* call quotation */
jmp *QUOT_XT_OFFSET(RETURN_REG)
DEF(long long,read_timestamp_counter,(void)): DEF(long long,read_timestamp_counter,(void)):
mov $0,%rax mov $0,%rax

View File

@ -3,8 +3,4 @@ namespace factor
#define FACTOR_CPU_STRING "x86.64" #define FACTOR_CPU_STRING "x86.64"
register cell ds asm("r14");
register cell rs asm("r15");
#define VM_ASM_API VM_C_API
} }

View File

@ -1,35 +1,3 @@
DEF(F_FASTCALL void,c_to_factor,(CELL quot, void *vm)):
PUSH_NONVOLATILE
mov ARG0,NV0
mov ARG1,NV1
/* Save old stack pointer and align */
mov STACK_REG,ARG0
and $-16,STACK_REG
add $CELL_SIZE,STACK_REG
push ARG0
/* Create register shadow area for Win64 */
sub $32,STACK_REG
/* Save stack pointer */
lea -CELL_SIZE(STACK_REG),ARG0
call MANGLE(save_callstack_bottom)
/* Call quot-xt */
mov NV0,ARG0
mov NV1,ARG1
call *QUOT_XT_OFFSET(ARG0)
/* Tear down register shadow area */
add $32,STACK_REG
/* Undo stack alignment */
mov (STACK_REG),STACK_REG
POP_NONVOLATILE
ret
/* cpu.x86.features calls this */ /* cpu.x86.features calls this */
DEF(bool,sse_version,(void)): DEF(bool,sse_version,(void)):
mov $0x1,RETURN_REG mov $0x1,RETURN_REG

View File

@ -74,11 +74,13 @@ inline static unsigned int fpu_status(unsigned int status)
} }
/* Defined in assembly */ /* Defined in assembly */
VM_ASM_API void c_to_factor(cell quot, void *vm); VM_C_API void c_to_factor(cell quot, void *vm);
VM_ASM_API void throw_impl(cell quot, stack_frame *rewind_to, void *vm); VM_C_API void throw_impl(cell quot, void *new_stack, void *vm);
VM_ASM_API void lazy_jit_compile(cell quot, void *vm); VM_C_API void lazy_jit_compile_impl(cell quot, void *vm);
VM_C_API void set_callstack(stack_frame *to, VM_C_API void set_callstack(
void *vm,
stack_frame *to,
stack_frame *from, stack_frame *from,
cell length, cell length,
void *(*memcpy)(void*,const void*, size_t)); void *(*memcpy)(void*,const void*, size_t));

View File

@ -230,7 +230,7 @@ data_heap_room factor_vm::data_room()
void factor_vm::primitive_data_room() void factor_vm::primitive_data_room()
{ {
data_heap_room room = data_room(); data_heap_room room = data_room();
dpush(tag<byte_array>(byte_array_from_value(&room))); ctx->push(tag<byte_array>(byte_array_from_value(&room)));
} }
struct object_accumulator { struct object_accumulator {
@ -265,7 +265,7 @@ cell factor_vm::instances(cell type)
void factor_vm::primitive_all_instances() void factor_vm::primitive_all_instances()
{ {
primitive_full_gc(); primitive_full_gc();
dpush(instances(TYPE_COUNT)); ctx->push(instances(TYPE_COUNT));
} }
} }

View File

@ -42,16 +42,16 @@ struct slot_checker {
char slot_card_value = *(char *)slot_card_pointer; char slot_card_value = *(char *)slot_card_pointer;
if((slot_card_value & mask) != mask) if((slot_card_value & mask) != mask)
{ {
printf("card not marked\n"); std::cout << "card not marked" << std::endl;
printf("source generation: %d\n",gen); std::cout << "source generation: " << gen << std::endl;
printf("target generation: %d\n",target); std::cout << "target generation: " << target << std::endl;
printf("object: 0x%lx\n",(cell)obj); std::cout << "object: 0x" << std::hex << (cell)obj << std::dec << std::endl;
printf("object type: %ld\n",obj->type()); std::cout << "object type: " << obj->type() << std::endl;
printf("slot pointer: 0x%lx\n",(cell)slot_ptr); std::cout << "slot pointer: 0x" << std::hex << (cell)slot_ptr << std::dec << std::endl;
printf("slot value: 0x%lx\n",*slot_ptr); std::cout << "slot value: 0x" << std::hex << *slot_ptr << std::dec << std::endl;
printf("card of object: 0x%lx\n",object_card_pointer); std::cout << "card of object: 0x" << std::hex << object_card_pointer << std::dec << std::endl;
printf("card of slot: 0x%lx\n",slot_card_pointer); std::cout << "card of slot: 0x" << std::hex << slot_card_pointer << std::dec << std::endl;
printf("\n"); std::cout << std::endl;
parent->factorbug(); parent->factorbug();
} }
} }

View File

@ -145,13 +145,13 @@ void factor_vm::print_objects(cell *start, cell *end)
void factor_vm::print_datastack() void factor_vm::print_datastack()
{ {
std::cout << "==== DATA STACK:\n"; std::cout << "==== DATA STACK:\n";
print_objects((cell *)ds_bot,(cell *)ds); print_objects((cell *)ctx->datastack_region->start,(cell *)ctx->datastack);
} }
void factor_vm::print_retainstack() void factor_vm::print_retainstack()
{ {
std::cout << "==== RETAIN STACK:\n"; std::cout << "==== RETAIN STACK:\n";
print_objects((cell *)rs_bot,(cell *)rs); print_objects((cell *)ctx->retainstack_region->start,(cell *)ctx->retainstack);
} }
struct stack_frame_printer { struct stack_frame_printer {
@ -421,9 +421,9 @@ void factor_vm::factorbug()
else if(strcmp(cmd,"t") == 0) else if(strcmp(cmd,"t") == 0)
full_output = !full_output; full_output = !full_output;
else if(strcmp(cmd,"s") == 0) else if(strcmp(cmd,"s") == 0)
dump_memory(ds_bot,ds); dump_memory(ctx->datastack_region->start,ctx->datastack);
else if(strcmp(cmd,"r") == 0) else if(strcmp(cmd,"r") == 0)
dump_memory(rs_bot,rs); dump_memory(ctx->retainstack_region->start,ctx->retainstack);
else if(strcmp(cmd,".s") == 0) else if(strcmp(cmd,".s") == 0)
print_datastack(); print_datastack();
else if(strcmp(cmd,".r") == 0) else if(strcmp(cmd,".r") == 0)
@ -459,7 +459,7 @@ void factor_vm::factorbug()
else if(strcmp(cmd,"push") == 0) else if(strcmp(cmd,"push") == 0)
{ {
cell addr = read_cell_hex(); cell addr = read_cell_hex();
dpush(addr); ctx->push(addr);
} }
else if(strcmp(cmd,"code") == 0) else if(strcmp(cmd,"code") == 0)
dump_code_heap(); dump_code_heap();

View File

@ -88,9 +88,9 @@ cell factor_vm::lookup_method(cell obj, cell methods)
void factor_vm::primitive_lookup_method() void factor_vm::primitive_lookup_method()
{ {
cell methods = dpop(); cell methods = ctx->pop();
cell obj = dpop(); cell obj = ctx->pop();
dpush(lookup_method(obj,methods)); ctx->push(lookup_method(obj,methods));
} }
cell factor_vm::object_class(cell obj) cell factor_vm::object_class(cell obj)
@ -120,17 +120,17 @@ void factor_vm::primitive_mega_cache_miss()
{ {
dispatch_stats.megamorphic_cache_misses++; dispatch_stats.megamorphic_cache_misses++;
cell cache = dpop(); cell cache = ctx->pop();
fixnum index = untag_fixnum(dpop()); fixnum index = untag_fixnum(ctx->pop());
cell methods = dpop(); cell methods = ctx->pop();
cell object = ((cell *)ds)[-index]; cell object = ((cell *)ctx->datastack)[-index];
cell klass = object_class(object); cell klass = object_class(object);
cell method = lookup_method(object,methods); cell method = lookup_method(object,methods);
update_method_cache(cache,klass,method); update_method_cache(cache,klass,method);
dpush(method); ctx->push(method);
} }
void factor_vm::primitive_reset_dispatch_stats() void factor_vm::primitive_reset_dispatch_stats()
@ -140,7 +140,7 @@ void factor_vm::primitive_reset_dispatch_stats()
void factor_vm::primitive_dispatch_stats() void factor_vm::primitive_dispatch_stats()
{ {
dpush(tag<byte_array>(byte_array_from_value(&dispatch_stats))); ctx->push(tag<byte_array>(byte_array_from_value(&dispatch_stats)));
} }
void quotation_jit::emit_mega_cache_lookup(cell methods_, fixnum index, cell cache_) void quotation_jit::emit_mega_cache_lookup(cell methods_, fixnum index, cell cache_)

View File

@ -43,9 +43,9 @@ void factor_vm::throw_error(cell error, stack_frame *callstack_top)
/* If we had an underflow or overflow, stack pointers might be /* If we had an underflow or overflow, stack pointers might be
out of bounds */ out of bounds */
fix_stacks(); ctx->fix_stacks();
dpush(error); ctx->push(error);
/* Errors thrown from C code pass NULL for this parameter. /* Errors thrown from C code pass NULL for this parameter.
Errors thrown from Factor code, or signal handlers, pass the Errors thrown from Factor code, or signal handlers, pass the
@ -99,13 +99,13 @@ bool factor_vm::in_page(cell fault, cell area, cell area_size, int offset)
void factor_vm::memory_protection_error(cell addr, stack_frame *native_stack) void factor_vm::memory_protection_error(cell addr, stack_frame *native_stack)
{ {
if(in_page(addr, ds_bot, 0, -1)) if(in_page(addr, ctx->datastack_region->start, 0, -1))
general_error(ERROR_DS_UNDERFLOW,false_object,false_object,native_stack); general_error(ERROR_DS_UNDERFLOW,false_object,false_object,native_stack);
else if(in_page(addr, ds_bot, ds_size, 0)) else if(in_page(addr, ctx->datastack_region->start, ds_size, 0))
general_error(ERROR_DS_OVERFLOW,false_object,false_object,native_stack); general_error(ERROR_DS_OVERFLOW,false_object,false_object,native_stack);
else if(in_page(addr, rs_bot, 0, -1)) else if(in_page(addr, ctx->retainstack_region->start, 0, -1))
general_error(ERROR_RS_UNDERFLOW,false_object,false_object,native_stack); general_error(ERROR_RS_UNDERFLOW,false_object,false_object,native_stack);
else if(in_page(addr, rs_bot, rs_size, 0)) else if(in_page(addr, ctx->retainstack_region->start, rs_size, 0))
general_error(ERROR_RS_OVERFLOW,false_object,false_object,native_stack); general_error(ERROR_RS_OVERFLOW,false_object,false_object,native_stack);
else if(in_page(addr, nursery.end, 0, 0)) else if(in_page(addr, nursery.end, 0, 0))
critical_error("allot_object() missed GC check",0); critical_error("allot_object() missed GC check",0);
@ -130,7 +130,7 @@ void factor_vm::fp_trap_error(unsigned int fpu_status, stack_frame *signal_calls
void factor_vm::primitive_call_clear() void factor_vm::primitive_call_clear()
{ {
throw_impl(dpop(),ctx->callstack_bottom,this); throw_impl(ctx->pop(),ctx->callstack_bottom,this);
} }
/* For testing purposes */ /* For testing purposes */

View File

@ -152,11 +152,9 @@ void factor_vm::init_factor(vm_parameters *p)
void factor_vm::pass_args_to_factor(int argc, vm_char **argv) void factor_vm::pass_args_to_factor(int argc, vm_char **argv)
{ {
growable_array args(this); growable_array args(this);
int i;
for(i = 1; i < argc; i++){ for(fixnum i = 1; i < argc; i++)
args.add(allot_alien(false_object,(cell)argv[i])); args.add(allot_alien(false_object,(cell)argv[i]));
}
args.trim(); args.trim();
special_objects[OBJ_ARGS] = args.elements.value(); special_objects[OBJ_ARGS] = args.elements.value();

View File

@ -15,11 +15,18 @@ struct free_heap_block
cell size() const cell size() const
{ {
return header & ~7; cell size = header & ~7;
#ifdef FACTOR_DEBUG
assert(size > 0);
#endif
return size;
} }
void make_free(cell size) void make_free(cell size)
{ {
#ifdef FACTOR_DEBUG
assert(size > 0);
#endif
header = size | 1; header = size | 1;
} }
}; };

View File

@ -57,34 +57,6 @@ void factor_vm::update_code_roots_for_sweep()
} }
} }
/* After a compaction, invalidate any code heap roots which are not
marked as above, and also slide the valid roots up so that call sites
can be updated correctly. */
void factor_vm::update_code_roots_for_compaction()
{
std::vector<code_root *>::const_iterator iter = code_roots.begin();
std::vector<code_root *>::const_iterator end = code_roots.end();
mark_bits<code_block> *state = &code->allocator->state;
for(; iter < end; iter++)
{
code_root *root = *iter;
code_block *block = (code_block *)(root->value & -data_alignment);
/* Offset of return address within 16-byte allocation line */
cell offset = root->value - (cell)block;
if(root->valid && state->marked_p(block))
{
block = state->forward_block(block);
root->value = (cell)block + offset;
}
else
root->valid = false;
}
}
void factor_vm::collect_mark_impl(bool trace_contexts_p) void factor_vm::collect_mark_impl(bool trace_contexts_p)
{ {
full_collector collector(this); full_collector collector(this);

View File

@ -131,8 +131,6 @@ void factor_vm::gc(gc_op op, cell requested_bytes, bool trace_contexts_p)
assert(!gc_off); assert(!gc_off);
assert(!current_gc); assert(!current_gc);
save_stacks();
current_gc = new gc_state(op,this); current_gc = new gc_state(op,this);
/* Keep trying to GC higher and higher generations until we don't run out /* Keep trying to GC higher and higher generations until we don't run out
@ -277,12 +275,12 @@ void factor_vm::primitive_disable_gc_events()
} }
result.trim(); result.trim();
dpush(result.elements.value()); ctx->push(result.elements.value());
delete this->gc_events; delete this->gc_events;
} }
else else
dpush(false_object); ctx->push(false_object);
} }
} }

View File

@ -314,7 +314,7 @@ void factor_vm::primitive_save_image()
/* do a full GC to push everything into tenured space */ /* do a full GC to push everything into tenured space */
primitive_compact_gc(); primitive_compact_gc();
data_root<byte_array> path(dpop(),this); data_root<byte_array> path(ctx->pop(),this);
path.untag_check(this); path.untag_check(this);
save_image((vm_char *)(path.untagged() + 1)); save_image((vm_char *)(path.untagged() + 1));
} }
@ -324,7 +324,7 @@ void factor_vm::primitive_save_image_and_exit()
/* We unbox this before doing anything else. This is the only point /* We unbox this before doing anything else. This is the only point
where we might throw an error, so we have to throw an error here since where we might throw an error, so we have to throw an error here since
later steps destroy the current image. */ later steps destroy the current image. */
data_root<byte_array> path(dpop(),this); data_root<byte_array> path(ctx->pop(),this);
path.untag_check(this); path.untag_check(this);
/* strip out special_objects data which is set on startup anyway */ /* strip out special_objects data which is set on startup anyway */

View File

@ -198,11 +198,11 @@ void *factor_vm::inline_cache_miss(cell return_address_)
<< std::endl; << std::endl;
#endif #endif
data_root<array> cache_entries(dpop(),this); data_root<array> cache_entries(ctx->pop(),this);
fixnum index = untag_fixnum(dpop()); fixnum index = untag_fixnum(ctx->pop());
data_root<array> methods(dpop(),this); data_root<array> methods(ctx->pop(),this);
data_root<word> generic_word(dpop(),this); data_root<word> generic_word(ctx->pop(),this);
data_root<object> object(((cell *)ds)[-index],this); data_root<object> object(((cell *)ctx->datastack)[-index],this);
cell pic_size = inline_cache_size(cache_entries.value()); cell pic_size = inline_cache_size(cache_entries.value());

View File

@ -33,8 +33,8 @@ void factor_vm::io_error()
void factor_vm::primitive_fopen() void factor_vm::primitive_fopen()
{ {
data_root<byte_array> mode(dpop(),this); data_root<byte_array> mode(ctx->pop(),this);
data_root<byte_array> path(dpop(),this); data_root<byte_array> path(ctx->pop(),this);
mode.untag_check(this); mode.untag_check(this);
path.untag_check(this); path.untag_check(this);
@ -46,15 +46,20 @@ void factor_vm::primitive_fopen()
io_error(); io_error();
else else
{ {
box_alien(file); ctx->push(allot_alien(file));
break; break;
} }
} }
} }
FILE *factor_vm::pop_file_handle()
{
return (FILE *)alien_offset(ctx->pop());
}
void factor_vm::primitive_fgetc() void factor_vm::primitive_fgetc()
{ {
FILE *file = (FILE *)unbox_alien(); FILE *file = pop_file_handle();
for(;;) for(;;)
{ {
@ -63,7 +68,7 @@ void factor_vm::primitive_fgetc()
{ {
if(feof(file)) if(feof(file))
{ {
dpush(false_object); ctx->push(false_object);
break; break;
} }
else else
@ -71,7 +76,7 @@ void factor_vm::primitive_fgetc()
} }
else else
{ {
dpush(tag_fixnum(c)); ctx->push(tag_fixnum(c));
break; break;
} }
} }
@ -79,12 +84,12 @@ void factor_vm::primitive_fgetc()
void factor_vm::primitive_fread() void factor_vm::primitive_fread()
{ {
FILE *file = (FILE *)unbox_alien(); FILE *file = pop_file_handle();
fixnum size = unbox_array_size(); fixnum size = unbox_array_size();
if(size == 0) if(size == 0)
{ {
dpush(tag<string>(allot_string(0,0))); ctx->push(tag<string>(allot_string(0,0)));
return; return;
} }
@ -97,7 +102,7 @@ void factor_vm::primitive_fread()
{ {
if(feof(file)) if(feof(file))
{ {
dpush(false_object); ctx->push(false_object);
break; break;
} }
else else
@ -111,7 +116,7 @@ void factor_vm::primitive_fread()
memcpy(new_buf + 1, buf.untagged() + 1,c); memcpy(new_buf + 1, buf.untagged() + 1,c);
buf = new_buf; buf = new_buf;
} }
dpush(buf.value()); ctx->push(buf.value());
break; break;
} }
} }
@ -119,8 +124,8 @@ void factor_vm::primitive_fread()
void factor_vm::primitive_fputc() void factor_vm::primitive_fputc()
{ {
FILE *file = (FILE *)unbox_alien(); FILE *file = pop_file_handle();
fixnum ch = to_fixnum(dpop()); fixnum ch = to_fixnum(ctx->pop());
for(;;) for(;;)
{ {
@ -137,8 +142,8 @@ void factor_vm::primitive_fputc()
void factor_vm::primitive_fwrite() void factor_vm::primitive_fwrite()
{ {
FILE *file = (FILE *)unbox_alien(); FILE *file = pop_file_handle();
byte_array *text = untag_check<byte_array>(dpop()); byte_array *text = untag_check<byte_array>(ctx->pop());
cell length = array_capacity(text); cell length = array_capacity(text);
char *string = (char *)(text + 1); char *string = (char *)(text + 1);
@ -166,20 +171,20 @@ void factor_vm::primitive_fwrite()
void factor_vm::primitive_ftell() void factor_vm::primitive_ftell()
{ {
FILE *file = (FILE *)unbox_alien(); FILE *file = pop_file_handle();
off_t offset; off_t offset;
if((offset = FTELL(file)) == -1) if((offset = FTELL(file)) == -1)
io_error(); io_error();
box_signed_8(offset); ctx->push(from_signed_8(offset));
} }
void factor_vm::primitive_fseek() void factor_vm::primitive_fseek()
{ {
int whence = to_fixnum(dpop()); int whence = to_fixnum(ctx->pop());
FILE *file = (FILE *)unbox_alien(); FILE *file = pop_file_handle();
off_t offset = to_signed_8(dpop()); off_t offset = to_signed_8(ctx->pop());
switch(whence) switch(whence)
{ {
@ -202,7 +207,7 @@ void factor_vm::primitive_fseek()
void factor_vm::primitive_fflush() void factor_vm::primitive_fflush()
{ {
FILE *file = (FILE *)unbox_alien(); FILE *file = pop_file_handle();
for(;;) for(;;)
{ {
if(fflush(file) == EOF) if(fflush(file) == EOF)
@ -214,7 +219,7 @@ void factor_vm::primitive_fflush()
void factor_vm::primitive_fclose() void factor_vm::primitive_fclose()
{ {
FILE *file = (FILE *)unbox_alien(); FILE *file = pop_file_handle();
for(;;) for(;;)
{ {
if(fclose(file) == EOF) if(fclose(file) == EOF)

View File

@ -5,40 +5,40 @@ namespace factor
void factor_vm::primitive_bignum_to_fixnum() void factor_vm::primitive_bignum_to_fixnum()
{ {
drepl(tag_fixnum(bignum_to_fixnum(untag<bignum>(dpeek())))); ctx->replace(tag_fixnum(bignum_to_fixnum(untag<bignum>(ctx->peek()))));
} }
void factor_vm::primitive_float_to_fixnum() void factor_vm::primitive_float_to_fixnum()
{ {
drepl(tag_fixnum(float_to_fixnum(dpeek()))); ctx->replace(tag_fixnum(float_to_fixnum(ctx->peek())));
} }
/* Division can only overflow when we are dividing the most negative fixnum /* Division can only overflow when we are dividing the most negative fixnum
by -1. */ by -1. */
void factor_vm::primitive_fixnum_divint() void factor_vm::primitive_fixnum_divint()
{ {
fixnum y = untag_fixnum(dpop()); \ fixnum y = untag_fixnum(ctx->pop()); \
fixnum x = untag_fixnum(dpeek()); fixnum x = untag_fixnum(ctx->peek());
fixnum result = x / y; fixnum result = x / y;
if(result == -fixnum_min) if(result == -fixnum_min)
drepl(allot_integer(-fixnum_min)); ctx->replace(allot_integer(-fixnum_min));
else else
drepl(tag_fixnum(result)); ctx->replace(tag_fixnum(result));
} }
void factor_vm::primitive_fixnum_divmod() void factor_vm::primitive_fixnum_divmod()
{ {
cell y = ((cell *)ds)[0]; cell y = ((cell *)ctx->datastack)[0];
cell x = ((cell *)ds)[-1]; cell x = ((cell *)ctx->datastack)[-1];
if(y == tag_fixnum(-1) && x == tag_fixnum(fixnum_min)) if(y == tag_fixnum(-1) && x == tag_fixnum(fixnum_min))
{ {
((cell *)ds)[-1] = allot_integer(-fixnum_min); ((cell *)ctx->datastack)[-1] = allot_integer(-fixnum_min);
((cell *)ds)[0] = tag_fixnum(0); ((cell *)ctx->datastack)[0] = tag_fixnum(0);
} }
else else
{ {
((cell *)ds)[-1] = tag_fixnum(untag_fixnum(x) / untag_fixnum(y)); ((cell *)ctx->datastack)[-1] = tag_fixnum(untag_fixnum(x) / untag_fixnum(y));
((cell *)ds)[0] = (fixnum)x % (fixnum)y; ((cell *)ctx->datastack)[0] = (fixnum)x % (fixnum)y;
} }
} }
@ -63,15 +63,15 @@ inline fixnum factor_vm::branchless_abs(fixnum x)
void factor_vm::primitive_fixnum_shift() void factor_vm::primitive_fixnum_shift()
{ {
fixnum y = untag_fixnum(dpop()); fixnum y = untag_fixnum(ctx->pop());
fixnum x = untag_fixnum(dpeek()); fixnum x = untag_fixnum(ctx->peek());
if(x == 0) if(x == 0)
return; return;
else if(y < 0) else if(y < 0)
{ {
y = branchless_max(y,-WORD_SIZE + 1); y = branchless_max(y,-WORD_SIZE + 1);
drepl(tag_fixnum(x >> -y)); ctx->replace(tag_fixnum(x >> -y));
return; return;
} }
else if(y < WORD_SIZE - TAG_BITS) else if(y < WORD_SIZE - TAG_BITS)
@ -79,57 +79,57 @@ void factor_vm::primitive_fixnum_shift()
fixnum mask = -((fixnum)1 << (WORD_SIZE - 1 - TAG_BITS - y)); fixnum mask = -((fixnum)1 << (WORD_SIZE - 1 - TAG_BITS - y));
if(!(branchless_abs(x) & mask)) if(!(branchless_abs(x) & mask))
{ {
drepl(tag_fixnum(x << y)); ctx->replace(tag_fixnum(x << y));
return; return;
} }
} }
drepl(tag<bignum>(bignum_arithmetic_shift( ctx->replace(tag<bignum>(bignum_arithmetic_shift(
fixnum_to_bignum(x),y))); fixnum_to_bignum(x),y)));
} }
void factor_vm::primitive_fixnum_to_bignum() void factor_vm::primitive_fixnum_to_bignum()
{ {
drepl(tag<bignum>(fixnum_to_bignum(untag_fixnum(dpeek())))); ctx->replace(tag<bignum>(fixnum_to_bignum(untag_fixnum(ctx->peek()))));
} }
void factor_vm::primitive_float_to_bignum() void factor_vm::primitive_float_to_bignum()
{ {
drepl(tag<bignum>(float_to_bignum(dpeek()))); ctx->replace(tag<bignum>(float_to_bignum(ctx->peek())));
} }
#define POP_BIGNUMS(x,y) \ #define POP_BIGNUMS(x,y) \
bignum * y = untag<bignum>(dpop()); \ bignum * y = untag<bignum>(ctx->pop()); \
bignum * x = untag<bignum>(dpop()); bignum * x = untag<bignum>(ctx->pop());
void factor_vm::primitive_bignum_eq() void factor_vm::primitive_bignum_eq()
{ {
POP_BIGNUMS(x,y); POP_BIGNUMS(x,y);
box_boolean(bignum_equal_p(x,y)); ctx->push(tag_boolean(bignum_equal_p(x,y)));
} }
void factor_vm::primitive_bignum_add() void factor_vm::primitive_bignum_add()
{ {
POP_BIGNUMS(x,y); POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_add(x,y))); ctx->push(tag<bignum>(bignum_add(x,y)));
} }
void factor_vm::primitive_bignum_subtract() void factor_vm::primitive_bignum_subtract()
{ {
POP_BIGNUMS(x,y); POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_subtract(x,y))); ctx->push(tag<bignum>(bignum_subtract(x,y)));
} }
void factor_vm::primitive_bignum_multiply() void factor_vm::primitive_bignum_multiply()
{ {
POP_BIGNUMS(x,y); POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_multiply(x,y))); ctx->push(tag<bignum>(bignum_multiply(x,y)));
} }
void factor_vm::primitive_bignum_divint() void factor_vm::primitive_bignum_divint()
{ {
POP_BIGNUMS(x,y); POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_quotient(x,y))); ctx->push(tag<bignum>(bignum_quotient(x,y)));
} }
void factor_vm::primitive_bignum_divmod() void factor_vm::primitive_bignum_divmod()
@ -137,85 +137,85 @@ void factor_vm::primitive_bignum_divmod()
bignum *q, *r; bignum *q, *r;
POP_BIGNUMS(x,y); POP_BIGNUMS(x,y);
bignum_divide(x,y,&q,&r); bignum_divide(x,y,&q,&r);
dpush(tag<bignum>(q)); ctx->push(tag<bignum>(q));
dpush(tag<bignum>(r)); ctx->push(tag<bignum>(r));
} }
void factor_vm::primitive_bignum_mod() void factor_vm::primitive_bignum_mod()
{ {
POP_BIGNUMS(x,y); POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_remainder(x,y))); ctx->push(tag<bignum>(bignum_remainder(x,y)));
} }
void factor_vm::primitive_bignum_and() void factor_vm::primitive_bignum_and()
{ {
POP_BIGNUMS(x,y); POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_bitwise_and(x,y))); ctx->push(tag<bignum>(bignum_bitwise_and(x,y)));
} }
void factor_vm::primitive_bignum_or() void factor_vm::primitive_bignum_or()
{ {
POP_BIGNUMS(x,y); POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_bitwise_ior(x,y))); ctx->push(tag<bignum>(bignum_bitwise_ior(x,y)));
} }
void factor_vm::primitive_bignum_xor() void factor_vm::primitive_bignum_xor()
{ {
POP_BIGNUMS(x,y); POP_BIGNUMS(x,y);
dpush(tag<bignum>(bignum_bitwise_xor(x,y))); ctx->push(tag<bignum>(bignum_bitwise_xor(x,y)));
} }
void factor_vm::primitive_bignum_shift() void factor_vm::primitive_bignum_shift()
{ {
fixnum y = untag_fixnum(dpop()); fixnum y = untag_fixnum(ctx->pop());
bignum* x = untag<bignum>(dpop()); bignum* x = untag<bignum>(ctx->pop());
dpush(tag<bignum>(bignum_arithmetic_shift(x,y))); ctx->push(tag<bignum>(bignum_arithmetic_shift(x,y)));
} }
void factor_vm::primitive_bignum_less() void factor_vm::primitive_bignum_less()
{ {
POP_BIGNUMS(x,y); POP_BIGNUMS(x,y);
box_boolean(bignum_compare(x,y) == bignum_comparison_less); ctx->push(tag_boolean(bignum_compare(x,y) == bignum_comparison_less));
} }
void factor_vm::primitive_bignum_lesseq() void factor_vm::primitive_bignum_lesseq()
{ {
POP_BIGNUMS(x,y); POP_BIGNUMS(x,y);
box_boolean(bignum_compare(x,y) != bignum_comparison_greater); ctx->push(tag_boolean(bignum_compare(x,y) != bignum_comparison_greater));
} }
void factor_vm::primitive_bignum_greater() void factor_vm::primitive_bignum_greater()
{ {
POP_BIGNUMS(x,y); POP_BIGNUMS(x,y);
box_boolean(bignum_compare(x,y) == bignum_comparison_greater); ctx->push(tag_boolean(bignum_compare(x,y) == bignum_comparison_greater));
} }
void factor_vm::primitive_bignum_greatereq() void factor_vm::primitive_bignum_greatereq()
{ {
POP_BIGNUMS(x,y); POP_BIGNUMS(x,y);
box_boolean(bignum_compare(x,y) != bignum_comparison_less); ctx->push(tag_boolean(bignum_compare(x,y) != bignum_comparison_less));
} }
void factor_vm::primitive_bignum_not() void factor_vm::primitive_bignum_not()
{ {
drepl(tag<bignum>(bignum_bitwise_not(untag<bignum>(dpeek())))); ctx->replace(tag<bignum>(bignum_bitwise_not(untag<bignum>(ctx->peek()))));
} }
void factor_vm::primitive_bignum_bitp() void factor_vm::primitive_bignum_bitp()
{ {
fixnum bit = to_fixnum(dpop()); fixnum bit = to_fixnum(ctx->pop());
bignum *x = untag<bignum>(dpop()); bignum *x = untag<bignum>(ctx->pop());
box_boolean(bignum_logbitp(bit,x)); ctx->push(tag_boolean(bignum_logbitp(bit,x)));
} }
void factor_vm::primitive_bignum_log2() void factor_vm::primitive_bignum_log2()
{ {
drepl(tag<bignum>(bignum_integer_length(untag<bignum>(dpeek())))); ctx->replace(tag<bignum>(bignum_integer_length(untag<bignum>(ctx->peek()))));
} }
unsigned int factor_vm::bignum_producer(unsigned int digit) unsigned int factor_vm::bignum_producer(unsigned int digit)
{ {
unsigned char *ptr = (unsigned char *)alien_offset(dpeek()); unsigned char *ptr = (unsigned char *)alien_offset(ctx->peek());
return *(ptr + digit); return *(ptr + digit);
} }
@ -226,145 +226,146 @@ unsigned int bignum_producer(unsigned int digit, factor_vm *parent)
void factor_vm::primitive_byte_array_to_bignum() void factor_vm::primitive_byte_array_to_bignum()
{ {
cell n_digits = array_capacity(untag_check<byte_array>(dpeek())); cell n_digits = array_capacity(untag_check<byte_array>(ctx->peek()));
bignum * result = digit_stream_to_bignum(n_digits,factor::bignum_producer,0x100,0); bignum * result = digit_stream_to_bignum(n_digits,factor::bignum_producer,0x100,0);
drepl(tag<bignum>(result)); ctx->replace(tag<bignum>(result));
} }
cell factor_vm::unbox_array_size_slow() cell factor_vm::unbox_array_size_slow()
{ {
if(tagged<object>(dpeek()).type() == BIGNUM_TYPE) if(tagged<object>(ctx->peek()).type() == BIGNUM_TYPE)
{ {
bignum *zero = untag<bignum>(bignum_zero); bignum *zero = untag<bignum>(bignum_zero);
bignum *max = cell_to_bignum(array_size_max); bignum *max = cell_to_bignum(array_size_max);
bignum *n = untag<bignum>(dpeek()); bignum *n = untag<bignum>(ctx->peek());
if(bignum_compare(n,zero) != bignum_comparison_less if(bignum_compare(n,zero) != bignum_comparison_less
&& bignum_compare(n,max) == bignum_comparison_less) && bignum_compare(n,max) == bignum_comparison_less)
{ {
dpop(); ctx->pop();
return bignum_to_cell(n); return bignum_to_cell(n);
} }
} }
general_error(ERROR_ARRAY_SIZE,dpop(),tag_fixnum(array_size_max),NULL); general_error(ERROR_ARRAY_SIZE,ctx->pop(),tag_fixnum(array_size_max),NULL);
return 0; /* can't happen */ return 0; /* can't happen */
} }
void factor_vm::primitive_fixnum_to_float() void factor_vm::primitive_fixnum_to_float()
{ {
drepl(allot_float(fixnum_to_float(dpeek()))); ctx->replace(allot_float(fixnum_to_float(ctx->peek())));
} }
void factor_vm::primitive_bignum_to_float() void factor_vm::primitive_bignum_to_float()
{ {
drepl(allot_float(bignum_to_float(dpeek()))); ctx->replace(allot_float(bignum_to_float(ctx->peek())));
} }
void factor_vm::primitive_str_to_float() void factor_vm::primitive_str_to_float()
{ {
byte_array *bytes = untag_check<byte_array>(dpeek()); byte_array *bytes = untag_check<byte_array>(ctx->peek());
cell capacity = array_capacity(bytes); cell capacity = array_capacity(bytes);
char *c_str = (char *)(bytes + 1); char *c_str = (char *)(bytes + 1);
char *end = c_str; char *end = c_str;
double f = strtod(c_str,&end); double f = strtod(c_str,&end);
if(end == c_str + capacity - 1) if(end == c_str + capacity - 1)
drepl(allot_float(f)); ctx->replace(allot_float(f));
else else
drepl(false_object); ctx->replace(false_object);
} }
void factor_vm::primitive_float_to_str() void factor_vm::primitive_float_to_str()
{ {
byte_array *array = allot_byte_array(33); byte_array *array = allot_byte_array(33);
snprintf((char *)(array + 1),32,"%.16g",untag_float_check(dpop())); snprintf((char *)(array + 1),32,"%.16g",untag_float_check(ctx->pop()));
dpush(tag<byte_array>(array)); ctx->push(tag<byte_array>(array));
} }
#define POP_FLOATS(x,y) \ #define POP_FLOATS(x,y) \
double y = untag_float(dpop()); \ double y = untag_float(ctx->pop()); \
double x = untag_float(dpop()); double x = untag_float(ctx->pop());
void factor_vm::primitive_float_eq() void factor_vm::primitive_float_eq()
{ {
POP_FLOATS(x,y); POP_FLOATS(x,y);
box_boolean(x == y); ctx->push(tag_boolean(x == y));
} }
void factor_vm::primitive_float_add() void factor_vm::primitive_float_add()
{ {
POP_FLOATS(x,y); POP_FLOATS(x,y);
box_double(x + y); ctx->push(allot_float(x + y));
} }
void factor_vm::primitive_float_subtract() void factor_vm::primitive_float_subtract()
{ {
POP_FLOATS(x,y); POP_FLOATS(x,y);
box_double(x - y); ctx->push(allot_float(x - y));
} }
void factor_vm::primitive_float_multiply() void factor_vm::primitive_float_multiply()
{ {
POP_FLOATS(x,y); POP_FLOATS(x,y);
box_double(x * y); ctx->push(allot_float(x * y));
} }
void factor_vm::primitive_float_divfloat() void factor_vm::primitive_float_divfloat()
{ {
POP_FLOATS(x,y); POP_FLOATS(x,y);
box_double(x / y); ctx->push(allot_float(x / y));
} }
void factor_vm::primitive_float_mod() void factor_vm::primitive_float_mod()
{ {
POP_FLOATS(x,y); POP_FLOATS(x,y);
box_double(fmod(x,y)); ctx->push(allot_float(fmod(x,y)));
} }
void factor_vm::primitive_float_less() void factor_vm::primitive_float_less()
{ {
POP_FLOATS(x,y); POP_FLOATS(x,y);
box_boolean(x < y); ctx->push(tag_boolean(x < y));
} }
void factor_vm::primitive_float_lesseq() void factor_vm::primitive_float_lesseq()
{ {
POP_FLOATS(x,y); POP_FLOATS(x,y);
box_boolean(x <= y); ctx->push(tag_boolean(x <= y));
} }
void factor_vm::primitive_float_greater() void factor_vm::primitive_float_greater()
{ {
POP_FLOATS(x,y); POP_FLOATS(x,y);
box_boolean(x > y); ctx->push(tag_boolean(x > y));
} }
void factor_vm::primitive_float_greatereq() void factor_vm::primitive_float_greatereq()
{ {
POP_FLOATS(x,y); POP_FLOATS(x,y);
box_boolean(x >= y); ctx->push(tag_boolean(x >= y));
} }
void factor_vm::primitive_float_bits() void factor_vm::primitive_float_bits()
{ {
box_unsigned_4(float_bits(untag_float_check(dpop()))); ctx->push(from_unsigned_4(float_bits(untag_float_check(ctx->pop()))));
} }
void factor_vm::primitive_bits_float() void factor_vm::primitive_bits_float()
{ {
box_float(bits_float(to_cell(dpop()))); ctx->push(allot_float(bits_float(to_cell(ctx->pop()))));
} }
void factor_vm::primitive_double_bits() void factor_vm::primitive_double_bits()
{ {
box_unsigned_8(double_bits(untag_float_check(dpop()))); ctx->push(from_unsigned_8(double_bits(untag_float_check(ctx->pop()))));
} }
void factor_vm::primitive_bits_double() void factor_vm::primitive_bits_double()
{ {
box_double(bits_double(to_unsigned_8(dpop()))); ctx->push(allot_float(bits_double(to_unsigned_8(ctx->pop()))));
} }
/* Cannot allocate */
fixnum factor_vm::to_fixnum(cell tagged) fixnum factor_vm::to_fixnum(cell tagged)
{ {
switch(TAG(tagged)) switch(TAG(tagged))
@ -394,99 +395,100 @@ VM_C_API cell to_cell(cell tagged, factor_vm *parent)
return parent->to_cell(tagged); return parent->to_cell(tagged);
} }
void factor_vm::box_signed_1(s8 n) cell factor_vm::from_signed_1(s8 n)
{ {
dpush(tag_fixnum(n)); return tag_fixnum(n);
} }
VM_C_API void box_signed_1(s8 n, factor_vm *parent) VM_C_API cell from_signed_1(s8 n, factor_vm *parent)
{ {
return parent->box_signed_1(n); return parent->from_signed_1(n);
} }
void factor_vm::box_unsigned_1(u8 n) cell factor_vm::from_unsigned_1(u8 n)
{ {
dpush(tag_fixnum(n)); return tag_fixnum(n);
} }
VM_C_API void box_unsigned_1(u8 n, factor_vm *parent) VM_C_API cell from_unsigned_1(u8 n, factor_vm *parent)
{ {
return parent->box_unsigned_1(n); return parent->from_unsigned_1(n);
} }
void factor_vm::box_signed_2(s16 n) cell factor_vm::from_signed_2(s16 n)
{ {
dpush(tag_fixnum(n)); return tag_fixnum(n);
} }
VM_C_API void box_signed_2(s16 n, factor_vm *parent) VM_C_API cell from_signed_2(s16 n, factor_vm *parent)
{ {
return parent->box_signed_2(n); return parent->from_signed_2(n);
} }
void factor_vm::box_unsigned_2(u16 n) cell factor_vm::from_unsigned_2(u16 n)
{ {
dpush(tag_fixnum(n)); return tag_fixnum(n);
} }
VM_C_API void box_unsigned_2(u16 n, factor_vm *parent) VM_C_API cell from_unsigned_2(u16 n, factor_vm *parent)
{ {
return parent->box_unsigned_2(n); return parent->from_unsigned_2(n);
} }
void factor_vm::box_signed_4(s32 n) cell factor_vm::from_signed_4(s32 n)
{ {
dpush(allot_integer(n)); return allot_integer(n);
} }
VM_C_API void box_signed_4(s32 n, factor_vm *parent) VM_C_API cell from_signed_4(s32 n, factor_vm *parent)
{ {
return parent->box_signed_4(n); return parent->from_signed_4(n);
} }
void factor_vm::box_unsigned_4(u32 n) cell factor_vm::from_unsigned_4(u32 n)
{ {
dpush(allot_cell(n)); return allot_cell(n);
} }
VM_C_API void box_unsigned_4(u32 n, factor_vm *parent) VM_C_API cell from_unsigned_4(u32 n, factor_vm *parent)
{ {
return parent->box_unsigned_4(n); return parent->from_unsigned_4(n);
} }
void factor_vm::box_signed_cell(fixnum integer) cell factor_vm::from_signed_cell(fixnum integer)
{ {
dpush(allot_integer(integer)); return allot_integer(integer);
} }
VM_C_API void box_signed_cell(fixnum integer, factor_vm *parent) cell factor_vm::from_unsigned_cell(cell integer)
{ {
return parent->box_signed_cell(integer); return allot_cell(integer);
} }
void factor_vm::box_unsigned_cell(cell cell) VM_C_API cell from_signed_cell(fixnum integer, factor_vm *parent)
{ {
dpush(allot_cell(cell)); return parent->from_signed_cell(integer);
} }
VM_C_API void box_unsigned_cell(cell cell, factor_vm *parent) VM_C_API cell from_unsigned_cell(cell integer, factor_vm *parent)
{ {
return parent->box_unsigned_cell(cell); return parent->from_unsigned_cell(integer);
} }
void factor_vm::box_signed_8(s64 n) cell factor_vm::from_signed_8(s64 n)
{ {
if(n < fixnum_min || n > fixnum_max) if(n < fixnum_min || n > fixnum_max)
dpush(tag<bignum>(long_long_to_bignum(n))); return tag<bignum>(long_long_to_bignum(n));
else else
dpush(tag_fixnum(n)); return tag_fixnum(n);
} }
VM_C_API void box_signed_8(s64 n, factor_vm *parent) VM_C_API cell from_signed_8(s64 n, factor_vm *parent)
{ {
return parent->box_signed_8(n); return parent->from_signed_8(n);
} }
/* Cannot allocate */
s64 factor_vm::to_signed_8(cell obj) s64 factor_vm::to_signed_8(cell obj)
{ {
switch(tagged<object>(obj).type()) switch(tagged<object>(obj).type())
@ -506,19 +508,20 @@ VM_C_API s64 to_signed_8(cell obj, factor_vm *parent)
return parent->to_signed_8(obj); return parent->to_signed_8(obj);
} }
void factor_vm::box_unsigned_8(u64 n) cell factor_vm::from_unsigned_8(u64 n)
{ {
if(n > (u64)fixnum_max) if(n > (u64)fixnum_max)
dpush(tag<bignum>(ulong_long_to_bignum(n))); return tag<bignum>(ulong_long_to_bignum(n));
else else
dpush(tag_fixnum(n)); return tag_fixnum(n);
} }
VM_C_API void box_unsigned_8(u64 n, factor_vm *parent) VM_C_API cell from_unsigned_8(u64 n, factor_vm *parent)
{ {
return parent->box_unsigned_8(n); return parent->from_unsigned_8(n);
} }
/* Cannot allocate */
u64 factor_vm::to_unsigned_8(cell obj) u64 factor_vm::to_unsigned_8(cell obj)
{ {
switch(tagged<object>(obj).type()) switch(tagged<object>(obj).type())
@ -538,16 +541,12 @@ VM_C_API u64 to_unsigned_8(cell obj, factor_vm *parent)
return parent->to_unsigned_8(obj); return parent->to_unsigned_8(obj);
} }
void factor_vm::box_float(float flo) VM_C_API cell from_float(float flo, factor_vm *parent)
{ {
dpush(allot_float(flo)); return parent->allot_float(flo);
}
VM_C_API void box_float(float flo, factor_vm *parent)
{
return parent->box_float(flo);
} }
/* Cannot allocate */
float factor_vm::to_float(cell value) float factor_vm::to_float(cell value)
{ {
return untag_float_check(value); return untag_float_check(value);
@ -558,16 +557,12 @@ VM_C_API float to_float(cell value, factor_vm *parent)
return parent->to_float(value); return parent->to_float(value);
} }
void factor_vm::box_double(double flo) VM_C_API cell from_double(double flo, factor_vm *parent)
{ {
dpush(allot_float(flo)); return parent->allot_float(flo);
}
VM_C_API void box_double(double flo, factor_vm *parent)
{
return parent->box_double(flo);
} }
/* Cannot allocate */
double factor_vm::to_double(cell value) double factor_vm::to_double(cell value)
{ {
return untag_float_check(value); return untag_float_check(value);
@ -582,22 +577,22 @@ VM_C_API double to_double(cell value, factor_vm *parent)
overflow, they call these functions. */ overflow, they call these functions. */
inline void factor_vm::overflow_fixnum_add(fixnum x, fixnum y) inline void factor_vm::overflow_fixnum_add(fixnum x, fixnum y)
{ {
drepl(tag<bignum>(fixnum_to_bignum( ctx->replace(tag<bignum>(fixnum_to_bignum(
untag_fixnum(x) + untag_fixnum(y)))); untag_fixnum(x) + untag_fixnum(y))));
} }
VM_ASM_API void overflow_fixnum_add(fixnum x, fixnum y, factor_vm *parent) VM_C_API void overflow_fixnum_add(fixnum x, fixnum y, factor_vm *parent)
{ {
parent->overflow_fixnum_add(x,y); parent->overflow_fixnum_add(x,y);
} }
inline void factor_vm::overflow_fixnum_subtract(fixnum x, fixnum y) inline void factor_vm::overflow_fixnum_subtract(fixnum x, fixnum y)
{ {
drepl(tag<bignum>(fixnum_to_bignum( ctx->replace(tag<bignum>(fixnum_to_bignum(
untag_fixnum(x) - untag_fixnum(y)))); untag_fixnum(x) - untag_fixnum(y))));
} }
VM_ASM_API void overflow_fixnum_subtract(fixnum x, fixnum y, factor_vm *parent) VM_C_API void overflow_fixnum_subtract(fixnum x, fixnum y, factor_vm *parent)
{ {
parent->overflow_fixnum_subtract(x,y); parent->overflow_fixnum_subtract(x,y);
} }
@ -608,10 +603,10 @@ inline void factor_vm::overflow_fixnum_multiply(fixnum x, fixnum y)
GC_BIGNUM(bx); GC_BIGNUM(bx);
bignum *by = fixnum_to_bignum(y); bignum *by = fixnum_to_bignum(y);
GC_BIGNUM(by); GC_BIGNUM(by);
drepl(tag<bignum>(bignum_multiply(bx,by))); ctx->replace(tag<bignum>(bignum_multiply(bx,by)));
} }
VM_ASM_API void overflow_fixnum_multiply(fixnum x, fixnum y, factor_vm *parent) VM_C_API void overflow_fixnum_multiply(fixnum x, fixnum y, factor_vm *parent)
{ {
parent->overflow_fixnum_multiply(x,y); parent->overflow_fixnum_multiply(x,y);
} }

View File

@ -60,13 +60,13 @@ inline double factor_vm::fixnum_to_float(cell tagged)
inline cell factor_vm::unbox_array_size() inline cell factor_vm::unbox_array_size()
{ {
cell obj = dpeek(); cell obj = ctx->peek();
if(TAG(obj) == FIXNUM_TYPE) if(TAG(obj) == FIXNUM_TYPE)
{ {
fixnum n = untag_fixnum(obj); fixnum n = untag_fixnum(obj);
if(n >= 0 && n < (fixnum)array_size_max) if(n >= 0 && n < (fixnum)array_size_max)
{ {
dpop(); ctx->pop();
return n; return n;
} }
} }
@ -74,21 +74,21 @@ inline cell factor_vm::unbox_array_size()
return unbox_array_size_slow(); return unbox_array_size_slow();
} }
VM_C_API void box_float(float flo, factor_vm *vm); VM_C_API cell from_float(float flo, factor_vm *vm);
VM_C_API float to_float(cell value, factor_vm *vm); VM_C_API float to_float(cell value, factor_vm *vm);
VM_C_API void box_double(double flo, factor_vm *vm); VM_C_API cell from_double(double flo, factor_vm *vm);
VM_C_API double to_double(cell value, factor_vm *vm); VM_C_API double to_double(cell value, factor_vm *vm);
VM_C_API void box_signed_1(s8 n, factor_vm *vm); VM_C_API cell from_signed_1(s8 n, factor_vm *vm);
VM_C_API void box_unsigned_1(u8 n, factor_vm *vm); VM_C_API cell from_unsigned_1(u8 n, factor_vm *vm);
VM_C_API void box_signed_2(s16 n, factor_vm *vm); VM_C_API cell from_signed_2(s16 n, factor_vm *vm);
VM_C_API void box_unsigned_2(u16 n, factor_vm *vm); VM_C_API cell from_unsigned_2(u16 n, factor_vm *vm);
VM_C_API void box_signed_4(s32 n, factor_vm *vm); VM_C_API cell from_signed_4(s32 n, factor_vm *vm);
VM_C_API void box_unsigned_4(u32 n, factor_vm *vm); VM_C_API cell from_unsigned_4(u32 n, factor_vm *vm);
VM_C_API void box_signed_cell(fixnum integer, factor_vm *vm); VM_C_API cell from_signed_cell(fixnum integer, factor_vm *vm);
VM_C_API void box_unsigned_cell(cell cell, factor_vm *vm); VM_C_API cell from_unsigned_cell(cell integer, factor_vm *vm);
VM_C_API void box_signed_8(s64 n, factor_vm *vm); VM_C_API cell from_signed_8(s64 n, factor_vm *vm);
VM_C_API void box_unsigned_8(u64 n, factor_vm *vm); VM_C_API cell from_unsigned_8(u64 n, factor_vm *vm);
VM_C_API s64 to_signed_8(cell obj, factor_vm *vm); VM_C_API s64 to_signed_8(cell obj, factor_vm *vm);
VM_C_API u64 to_unsigned_8(cell obj, factor_vm *vm); VM_C_API u64 to_unsigned_8(cell obj, factor_vm *vm);
@ -96,8 +96,8 @@ VM_C_API u64 to_unsigned_8(cell obj, factor_vm *vm);
VM_C_API fixnum to_fixnum(cell tagged, factor_vm *vm); VM_C_API fixnum to_fixnum(cell tagged, factor_vm *vm);
VM_C_API cell to_cell(cell tagged, factor_vm *vm); VM_C_API cell to_cell(cell tagged, factor_vm *vm);
VM_ASM_API void overflow_fixnum_add(fixnum x, fixnum y, factor_vm *vm); VM_C_API void overflow_fixnum_add(fixnum x, fixnum y, factor_vm *parent);
VM_ASM_API void overflow_fixnum_subtract(fixnum x, fixnum y, factor_vm *vm); VM_C_API void overflow_fixnum_subtract(fixnum x, fixnum y, factor_vm *parent);
VM_ASM_API void overflow_fixnum_multiply(fixnum x, fixnum y, factor_vm *vm); VM_C_API void overflow_fixnum_multiply(fixnum x, fixnum y, factor_vm *parent);
} }

View File

@ -5,22 +5,22 @@ namespace factor
void factor_vm::primitive_special_object() void factor_vm::primitive_special_object()
{ {
fixnum e = untag_fixnum(dpeek()); fixnum e = untag_fixnum(ctx->peek());
drepl(special_objects[e]); ctx->replace(special_objects[e]);
} }
void factor_vm::primitive_set_special_object() void factor_vm::primitive_set_special_object()
{ {
fixnum e = untag_fixnum(dpop()); fixnum e = untag_fixnum(ctx->pop());
cell value = dpop(); cell value = ctx->pop();
special_objects[e] = value; special_objects[e] = value;
} }
void factor_vm::primitive_identity_hashcode() void factor_vm::primitive_identity_hashcode()
{ {
cell tagged = dpeek(); cell tagged = ctx->peek();
object *obj = untag<object>(tagged); object *obj = untag<object>(tagged);
drepl(tag_fixnum(obj->hashcode())); ctx->replace(tag_fixnum(obj->hashcode()));
} }
void factor_vm::compute_identity_hashcode(object *obj) void factor_vm::compute_identity_hashcode(object *obj)
@ -32,15 +32,15 @@ void factor_vm::compute_identity_hashcode(object *obj)
void factor_vm::primitive_compute_identity_hashcode() void factor_vm::primitive_compute_identity_hashcode()
{ {
object *obj = untag<object>(dpop()); object *obj = untag<object>(ctx->pop());
compute_identity_hashcode(obj); compute_identity_hashcode(obj);
} }
void factor_vm::primitive_set_slot() void factor_vm::primitive_set_slot()
{ {
fixnum slot = untag_fixnum(dpop()); fixnum slot = untag_fixnum(ctx->pop());
object *obj = untag<object>(dpop()); object *obj = untag<object>(ctx->pop());
cell value = dpop(); cell value = ctx->pop();
cell *slot_ptr = &obj->slots()[slot]; cell *slot_ptr = &obj->slots()[slot];
*slot_ptr = value; *slot_ptr = value;
@ -65,7 +65,7 @@ cell factor_vm::clone_object(cell obj_)
void factor_vm::primitive_clone() void factor_vm::primitive_clone()
{ {
drepl(clone_object(dpeek())); ctx->replace(clone_object(ctx->peek()));
} }
/* Size of the object pointed to by a tagged pointer */ /* Size of the object pointed to by a tagged pointer */
@ -79,7 +79,7 @@ cell factor_vm::object_size(cell tagged)
void factor_vm::primitive_size() void factor_vm::primitive_size()
{ {
box_unsigned_cell(object_size(dpop())); ctx->push(allot_cell(object_size(ctx->pop())));
} }
struct slot_become_visitor { struct slot_become_visitor {
@ -114,8 +114,8 @@ struct object_become_visitor {
to coalesce equal but distinct quotations and wrappers. */ to coalesce equal but distinct quotations and wrappers. */
void factor_vm::primitive_become() void factor_vm::primitive_become()
{ {
array *new_objects = untag_check<array>(dpop()); array *new_objects = untag_check<array>(ctx->pop());
array *old_objects = untag_check<array>(dpop()); array *old_objects = untag_check<array>(ctx->pop());
cell capacity = array_capacity(new_objects); cell capacity = array_capacity(new_objects);
if(capacity != array_capacity(old_objects)) if(capacity != array_capacity(old_objects))

View File

@ -14,12 +14,12 @@ NS_DURING
c_to_factor(quot,this); c_to_factor(quot,this);
NS_VOIDRETURN; NS_VOIDRETURN;
NS_HANDLER NS_HANDLER
dpush(allot_alien(false_object,(cell)localException)); ctx->push(allot_alien(false_object,(cell)localException));
quot = special_objects[OBJ_COCOA_EXCEPTION]; quot = special_objects[OBJ_COCOA_EXCEPTION];
if(!tagged<object>(quot).type_p(QUOTATION_TYPE)) if(!tagged<object>(quot).type_p(QUOTATION_TYPE))
{ {
/* No Cocoa exception handler was registered, so /* No Cocoa exception handler was registered, so
extra/cocoa/ is not loaded. So we pass the exception basis/cocoa/ is not loaded. So we pass the exception
along. */ along. */
[localException raise]; [localException raise];
} }

View File

@ -92,8 +92,8 @@ void factor_vm::ffi_dlclose(dll *dll)
void factor_vm::primitive_existsp() void factor_vm::primitive_existsp()
{ {
struct stat sb; struct stat sb;
char *path = (char *)(untag_check<byte_array>(dpop()) + 1); char *path = (char *)(untag_check<byte_array>(ctx->pop()) + 1);
box_boolean(stat(path,&sb) >= 0); ctx->push(tag_boolean(stat(path,&sb) >= 0));
} }
segment::segment(cell size_, bool executable_p) segment::segment(cell size_, bool executable_p)

View File

@ -92,8 +92,8 @@ const vm_char *factor_vm::vm_executable_path()
void factor_vm::primitive_existsp() void factor_vm::primitive_existsp()
{ {
vm_char *path = untag_check<byte_array>(dpop())->data<vm_char>(); vm_char *path = untag_check<byte_array>(ctx->pop())->data<vm_char>();
box_boolean(windows_stat(path)); ctx->push(tag_boolean(windows_stat(path)));
} }
segment::segment(cell size_, bool executable_p) segment::segment(cell size_, bool executable_p)

View File

@ -1,29 +1,14 @@
namespace factor namespace factor
{ {
#if defined(FACTOR_X86) extern "C" typedef void (*primitive_type)(factor_vm *parent);
extern "C" __attribute__ ((regparm (1))) typedef void (*primitive_type)(factor_vm *parent); #define PRIMITIVE(name) extern "C" void primitive_##name(factor_vm *parent)
#define PRIMITIVE(name) extern "C" __attribute__ ((regparm (1))) void primitive_##name(factor_vm *parent) #define PRIMITIVE_FORWARD(name) extern "C" void primitive_##name(factor_vm *parent) \
#define PRIMITIVE_FORWARD(name) extern "C" __attribute__ ((regparm (1))) void primitive_##name(factor_vm *parent) \ { \
{ \
parent->primitive_##name(); \ parent->primitive_##name(); \
} }
#else
extern "C" typedef void (*primitive_type)(factor_vm *parent);
#define PRIMITIVE(name) extern "C" void primitive_##name(factor_vm *parent)
#define PRIMITIVE_FORWARD(name) extern "C" void primitive_##name(factor_vm *parent) \
{ \
parent->primitive_##name(); \
}
#endif
extern const primitive_type primitives[];
/* These are defined in assembly */ extern const primitive_type primitives[];
PRIMITIVE(fixnum_add);
PRIMITIVE(fixnum_subtract);
PRIMITIVE(fixnum_multiply);
PRIMITIVE(inline_cache_miss);
PRIMITIVE(inline_cache_miss_tail);
/* These are generated with macros in alien.c */ /* These are generated with macros in alien.c */
PRIMITIVE(alien_signed_cell); PRIMITIVE(alien_signed_cell);

View File

@ -60,7 +60,7 @@ void factor_vm::set_profiling(bool profiling)
void factor_vm::primitive_profiling() void factor_vm::primitive_profiling()
{ {
set_profiling(to_boolean(dpop())); set_profiling(to_boolean(ctx->pop()));
} }
} }

View File

@ -297,25 +297,25 @@ void factor_vm::jit_compile_quot(cell quot_, bool relocating)
void factor_vm::primitive_jit_compile() void factor_vm::primitive_jit_compile()
{ {
jit_compile_quot(dpop(),true); jit_compile_quot(ctx->pop(),true);
} }
/* push a new quotation on the stack */ /* push a new quotation on the stack */
void factor_vm::primitive_array_to_quotation() void factor_vm::primitive_array_to_quotation()
{ {
quotation *quot = allot<quotation>(sizeof(quotation)); quotation *quot = allot<quotation>(sizeof(quotation));
quot->array = dpeek(); quot->array = ctx->peek();
quot->cached_effect = false_object; quot->cached_effect = false_object;
quot->cache_counter = false_object; quot->cache_counter = false_object;
quot->xt = (void *)lazy_jit_compile; quot->xt = (void *)lazy_jit_compile_impl;
quot->code = NULL; quot->code = NULL;
drepl(tag<quotation>(quot)); ctx->replace(tag<quotation>(quot));
} }
void factor_vm::primitive_quotation_xt() void factor_vm::primitive_quotation_xt()
{ {
quotation *quot = untag_check<quotation>(dpeek()); quotation *quot = untag_check<quotation>(ctx->peek());
drepl(allot_cell((cell)quot->xt)); ctx->replace(allot_cell((cell)quot->xt));
} }
/* Allocates memory */ /* Allocates memory */
@ -332,24 +332,23 @@ fixnum factor_vm::quot_code_offset_to_scan(cell quot_, cell offset)
return compiler.get_position(); return compiler.get_position();
} }
cell factor_vm::lazy_jit_compile_impl(cell quot_, stack_frame *stack) cell factor_vm::lazy_jit_compile(cell quot_)
{ {
data_root<quotation> quot(quot_,this); data_root<quotation> quot(quot_,this);
ctx->callstack_top = stack;
jit_compile_quot(quot.value(),true); jit_compile_quot(quot.value(),true);
return quot.value(); return quot.value();
} }
VM_ASM_API cell lazy_jit_compile_impl(cell quot_, stack_frame *stack, factor_vm *parent) VM_C_API cell lazy_jit_compile(cell quot, factor_vm *parent)
{ {
return parent->lazy_jit_compile_impl(quot_,stack); return parent->lazy_jit_compile(quot);
} }
void factor_vm::primitive_quot_compiled_p() void factor_vm::primitive_quot_compiled_p()
{ {
tagged<quotation> quot(dpop()); tagged<quotation> quot(ctx->pop());
quot.untag_check(this); quot.untag_check(this);
dpush(tag_boolean(quot->code != NULL)); ctx->push(tag_boolean(quot->code != NULL));
} }
} }

View File

@ -27,6 +27,6 @@ struct quotation_jit : public jit {
void iterate_quotation(); void iterate_quotation();
}; };
VM_ASM_API cell lazy_jit_compile_impl(cell quot, stack_frame *stack, factor_vm *parent); VM_C_API cell lazy_jit_compile(cell quot, factor_vm *parent);
} }

View File

@ -5,12 +5,12 @@ namespace factor
void factor_vm::primitive_exit() void factor_vm::primitive_exit()
{ {
exit(to_fixnum(dpop())); exit(to_fixnum(ctx->pop()));
} }
void factor_vm::primitive_system_micros() void factor_vm::primitive_system_micros()
{ {
box_unsigned_8(system_micros()); ctx->push(from_unsigned_8(system_micros()));
} }
void factor_vm::primitive_nano_count() void factor_vm::primitive_nano_count()
@ -18,12 +18,12 @@ void factor_vm::primitive_nano_count()
u64 nanos = nano_count(); u64 nanos = nano_count();
if(nanos < last_nano_count) critical_error("Monotonic counter decreased",0); if(nanos < last_nano_count) critical_error("Monotonic counter decreased",0);
last_nano_count = nanos; last_nano_count = nanos;
box_unsigned_8(nanos); ctx->push(from_unsigned_8(nanos));
} }
void factor_vm::primitive_sleep() void factor_vm::primitive_sleep()
{ {
sleep_nanos(to_unsigned_8(dpop())); sleep_nanos(to_unsigned_8(ctx->pop()));
} }
} }

View File

@ -101,9 +101,9 @@ string *factor_vm::allot_string(cell capacity, cell fill)
void factor_vm::primitive_string() void factor_vm::primitive_string()
{ {
cell initial = to_cell(dpop()); cell initial = to_cell(ctx->pop());
cell length = unbox_array_size(); cell length = unbox_array_size();
dpush(tag<string>(allot_string(length,initial))); ctx->push(tag<string>(allot_string(length,initial)));
} }
bool factor_vm::reallot_string_in_place_p(string *str, cell capacity) bool factor_vm::reallot_string_in_place_p(string *str, cell capacity)
@ -157,32 +157,32 @@ string* factor_vm::reallot_string(string *str_, cell capacity)
void factor_vm::primitive_resize_string() void factor_vm::primitive_resize_string()
{ {
data_root<string> str(dpop(),this); data_root<string> str(ctx->pop(),this);
str.untag_check(this); str.untag_check(this);
cell capacity = unbox_array_size(); cell capacity = unbox_array_size();
dpush(tag<string>(reallot_string(str.untagged(),capacity))); ctx->push(tag<string>(reallot_string(str.untagged(),capacity)));
} }
void factor_vm::primitive_string_nth() void factor_vm::primitive_string_nth()
{ {
string *str = untag<string>(dpop()); string *str = untag<string>(ctx->pop());
cell index = untag_fixnum(dpop()); cell index = untag_fixnum(ctx->pop());
dpush(tag_fixnum(str->nth(index))); ctx->push(tag_fixnum(str->nth(index)));
} }
void factor_vm::primitive_set_string_nth_fast() void factor_vm::primitive_set_string_nth_fast()
{ {
string *str = untag<string>(dpop()); string *str = untag<string>(ctx->pop());
cell index = untag_fixnum(dpop()); cell index = untag_fixnum(ctx->pop());
cell value = untag_fixnum(dpop()); cell value = untag_fixnum(ctx->pop());
set_string_nth_fast(str,index,value); set_string_nth_fast(str,index,value);
} }
void factor_vm::primitive_set_string_nth_slow() void factor_vm::primitive_set_string_nth_slow()
{ {
string *str = untag<string>(dpop()); string *str = untag<string>(ctx->pop());
cell index = untag_fixnum(dpop()); cell index = untag_fixnum(ctx->pop());
cell value = untag_fixnum(dpop()); cell value = untag_fixnum(ctx->pop());
set_string_nth_slow(str,index,value); set_string_nth_slow(str,index,value);
} }

View File

@ -6,27 +6,27 @@ namespace factor
/* push a new tuple on the stack, filling its slots with f */ /* push a new tuple on the stack, filling its slots with f */
void factor_vm::primitive_tuple() void factor_vm::primitive_tuple()
{ {
data_root<tuple_layout> layout(dpop(),this); data_root<tuple_layout> layout(ctx->pop(),this);
tagged<tuple> t(allot<tuple>(tuple_size(layout.untagged()))); tagged<tuple> t(allot<tuple>(tuple_size(layout.untagged())));
t->layout = layout.value(); t->layout = layout.value();
memset_cell(t->data(),false_object,tuple_size(layout.untagged()) - sizeof(cell)); memset_cell(t->data(),false_object,tuple_size(layout.untagged()) - sizeof(cell));
dpush(t.value()); ctx->push(t.value());
} }
/* push a new tuple on the stack, filling its slots from the stack */ /* push a new tuple on the stack, filling its slots from the stack */
void factor_vm::primitive_tuple_boa() void factor_vm::primitive_tuple_boa()
{ {
data_root<tuple_layout> layout(dpop(),this); data_root<tuple_layout> layout(ctx->pop(),this);
tagged<tuple> t(allot<tuple>(tuple_size(layout.untagged()))); tagged<tuple> t(allot<tuple>(tuple_size(layout.untagged())));
t->layout = layout.value(); t->layout = layout.value();
cell size = untag_fixnum(layout.untagged()->size) * sizeof(cell); cell size = untag_fixnum(layout.untagged()->size) * sizeof(cell);
memcpy(t->data(),(cell *)(ds - size + sizeof(cell)),size); memcpy(t->data(),(cell *)(ctx->datastack - size + sizeof(cell)),size);
ds -= size; ctx->datastack -= size;
dpush(t.value()); ctx->push(t.value());
} }
} }

View File

@ -92,10 +92,6 @@ struct factor_vm
u64 last_nano_count; u64 last_nano_count;
// contexts // contexts
void reset_datastack();
void reset_retainstack();
void fix_stacks();
void save_stacks();
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(stack_frame *magic_frame);
@ -375,9 +371,7 @@ struct factor_vm
void primitive_set_string_nth_slow(); void primitive_set_string_nth_slow();
//booleans //booleans
void box_boolean(bool value); cell tag_boolean(cell untagged)
inline cell tag_boolean(cell untagged)
{ {
return (untagged ? true_object : false_object); return (untagged ? true_object : false_object);
} }
@ -462,21 +456,19 @@ struct factor_vm
void primitive_bits_double(); void primitive_bits_double();
fixnum to_fixnum(cell tagged); fixnum to_fixnum(cell tagged);
cell to_cell(cell tagged); cell to_cell(cell tagged);
void box_signed_1(s8 n); cell from_signed_1(s8 n);
void box_unsigned_1(u8 n); cell from_unsigned_1(u8 n);
void box_signed_2(s16 n); cell from_signed_2(s16 n);
void box_unsigned_2(u16 n); cell from_unsigned_2(u16 n);
void box_signed_4(s32 n); cell from_signed_4(s32 n);
void box_unsigned_4(u32 n); cell from_unsigned_4(u32 n);
void box_signed_cell(fixnum integer); cell from_signed_cell(fixnum integer);
void box_unsigned_cell(cell cell); cell from_unsigned_cell(cell integer);
void box_signed_8(s64 n); cell from_signed_8(s64 n);
s64 to_signed_8(cell obj); s64 to_signed_8(cell obj);
void box_unsigned_8(u64 n); cell from_unsigned_8(u64 n);
u64 to_unsigned_8(cell obj); u64 to_unsigned_8(cell obj);
void box_float(float flo);
float to_float(cell value); float to_float(cell value);
void box_double(double flo);
double to_double(cell value); double to_double(cell value);
inline void overflow_fixnum_add(fixnum x, fixnum y); inline void overflow_fixnum_add(fixnum x, fixnum y);
inline void overflow_fixnum_subtract(fixnum x, fixnum y); inline void overflow_fixnum_subtract(fixnum x, fixnum y);
@ -498,6 +490,7 @@ struct factor_vm
void init_c_io(); void init_c_io();
void io_error(); void io_error();
void primitive_fopen(); void primitive_fopen();
FILE *pop_file_handle();
void primitive_fgetc(); void primitive_fgetc();
void primitive_fread(); void primitive_fread();
void primitive_fputc(); void primitive_fputc();
@ -582,12 +575,12 @@ struct factor_vm
void primitive_innermost_stack_frame_executing(); void primitive_innermost_stack_frame_executing();
void primitive_innermost_stack_frame_scan(); void primitive_innermost_stack_frame_scan();
void primitive_set_innermost_stack_frame_quot(); void primitive_set_innermost_stack_frame_quot();
void save_callstack_bottom(stack_frame *callstack_bottom);
template<typename Iterator> void iterate_callstack(context *ctx, Iterator &iterator); template<typename Iterator> void iterate_callstack(context *ctx, Iterator &iterator);
//alien //alien
char *pinned_alien_offset(cell obj); char *pinned_alien_offset(cell obj);
cell allot_alien(cell delegate_, cell displacement); cell allot_alien(cell delegate_, cell displacement);
cell allot_alien(void *address);
void primitive_displaced_alien(); void primitive_displaced_alien();
void primitive_alien_address(); void primitive_alien_address();
void *alien_pointer(); void *alien_pointer();
@ -597,12 +590,10 @@ struct factor_vm
void primitive_dll_validp(); void primitive_dll_validp();
void primitive_vm_ptr(); void primitive_vm_ptr();
char *alien_offset(cell obj); char *alien_offset(cell obj);
char *unbox_alien();
void box_alien(void *ptr);
void to_value_struct(cell src, void *dest, cell size); void to_value_struct(cell src, void *dest, cell size);
void box_value_struct(void *src, cell size); cell from_value_struct(void *src, cell size);
void box_small_struct(cell x, cell y, cell size); cell from_small_struct(cell x, cell y, cell size);
void box_medium_struct(cell x1, cell x2, cell x3, cell x4, cell size); cell from_medium_struct(cell x1, cell x2, cell x3, cell x4, cell size);
//quotations //quotations
void primitive_jit_compile(); void primitive_jit_compile();
@ -612,7 +603,7 @@ struct factor_vm
code_block *jit_compile_quot(cell owner_, cell quot_, bool relocating); code_block *jit_compile_quot(cell owner_, cell quot_, bool relocating);
void jit_compile_quot(cell quot_, bool relocating); void jit_compile_quot(cell quot_, bool relocating);
fixnum quot_code_offset_to_scan(cell quot_, cell offset); fixnum quot_code_offset_to_scan(cell quot_, cell offset);
cell lazy_jit_compile_impl(cell quot_, stack_frame *stack); cell lazy_jit_compile(cell quot);
void primitive_quot_compiled_p(); void primitive_quot_compiled_p();
//dispatch //dispatch

View File

@ -34,7 +34,6 @@ void factor_vm::compile_all_words()
jit_compile_word(word.value(),word->def,false); jit_compile_word(word.value(),word->def,false);
update_word_xt(word.untagged()); update_word_xt(word.untagged());
} }
} }
@ -73,27 +72,27 @@ word *factor_vm::allot_word(cell name_, cell vocab_, cell hashcode_)
/* (word) ( name vocabulary hashcode -- word ) */ /* (word) ( name vocabulary hashcode -- word ) */
void factor_vm::primitive_word() void factor_vm::primitive_word()
{ {
cell hashcode = dpop(); cell hashcode = ctx->pop();
cell vocab = dpop(); cell vocab = ctx->pop();
cell name = dpop(); cell name = ctx->pop();
dpush(tag<word>(allot_word(name,vocab,hashcode))); ctx->push(tag<word>(allot_word(name,vocab,hashcode)));
} }
/* word-xt ( word -- start end ) */ /* word-xt ( word -- start end ) */
void factor_vm::primitive_word_xt() void factor_vm::primitive_word_xt()
{ {
data_root<word> w(dpop(),this); data_root<word> w(ctx->pop(),this);
w.untag_check(this); w.untag_check(this);
if(profiling_p) if(profiling_p)
{ {
dpush(allot_cell((cell)w->profiling->xt())); ctx->push(allot_cell((cell)w->profiling->xt()));
dpush(allot_cell((cell)w->profiling + w->profiling->size())); ctx->push(allot_cell((cell)w->profiling + w->profiling->size()));
} }
else else
{ {
dpush(allot_cell((cell)w->code->xt())); ctx->push(allot_cell((cell)w->code->xt()));
dpush(allot_cell((cell)w->code + w->code->size())); ctx->push(allot_cell((cell)w->code + w->code->size()));
} }
} }
@ -107,15 +106,15 @@ void factor_vm::update_word_xt(word *w)
void factor_vm::primitive_optimized_p() void factor_vm::primitive_optimized_p()
{ {
word *w = untag_check<word>(dpeek()); word *w = untag_check<word>(ctx->peek());
drepl(tag_boolean(w->code->optimized_p())); ctx->replace(tag_boolean(w->code->optimized_p()));
} }
void factor_vm::primitive_wrapper() void factor_vm::primitive_wrapper()
{ {
wrapper *new_wrapper = allot<wrapper>(sizeof(wrapper)); wrapper *new_wrapper = allot<wrapper>(sizeof(wrapper));
new_wrapper->object = dpeek(); new_wrapper->object = ctx->peek();
drepl(tag<wrapper>(new_wrapper)); ctx->replace(tag<wrapper>(new_wrapper));
} }
} }