Merge branch 'eliminating_register_variables'
commit
4d70649914
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 ;
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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 -- )
|
||||||
|
|
|
@ -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 ( -- )
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
[
|
[
|
||||||
|
|
|
@ -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 ;
|
||||||
|
|
||||||
|
|
|
@ -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 ;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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" (( -- * )) }
|
||||||
|
|
|
@ -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" } "." } ;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
160
vm/alien.cpp
160
vm/alien.cpp
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
10
vm/alien.hpp
10
vm/alien.hpp
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
182
vm/cpu-x86.32.S
182
vm/cpu-x86.32.S
|
@ -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
|
||||||
|
|
|
@ -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)))
|
|
||||||
}
|
}
|
||||||
|
|
154
vm/cpu-x86.64.S
154
vm/cpu-x86.64.S
|
@ -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
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
32
vm/cpu-x86.S
32
vm/cpu-x86.S
|
@ -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
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
vm/debug.cpp
10
vm/debug.cpp
|
@ -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();
|
||||||
|
|
|
@ -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_)
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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());
|
||||||
|
|
||||||
|
|
47
vm/io.cpp
47
vm/io.cpp
|
@ -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)
|
||||||
|
|
267
vm/math.cpp
267
vm/math.cpp
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
34
vm/math.hpp
34
vm/math.hpp
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
43
vm/vm.hpp
43
vm/vm.hpp
|
@ -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
|
||||||
|
|
27
vm/words.cpp
27
vm/words.cpp
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue