Merge branch 'master' of git://factorcode.org/git/factor

db4
Anton Gorenko 2010-06-17 11:33:21 +06:00
commit 507583c8d3
49 changed files with 577 additions and 380 deletions

View File

@ -102,7 +102,7 @@ M: #alien-invoke emit-node
[
{
[ caller-parameters ]
[ ##prepare-var-args alien-invoke-dlsym ##alien-invoke ]
[ ##prepare-var-args alien-invoke-dlsym <gc-map> ##alien-invoke ]
[ emit-stack-frame ]
[ box-return* ]
} cleave
@ -111,7 +111,7 @@ M: #alien-invoke emit-node
M:: #alien-indirect emit-node ( node -- )
node [
D 0 ^^peek -1 ##inc-d ^^unbox-any-c-ptr :> src
[ caller-parameters src ##alien-indirect ]
[ caller-parameters src <gc-map> ##alien-indirect ]
[ emit-stack-frame ]
[ box-return* ]
tri

View File

@ -105,13 +105,13 @@ M: struct-c-type flatten-parameter-type frob-struct flatten-c-type ;
GENERIC: box ( vregs reps c-type -- dst )
M: c-type box
[ first ] [ drop ] [ [ boxer>> ] [ rep>> ] bi ] tri* ^^box ;
[ first ] [ drop ] [ [ boxer>> ] [ rep>> ] bi ] tri* <gc-map> ^^box ;
M: long-long-type box
[ first2 ] [ drop ] [ boxer>> ] tri* ^^box-long-long ;
[ first2 ] [ drop ] [ boxer>> ] tri* <gc-map> ^^box-long-long ;
M: struct-c-type box
'[ _ heap-size ^^allot-byte-array dup ^^unbox-byte-array ] 2dip
'[ _ heap-size <gc-map> ^^allot-byte-array dup ^^unbox-byte-array ] 2dip
implode-struct ;
GENERIC: box-parameter ( vregs reps c-type -- dst )

View File

@ -1,15 +1,17 @@
! Copyright (C) 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: compiler.cfg.gc-checks compiler.cfg.representations
compiler.cfg.save-contexts compiler.cfg.ssa.destruction
compiler.cfg.build-stack-frame compiler.cfg.linear-scan
compiler.cfg.scheduling ;
USING: kernel compiler.cfg.gc-checks
compiler.cfg.representations compiler.cfg.save-contexts
compiler.cfg.ssa.destruction compiler.cfg.build-stack-frame
compiler.cfg.linear-scan compiler.cfg.scheduling
compiler.cfg.stacks.uninitialized ;
IN: compiler.cfg.finalization
: finalize-cfg ( cfg -- cfg' )
select-representations
schedule-instructions
insert-gc-checks
dup compute-uninitialized-sets
insert-save-contexts
destruct-ssa
linear-scan

View File

@ -42,13 +42,12 @@ V{
[
V{
T{ ##gc-map f V{ 0 } V{ 3 } { 0 1 2 } }
T{ ##call-gc }
T{ ##call-gc f T{ gc-map } }
T{ ##branch }
}
]
[
V{ D 0 R 3 } { 0 1 2 } <gc-call> instructions>>
<gc-call> instructions>>
] unit-test
30 \ vreg-counter set-global
@ -82,7 +81,7 @@ V{
[ ] [ cfg get needs-predecessors drop ] unit-test
[ ] [ { D 1 R 2 } { 10 20 } V{ } 31337 3 get (insert-gc-check) ] unit-test
[ ] [ V{ } 31337 3 get (insert-gc-check) ] unit-test
[ t ] [ 1 get successors>> first gc-check? ] unit-test
@ -146,8 +145,7 @@ H{
[
V{
T{ ##gc-map f V{ 0 1 2 } V{ } { 2 } }
T{ ##call-gc }
T{ ##call-gc f T{ gc-map } }
T{ ##branch }
}
] [ 2 get predecessors>> second instructions>> ] unit-test

View File

@ -9,10 +9,7 @@ compiler.cfg.registers
compiler.cfg.utilities
compiler.cfg.comparisons
compiler.cfg.instructions
compiler.cfg.predecessors
compiler.cfg.liveness
compiler.cfg.liveness.ssa
compiler.cfg.stacks.uninitialized ;
compiler.cfg.predecessors ;
IN: compiler.cfg.gc-checks
<PRIVATE
@ -50,12 +47,9 @@ IN: compiler.cfg.gc-checks
] bi*
] V{ } make >>instructions ;
: scrubbed ( uninitialized-locs -- scrub-d scrub-r )
[ ds-loc? ] partition [ [ n>> ] map ] bi@ ;
: <gc-call> ( uninitialized-locs gc-roots -- bb )
[ <basic-block> ] 2dip
[ [ scrubbed ] dip ##gc-map ##call-gc ##branch ] V{ } make
: <gc-call> ( -- bb )
<basic-block>
[ <gc-map> ##call-gc ##branch ] V{ } make
>>instructions t >>unlikely? ;
:: insert-guard ( body check bb -- )
@ -69,7 +63,7 @@ IN: compiler.cfg.gc-checks
check predecessors>> [ bb check update-successors ] each ;
: (insert-gc-check) ( uninitialized-locs gc-roots phis size bb -- )
: (insert-gc-check) ( phis size bb -- )
[ [ <gc-call> ] 2dip <gc-check> ] dip insert-guard ;
GENERIC: allocation-size* ( insn -- n )
@ -85,35 +79,17 @@ M: ##box-displaced-alien allocation-size* drop 5 cells ;
[ ##allocation? ] filter
[ allocation-size* data-alignment get align ] map-sum ;
: gc-live-in ( bb -- vregs )
[ live-in keys ] [ instructions>> [ ##phi? ] filter [ dst>> ] map ] bi
append ;
: live-tagged ( bb -- vregs )
gc-live-in [ rep-of tagged-rep? ] filter ;
: remove-phis ( bb -- phis )
[ [ ##phi? ] partition ] change-instructions drop ;
: insert-gc-check ( bb -- )
{
[ uninitialized-locs ]
[ live-tagged ]
[ remove-phis ]
[ allocation-size ]
[ ]
} cleave
(insert-gc-check) ;
[ remove-phis ] [ allocation-size ] [ ] tri (insert-gc-check) ;
PRIVATE>
: insert-gc-checks ( cfg -- cfg' )
dup blocks-with-gc [
[
needs-predecessors
dup compute-ssa-live-sets
dup compute-uninitialized-sets
] dip
[ needs-predecessors ] dip
[ insert-gc-check ] each
cfg-changed
] unless-empty ;

View File

@ -670,27 +670,28 @@ literal: size align offset ;
INSN: ##box
def: dst/tagged-rep
use: src
literal: boxer rep ;
literal: boxer rep gc-map ;
INSN: ##box-long-long
def: dst/tagged-rep
use: src1/int-rep src2/int-rep
literal: boxer ;
literal: boxer gc-map ;
INSN: ##allot-byte-array
def: dst/tagged-rep
literal: size ;
literal: size gc-map ;
INSN: ##prepare-var-args ;
INSN: ##alien-invoke
literal: symbols dll ;
literal: symbols dll gc-map ;
INSN: ##cleanup
literal: n ;
INSN: ##alien-indirect
use: src/int-rep ;
use: src/int-rep
literal: gc-map ;
INSN: ##alien-assembly
literal: quot ;
@ -819,10 +820,7 @@ INSN: ##check-nursery-branch
literal: size cc
temp: temp1/int-rep temp2/int-rep ;
INSN: ##call-gc ;
INSN: ##gc-map
literal: scrub-d scrub-r gc-roots ;
INSN: ##call-gc literal: gc-map ;
! Spills and reloads, inserted by register allocator
TUPLE: spill-slot { n integer } ;
@ -860,6 +858,23 @@ UNION: conditional-branch-insn
UNION: ##read ##slot ##slot-imm ##vm-field ##alien-global ;
UNION: ##write ##set-slot ##set-slot-imm ##set-vm-field ;
! Instructions that contain subroutine calls to functions which
! allocate memory
UNION: gc-map-insn
##call-gc
##alien-invoke
##alien-indirect
##box
##box-long-long
##allot-byte-array ;
M: gc-map-insn clone call-next-method [ clone ] change-gc-map ;
! Each one has a gc-map slot
TUPLE: gc-map scrub-d scrub-r gc-roots ;
: <gc-map> ( -- gc-map ) gc-map new ;
! Instructions that clobber registers. They receive inputs and
! produce outputs in spill slots.
UNION: hairy-clobber-insn

View File

@ -142,8 +142,10 @@ RENAMING: assign [ vreg>reg ] [ vreg>reg ] [ vreg>reg ]
M: vreg-insn assign-registers-in-insn
[ assign-insn-defs ] [ assign-insn-uses ] [ assign-insn-temps ] tri ;
M: ##gc-map assign-registers-in-insn
[ [ vreg>reg ] map ] change-gc-roots drop ;
M: gc-map-insn assign-registers-in-insn
[ [ assign-insn-defs ] [ assign-insn-uses ] [ assign-insn-temps ] tri ]
[ gc-map>> [ [ vreg>reg ] map ] change-gc-roots drop ]
bi ;
M: insn assign-registers-in-insn drop ;

View File

@ -1,25 +1,40 @@
! Copyright (C) 2009 Slava Pestov.
! Copyright (C) 2009, 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: kernel accessors assocs sequences sets
compiler.cfg.def-use compiler.cfg.dataflow-analysis
compiler.cfg.instructions ;
compiler.cfg.instructions compiler.cfg.registers
cpu.architecture ;
IN: compiler.cfg.liveness
! See http://en.wikipedia.org/wiki/Liveness_analysis
! Do not run after SSA construction
! Do not run after SSA construction; compiler.cfg.liveness.ssa
! should be used instead. The transfer-liveness word is used
! by SSA liveness too, so it handles ##phi instructions.
BACKWARD-ANALYSIS: live
GENERIC: insn-liveness ( live-set insn -- )
GENERIC: visit-insn ( live-set insn -- live-set )
: kill-defs ( live-set insn -- live-set )
defs-vreg [ over delete-at ] when* ;
defs-vreg [ over delete-at ] when* ; inline
: gen-uses ( live-set insn -- live-set )
dup ##phi? [ drop ] [ uses-vregs [ over conjoin ] each ] if ;
uses-vregs [ over conjoin ] each ; inline
M: vreg-insn visit-insn [ kill-defs ] [ gen-uses ] bi ;
: fill-gc-map ( live-set insn -- live-set )
gc-map>> over keys [ rep-of tagged-rep? ] filter >>gc-roots drop ;
M: gc-map-insn visit-insn
[ kill-defs ] [ fill-gc-map ] [ gen-uses ] tri ;
M: ##phi visit-insn kill-defs ;
M: insn visit-insn drop ;
: transfer-liveness ( live-set instructions -- live-set' )
[ clone ] [ <reversed> ] bi* [ [ kill-defs ] [ gen-uses ] bi ] each ;
[ clone ] [ <reversed> ] bi* [ visit-insn ] each ;
: local-live-in ( instructions -- live-set )
[ H{ } ] dip transfer-liveness keys ;

View File

@ -182,7 +182,7 @@ V{
V{
T{ ##save-context f 77 78 }
T{ ##call-gc f { } }
T{ ##call-gc f T{ gc-map } }
T{ ##branch }
} 2 test-bb

View File

@ -29,8 +29,8 @@ V{
[ ] [ test-uninitialized ] unit-test
[ V{ D 0 D 1 D 2 } ] [ 1 get uninitialized-locs ] unit-test
[ V{ R 0 } ] [ 2 get uninitialized-locs ] unit-test
[ { B{ 0 0 0 } B{ } } ] [ 1 get uninitialized-in ] unit-test
[ { B{ 1 1 1 } B{ 0 } } ] [ 2 get uninitialized-in ] unit-test
! When merging, if a location is uninitialized in one branch and
! initialized in another, we have to consider it uninitialized,
@ -57,4 +57,4 @@ V{
[ ] [ test-uninitialized ] unit-test
[ V{ D 0 } ] [ 3 get uninitialized-locs ] unit-test
[ { B{ 0 } B{ } } ] [ 3 get uninitialized-in ] unit-test

View File

@ -9,11 +9,17 @@ IN: compiler.cfg.stacks.uninitialized
! Consider the following sequence of instructions:
! ##inc-d 2
! ##gc
! ...
! ##allot
! ##replace ... D 0
! ##replace ... D 1
! The GC check runs before stack locations 0 and 1 have been initialized,
! and it needs to zero them out so that GC doesn't try to trace them.
! The GC check runs before stack locations 0 and 1 have been
! initialized, and so the GC needs to scrub them so that they
! don't get traced. This is achieved by computing uninitialized
! locations with a dataflow analysis, and recording the
! information in GC maps. The scrub_contexts() method on
! vm/gc.cpp reads this information from GC maps and performs
! the scrubbing.
<PRIVATE
@ -28,7 +34,6 @@ GENERIC: visit-insn ( insn -- )
] change ;
M: ##inc-d visit-insn n>> ds-loc handle-inc ;
M: ##inc-r visit-insn n>> rs-loc handle-inc ;
ERROR: uninitialized-peek insn ;
@ -46,6 +51,12 @@ M: ##peek visit-insn visit-peek ;
M: ##replace visit-insn visit-replace ;
M: ##replace-imm visit-insn visit-replace ;
M: gc-map-insn visit-insn
gc-map>>
ds-loc get clone >>scrub-d
rs-loc get clone >>scrub-r
drop ;
M: insn visit-insn drop ;
: prepare ( pair -- )
@ -59,9 +70,6 @@ M: insn visit-insn drop ;
: (join-sets) ( seq1 seq2 -- seq )
2dup [ length ] bi@ max '[ _ 1 pad-tail ] bi@ [ bitand ] 2map ;
: (uninitialized-locs) ( seq quot -- seq' )
[ [ drop 0 = ] selector [ each-index ] dip ] dip map ; inline
PRIVATE>
FORWARD-ANALYSIS: uninitialized
@ -71,11 +79,3 @@ M: uninitialized-analysis transfer-set ( pair bb analysis -- pair' )
M: uninitialized-analysis join-sets ( sets analysis -- pair )
2drop sift [ f ] [ [ ] [ [ (join-sets) ] 2map ] map-reduce ] if-empty ;
: uninitialized-locs ( bb -- locs )
uninitialized-in dup [
first2
[ [ <ds-loc> ] (uninitialized-locs) ]
[ [ <rs-loc> ] (uninitialized-locs) ]
bi* append f like
] when ;

View File

@ -258,7 +258,6 @@ CODEGEN: ##restore-context %restore-context
CODEGEN: ##vm-field %vm-field
CODEGEN: ##set-vm-field %set-vm-field
CODEGEN: ##alien-global %alien-global
CODEGEN: ##gc-map %gc-map
CODEGEN: ##call-gc %call-gc
CODEGEN: ##spill %spill
CODEGEN: ##reload %reload

View File

@ -1,6 +1,7 @@
USING: namespaces byte-arrays make compiler.codegen.fixup
bit-arrays accessors classes.struct tools.test kernel math
sequences alien.c-types specialized-arrays boxes ;
sequences alien.c-types specialized-arrays boxes
compiler.cfg.instructions system cpu.architecture ;
SPECIALIZED-ARRAY: uint
IN: compiler.codegen.fixup.tests
@ -10,19 +11,23 @@ STRUCT: gc-info
{ gc-root-count uint }
{ return-address-count uint } ;
SINGLETON: fake-cpu
fake-cpu \ cpu set
M: fake-cpu gc-root-offsets ;
[ ] [
[
init-fixup
50 <byte-array> %
{ { } { } { } } set-next-gc-map
gc-map-here
T{ gc-map f B{ } B{ } V{ } } gc-map-here
50 <byte-array> %
{ { 0 4 } { 1 } { 1 3 } } set-next-gc-map
gc-map-here
T{ gc-map f B{ 0 1 1 1 0 } B{ 1 0 } V{ 1 3 } } gc-map-here
emit-gc-info
] B{ } make

View File

@ -4,8 +4,9 @@ USING: arrays bit-arrays byte-arrays byte-vectors generic assocs
hashtables io.binary kernel kernel.private math namespaces make
sequences words quotations strings alien.accessors alien.strings
layouts system combinators math.bitwise math.order
combinators.smart accessors growable fry compiler.constants
memoize boxes ;
combinators.short-circuit combinators.smart accessors growable
fry memoize compiler.constants compiler.cfg.instructions
cpu.architecture ;
IN: compiler.codegen.fixup
! Utilities
@ -149,30 +150,37 @@ MEMO: cached-string>symbol ( symbol -- obj ) string>symbol ;
! uint <largest GC root spill slot>
! uint <number of return addresses>
SYMBOLS: next-gc-map return-addresses gc-maps ;
SYMBOLS: return-addresses gc-maps ;
: gc-map? ( triple -- ? )
: gc-map-needed? ( gc-map -- ? )
! If there are no stack locations to scrub and no GC roots,
! there's no point storing the GC map.
[ empty? not ] any? ;
dup [
{
[ scrub-d>> empty? ]
[ scrub-r>> empty? ]
[ gc-roots>> empty? ]
} 1&& not
] when ;
: gc-map-here ( -- )
next-gc-map get box> dup gc-map? [
: gc-map-here ( gc-map -- )
dup gc-map-needed? [
gc-maps get push
compiled-offset return-addresses get push
] [ drop ] if ;
: set-next-gc-map ( gc-map -- ) next-gc-map get >box ;
: emit-scrub ( seqs -- n )
! seqs is a sequence of sequences of 0/1
dup [ length ] [ max ] map-reduce
[ '[ [ 0 = ] ?{ } map-as _ f pad-tail % ] each ] keep ;
: integers>bits ( seq n -- bit-array )
<bit-array> [ '[ [ t ] dip _ set-nth ] each ] keep ;
: emit-bitmap ( seqs -- n )
: emit-gc-roots ( seqs -- n )
! seqs is a sequence of sequences of integers 0..n-1
[ 0 ] [
dup [ [ 0 ] [ supremum 1 + ] if-empty ] [ max ] map-reduce
[ '[ _ integers>bits % ] each ] keep
] if-empty ;
dup [ [ 0 ] [ supremum 1 + ] if-empty ] [ max ] map-reduce
[ '[ _ integers>bits % ] each ] keep ;
: emit-uint ( n -- )
building get push-uint ;
@ -182,9 +190,9 @@ SYMBOLS: next-gc-map return-addresses gc-maps ;
return-addresses get empty? [ 0 emit-uint ] [
gc-maps get
[
[ [ first ] map emit-bitmap ]
[ [ second ] map emit-bitmap ]
[ [ third ] map emit-bitmap ] tri
[ [ scrub-d>> ] map emit-scrub ]
[ [ scrub-r>> ] map emit-scrub ]
[ [ gc-roots>> gc-root-offsets ] map emit-gc-roots ] tri
] ?{ } make underlying>> %
return-addresses get [ emit-uint ] each
[ emit-uint ] tri@
@ -208,12 +216,10 @@ SYMBOLS: next-gc-map return-addresses gc-maps ;
BV{ } clone relocation-table set
V{ } clone binary-literal-table set
V{ } clone return-addresses set
V{ } clone gc-maps set
<box> next-gc-map set ;
V{ } clone gc-maps set ;
: check-fixup ( seq -- )
length data-alignment get mod 0 assert=
next-gc-map get occupied>> f assert= ;
length data-alignment get mod 0 assert= ;
: with-fixup ( quot -- code )
'[

View File

@ -225,6 +225,8 @@ M: object vm-stack-space 0 ;
! %store-memory work
HOOK: complex-addressing? cpu ( -- ? )
HOOK: gc-root-offsets cpu ( seq -- seq' )
HOOK: %load-immediate cpu ( reg val -- )
HOOK: %load-reference cpu ( reg obj -- )
HOOK: %load-float cpu ( reg val -- )
@ -488,8 +490,7 @@ HOOK: %write-barrier-imm cpu ( src slot tag temp1 temp2 -- )
! GC checks
HOOK: %check-nursery-branch cpu ( label size cc temp1 temp2 -- )
HOOK: %gc-map cpu ( scrub-d scrub-r gc-roots -- )
HOOK: %call-gc cpu ( -- )
HOOK: %call-gc cpu ( gc-map -- )
HOOK: %prologue cpu ( n -- )
HOOK: %epilogue cpu ( n -- )
@ -595,11 +596,11 @@ HOOK: %local-allot cpu ( dst size align offset -- )
! 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
HOOK: %box cpu ( dst src func rep -- )
HOOK: %box cpu ( dst src func rep gc-map -- )
HOOK: %box-long-long cpu ( dst src1 src2 func -- )
HOOK: %box-long-long cpu ( dst src1 src2 func gc-map -- )
HOOK: %allot-byte-array cpu ( dst size -- )
HOOK: %allot-byte-array cpu ( dst size gc-map -- )
HOOK: %restore-context cpu ( temp1 temp2 -- )
@ -609,13 +610,13 @@ HOOK: %prepare-var-args cpu ( -- )
M: object %prepare-var-args ;
HOOK: %alien-invoke cpu ( function library -- )
HOOK: %alien-invoke cpu ( function library gc-map -- )
HOOK: %cleanup cpu ( n -- )
M: object %cleanup ( n -- ) drop ;
HOOK: %alien-indirect cpu ( src -- )
HOOK: %alien-indirect cpu ( src gc-map -- )
HOOK: %load-reg-param cpu ( dst reg rep -- )

View File

@ -134,7 +134,7 @@ M: x86.32 %store-reg-param ( src reg rep -- )
EAX src tagged-rep %copy
4 save-vm-ptr
0 stack@ EAX MOV
func f %alien-invoke ;
func f f %alien-invoke ;
M:: x86.32 %unbox ( dst src func rep -- )
src func call-unbox-func
@ -146,36 +146,37 @@ M:: x86.32 %unbox-long-long ( src out func -- )
EAX out int-rep %copy
4 stack@ EAX MOV
8 save-vm-ptr
func f %alien-invoke ;
func f f %alien-invoke ;
M:: x86.32 %box ( dst src func rep -- )
M:: x86.32 %box ( dst src func rep gc-map -- )
rep rep-size save-vm-ptr
src rep %store-return
0 stack@ rep %load-return
func f %alien-invoke
func f gc-map %alien-invoke
dst EAX tagged-rep %copy ;
M:: x86.32 %box-long-long ( dst src1 src2 func -- )
M:: x86.32 %box-long-long ( dst src1 src2 func gc-map -- )
8 save-vm-ptr
EAX src1 int-rep %copy
0 stack@ EAX int-rep %copy
EAX src2 int-rep %copy
4 stack@ EAX int-rep %copy
func f %alien-invoke
func f gc-map %alien-invoke
dst EAX tagged-rep %copy ;
M:: x86.32 %allot-byte-array ( dst size -- )
M:: x86.32 %allot-byte-array ( dst size gc-map -- )
4 save-vm-ptr
0 stack@ size MOV
"allot_byte_array" f %alien-invoke
"allot_byte_array" f gc-map %alien-invoke
dst EAX tagged-rep %copy ;
M: x86.32 %alien-invoke 0 CALL rc-relative rel-dlsym ;
M: x86.32 %alien-invoke
[ 0 CALL rc-relative rel-dlsym ] dip gc-map-here ;
M: x86.32 %begin-callback ( -- )
0 save-vm-ptr
4 stack@ 0 MOV
"begin_callback" f %alien-invoke ;
"begin_callback" f f %alien-invoke ;
M: x86.32 %alien-callback ( quot -- )
[ EAX ] dip %load-reference
@ -183,7 +184,7 @@ M: x86.32 %alien-callback ( quot -- )
M: x86.32 %end-callback ( -- )
0 save-vm-ptr
"end_callback" f %alien-invoke ;
"end_callback" f f %alien-invoke ;
GENERIC: float-function-param ( n dst src -- )
@ -198,13 +199,13 @@ M:: register float-function-param ( n dst src -- )
M:: x86.32 %unary-float-function ( dst src func -- )
0 dst src float-function-param
func "libm" load-library %alien-invoke
func "libm" load-library f %alien-invoke
dst double-rep %load-return ;
M:: x86.32 %binary-float-function ( dst src1 src2 func -- )
0 dst src1 float-function-param
8 dst src2 float-function-param
func "libm" load-library %alien-invoke
func "libm" load-library f %alien-invoke
dst double-rep %load-return ;
: funny-large-struct-return? ( return abi -- ? )

View File

@ -63,6 +63,9 @@ IN: bootstrap.x86
ds-reg ctx-reg context-datastack-offset [+] MOV
rs-reg ctx-reg context-retainstack-offset [+] MOV ;
: jit-scrub-return ( n -- )
ESP swap [+] 0 MOV ;
[
! ctx-reg is preserved across the call because it is non-volatile
! in the C ABI
@ -130,6 +133,7 @@ IN: bootstrap.x86
! Unwind stack frames
ESP EDX MOV
0 jit-scrub-return
jit-jump-quot
] \ unwind-native-frames define-sub-primitive
@ -252,9 +256,7 @@ IN: bootstrap.x86
! Contexts
: jit-switch-context ( reg -- )
! Dummy return address -- it never gets returned to but it
! must point to inside the current code block
ESP -4 [+] HEX: ffffffff MOV rc-absolute-cell rt-this jit-rel
-4 jit-scrub-return
! Save ds, rs registers
jit-load-vm

View File

@ -90,30 +90,29 @@ M:: x86.64 %store-reg-param ( src reg rep -- )
M:: x86.64 %unbox ( dst src func rep -- )
param-reg-0 src tagged-rep %copy
param-reg-1 %mov-vm-ptr
func f %alien-invoke
func f f %alien-invoke
dst rep %load-return ;
M:: x86.64 %box ( dst src func rep -- )
M:: x86.64 %box ( dst src func rep gc-map -- )
0 rep reg-class-of cdecl param-regs at nth src rep %copy
rep int-rep? os windows? or param-reg-1 param-reg-0 ? %mov-vm-ptr
func f %alien-invoke
func f gc-map %alien-invoke
dst int-rep %load-return ;
M:: x86.64 %allot-byte-array ( dst size -- )
M:: x86.64 %allot-byte-array ( dst size gc-map -- )
param-reg-0 size MOV
param-reg-1 %mov-vm-ptr
"allot_byte_array" f %alien-invoke
"allot_byte_array" f gc-map %alien-invoke
dst int-rep %load-return ;
M: x86.64 %alien-invoke
R11 0 MOV
rc-absolute-cell rel-dlsym
R11 CALL ;
[ R11 0 MOV rc-absolute-cell rel-dlsym R11 CALL ] dip
gc-map-here ;
M: x86.64 %begin-callback ( -- )
param-reg-0 %mov-vm-ptr
param-reg-1 0 MOV
"begin_callback" f %alien-invoke ;
"begin_callback" f f %alien-invoke ;
M: x86.64 %alien-callback ( quot -- )
[ param-reg-0 ] dip %load-reference
@ -121,14 +120,14 @@ M: x86.64 %alien-callback ( quot -- )
M: x86.64 %end-callback ( -- )
param-reg-0 %mov-vm-ptr
"end_callback" f %alien-invoke ;
"end_callback" f f %alien-invoke ;
: float-function-param ( i src -- )
[ float-regs cdecl param-regs at nth ] dip double-rep %copy ;
M:: x86.64 %unary-float-function ( dst src func -- )
0 src float-function-param
func "libm" load-library %alien-invoke
func "libm" load-library f %alien-invoke
dst double-rep %load-return ;
M:: x86.64 %binary-float-function ( dst src1 src2 func -- )
@ -136,7 +135,7 @@ M:: x86.64 %binary-float-function ( dst src1 src2 func -- )
! src2 is always a spill slot
0 src1 float-function-param
1 src2 float-function-param
func "libm" load-library %alien-invoke
func "libm" load-library f %alien-invoke
dst double-rep %load-return ;
M: x86.64 long-long-on-stack? f ;

View File

@ -61,6 +61,9 @@ IN: bootstrap.x86
ds-reg ctx-reg context-datastack-offset [+] MOV
rs-reg ctx-reg context-retainstack-offset [+] MOV ;
: jit-scrub-return ( n -- )
RSP swap [+] 0 MOV ;
[
! ctx-reg is preserved across the call because it is non-volatile
! in the C ABI
@ -111,6 +114,7 @@ IN: bootstrap.x86
! Unwind stack frames
RSP arg2 MOV
0 jit-scrub-return
! Load VM pointer into vm-reg, since we're entering from
! C code
@ -228,10 +232,7 @@ IN: bootstrap.x86
! Contexts
: jit-switch-context ( reg -- )
! Dummy return address -- it never gets returned to but it
! must point to inside the current code block
R11 0 [RIP+] LEA
RSP -8 [+] R11 MOV
-8 jit-scrub-return
! Save ds, rs registers
jit-save-context

View File

@ -480,13 +480,10 @@ M:: x86 %check-nursery-branch ( label size cc temp1 temp2 -- )
{ cc/<= [ label JG ] }
} case ;
: gc-root-offsets ( seq -- seq' )
M: x86 gc-root-offsets
[ n>> spill-offset special-offset cell + cell /i ] map f like ;
M: x86 %gc-map ( scrub-d scrub-r gc-roots -- )
gc-root-offsets 3array set-next-gc-map ;
M: x86 %call-gc
M: x86 %call-gc ( gc-map -- )
\ minor-gc %call
gc-map-here ;
@ -612,8 +609,8 @@ M:: x86 %load-stack-param ( dst n rep -- )
M:: x86 %local-allot ( dst size align offset -- )
dst offset local-allot-offset special-offset stack@ LEA ;
M: x86 %alien-indirect ( src -- )
?spill-slot CALL ;
M: x86 %alien-indirect ( src gc-map -- )
[ ?spill-slot CALL ] [ gc-map-here ] bi* ;
M: x86 %loop-entry 16 alignment [ NOP ] times ;

View File

@ -34,6 +34,10 @@ ARTICLE: "network-connection" "Connection-oriented networking"
<client>
with-client
}
"The local address of a client socket can be controlled with this word:"
{ $subsections
with-local-address
}
"Connection-oriented network servers are implemented by first opening a server socket, then waiting for connections:"
{ $subsections
<server>
@ -215,3 +219,17 @@ HELP: send
HELP: resolve-host
{ $values { "addrspec" "an address specifier" } { "seq" "a sequence of address specifiers" } }
{ $description "Resolves host names to IP addresses." } ;
HELP: with-local-address
{ $values { "addr" "an " { $link inet4 } " or " { $link inet6 } " address specifier" } { "quot" quotation } }
{ $description "Client sockets opened within the scope of the quotation passed to this combinator will have their local address bound to the given address." }
{ $examples
{ "Binds the local address of a newly created client socket within the quotation to 127.0.0.1."
"This ensures that all traffic originates from the given address (the port is choosen by the TCP stack)." }
{ $code "\"127.0.0.1\" 0 <inet4> [ ] with-local-address" }
$nl
{ "Binds the local address of a newly created client socket within the quotation to the local address 192.168.0.1 and the local port 23000. "
"Be aware that you can only have one client socket with the same local address at a time or else an I/O error (\"address already in use\") will be thrown."
}
{ $code "\"192.168.0.1\" 23000 <inet4> [ ] with-local-address" }
} ;

View File

@ -0,0 +1,4 @@
USING: math.vectors.simd math.vectors.simd.cords tools.test ;
IN: math.vectors.simd.cords.tests
[ float-4{ 1.0 2.0 3.0 4.0 } ] [ double-4{ 1.0 2.0 3.0 4.0 } >float-4 ] unit-test

View File

@ -28,8 +28,8 @@ BOA-EFFECT [ N 2 * "n" <array> { "v" } <effect> ]
WHERE
: >A ( seq -- A )
[ N head >A/2 ]
[ N tail >A/2 ] bi cord-append ;
[ N head-slice >A/2 ]
[ N tail-slice >A/2 ] bi cord-append ;
\ A-boa
{ N ndip A/2-boa cord-append } { A/2-boa } >quotation prefix >quotation

View File

@ -226,7 +226,9 @@ M: object pprint-object ( obj -- )
M: object pprint* pprint-object ;
M: vector pprint* pprint-object ;
M: byte-vector pprint* pprint-object ;
M: hashtable pprint* pprint-object ;
M: hashtable pprint*
nesting-limit inc
[ pprint-object ] [ nesting-limit dec ] [ ] cleanup ;
M: curry pprint* pprint-object ;
M: compose pprint* pprint-object ;
M: hash-set pprint* pprint-object ;

View File

@ -1,8 +1,8 @@
! Copyright (C) 2008, 2010 Slava Pestov, Joe Groff.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors assocs sequences sorting binary-search fry math
math.order arrays classes combinators kernel functors math.functions
math.vectors ;
math.order arrays classes combinators kernel functors locals
math.functions math.vectors ;
IN: sequences.cords
MIXIN: cord
@ -47,57 +47,62 @@ M: T cord-append
[ [ head>> ] dip call ]
[ [ tail>> ] dip call ] 2bi cord-append ; inline
: cord-2map ( cord cord quot -- cord' )
[ [ [ head>> ] bi@ ] dip call ]
[ [ [ tail>> ] bi@ ] dip call ] 3bi cord-append ; inline
:: cord-2map ( cord-a cord-b quot fallback -- cord' )
cord-a cord-b 2dup [ cord? ] both? [
[ [ head>> ] bi@ quot call ]
[ [ tail>> ] bi@ quot call ] 2bi cord-append
] [ fallback call ] if ; inline
: cord-both ( cord quot -- h t )
[ [ head>> ] [ tail>> ] bi ] dip bi@ ; inline
: cord-2both ( cord cord quot -- h t )
[ [ [ head>> ] bi@ ] dip call ]
[ [ [ tail>> ] bi@ ] dip call ] 3bi ; inline
:: cord-2both ( cord-a cord-b quot combine fallback -- result )
cord-a cord-b 2dup [ cord? ] both? [
[ [ head>> ] bi@ quot call ]
[ [ tail>> ] bi@ quot call ] 2bi combine call
] [ fallback call ] if ; inline
<PRIVATE
: split-shuffle ( shuf -- sh uf )
dup length 2 /i cut* ; foldable
PRIVATE>
M: cord v+ [ v+ ] cord-2map ; inline
M: cord v- [ v- ] cord-2map ; inline
M: cord v+ [ v+ ] [ call-next-method ] cord-2map ; inline
M: cord v- [ v- ] [ call-next-method ] cord-2map ; inline
M: cord vneg [ vneg ] cord-map ; inline
M: cord v+- [ v+- ] cord-2map ; inline
M: cord vs+ [ vs+ ] cord-2map ; inline
M: cord vs- [ vs- ] cord-2map ; inline
M: cord vs* [ vs* ] cord-2map ; inline
M: cord v* [ v* ] cord-2map ; inline
M: cord v/ [ v/ ] cord-2map ; inline
M: cord vmin [ vmin ] cord-2map ; inline
M: cord vmax [ vmax ] cord-2map ; inline
M: cord v. [ v. ] cord-2both + ; inline
M: cord v+- [ v+- ] [ call-next-method ] cord-2map ; inline
M: cord vs+ [ vs+ ] [ call-next-method ] cord-2map ; inline
M: cord vs- [ vs- ] [ call-next-method ] cord-2map ; inline
M: cord vs* [ vs* ] [ call-next-method ] cord-2map ; inline
M: cord v* [ v* ] [ call-next-method ] cord-2map ; inline
M: cord v/ [ v/ ] [ call-next-method ] cord-2map ; inline
M: cord vmin [ vmin ] [ call-next-method ] cord-2map ; inline
M: cord vmax [ vmax ] [ call-next-method ] cord-2map ; inline
M: cord v.
[ v. ] [ + ] [ call-next-method ] cord-2both ; inline
M: cord vsqrt [ vsqrt ] cord-map ; inline
M: cord sum [ sum ] cord-both + ; inline
M: cord vabs [ vabs ] cord-map ; inline
M: cord vbitand [ vbitand ] cord-2map ; inline
M: cord vbitandn [ vbitandn ] cord-2map ; inline
M: cord vbitor [ vbitor ] cord-2map ; inline
M: cord vbitxor [ vbitxor ] cord-2map ; inline
M: cord vbitand [ vbitand ] [ call-next-method ] cord-2map ; inline
M: cord vbitandn [ vbitandn ] [ call-next-method ] cord-2map ; inline
M: cord vbitor [ vbitor ] [ call-next-method ] cord-2map ; inline
M: cord vbitxor [ vbitxor ] [ call-next-method ] cord-2map ; inline
M: cord vbitnot [ vbitnot ] cord-map ; inline
M: cord vand [ vand ] cord-2map ; inline
M: cord vandn [ vandn ] cord-2map ; inline
M: cord vor [ vor ] cord-2map ; inline
M: cord vxor [ vxor ] cord-2map ; inline
M: cord vand [ vand ] [ call-next-method ] cord-2map ; inline
M: cord vandn [ vandn ] [ call-next-method ] cord-2map ; inline
M: cord vor [ vor ] [ call-next-method ] cord-2map ; inline
M: cord vxor [ vxor ] [ call-next-method ] cord-2map ; inline
M: cord vnot [ vnot ] cord-map ; inline
M: cord vlshift '[ _ vlshift ] cord-map ; inline
M: cord vrshift '[ _ vrshift ] cord-map ; inline
M: cord (vmerge-head) [ head>> ] bi@ (vmerge) cord-append ; inline
M: cord (vmerge-tail) [ tail>> ] bi@ (vmerge) cord-append ; inline
M: cord v<= [ v<= ] cord-2map ; inline
M: cord v< [ v< ] cord-2map ; inline
M: cord v= [ v= ] cord-2map ; inline
M: cord v> [ v> ] cord-2map ; inline
M: cord v>= [ v>= ] cord-2map ; inline
M: cord vunordered? [ vunordered? ] cord-2map ; inline
M: cord v<= [ v<= ] [ call-next-method ] cord-2map ; inline
M: cord v< [ v< ] [ call-next-method ] cord-2map ; inline
M: cord v= [ v= ] [ call-next-method ] cord-2map ; inline
M: cord v> [ v> ] [ call-next-method ] cord-2map ; inline
M: cord v>= [ v>= ] [ call-next-method ] cord-2map ; inline
M: cord vunordered? [ vunordered? ] [ call-next-method ] cord-2map ; inline
M: cord vany? [ vany? ] cord-both or ; inline
M: cord vall? [ vall? ] cord-both and ; inline
M: cord vnone? [ vnone? ] cord-both and ; inline

View File

@ -2,8 +2,7 @@ IN: tools.disassembler.udis.tests
USING: tools.disassembler.udis tools.test alien.c-types system combinators kernel ;
{
{ [ os linux? cpu x86.64? and ] [ [ 656 ] [ ud heap-size ] unit-test ] }
{ [ os macosx? cpu x86.32? and ] [ [ 592 ] [ ud heap-size ] unit-test ] }
{ [ os macosx? cpu x86.64? and ] [ [ 656 ] [ ud heap-size ] unit-test ] }
{ [ cpu x86.32? ] [ [ 604 ] [ ud heap-size ] unit-test ] }
{ [ cpu x86.64? ] [ [ 672 ] [ ud heap-size ] unit-test ] }
[ ]
} cond

View File

@ -67,7 +67,11 @@ STRUCT: ud
{ c3 uchar }
{ inp_cache uchar[256] }
{ inp_sess uchar[64] }
{ itab_entry void* } ;
{ have_modrm uchar }
{ modrm uchar }
{ user_opaque_data void* }
{ itab_entry void* }
{ le void* } ;
FUNCTION: void ud_translate_intel ( ud* u ) ;
FUNCTION: void ud_translate_att ( ud* u ) ;

View File

@ -1,4 +1,5 @@
USING: definitions kernel locals.definitions see see.private typed words ;
USING: definitions kernel locals.definitions see see.private typed words
summary make accessors classes ;
IN: typed.prettyprint
PREDICATE: typed-lambda-word < lambda-word "typed-word" word-prop ;
@ -9,3 +10,24 @@ M: typed-lambda-word definer drop \ TYPED:: \ ; ;
M: typed-word definition "typed-def" word-prop ;
M: typed-word declarations. "typed-word" word-prop declarations. ;
M: input-mismatch-error summary
[
"Typed word “" %
dup word>> name>> %
"” expected input value of type " %
dup expected-type>> name>> %
" but got " %
dup value>> class name>> %
drop
] "" make ;
M: output-mismatch-error summary
[
"Typed word “" %
dup word>> name>> %
"” expected to output value of type " %
dup expected-type>> name>> %
" but gave " %
dup value>> class name>> %
drop
] "" make ;

View File

@ -1,6 +1,6 @@
USING: accessors effects eval kernel layouts math namespaces
quotations tools.test typed words words.symbol
compiler.tree.debugger prettyprint definitions compiler.units ;
quotations tools.test typed words words.symbol combinators.short-circuit
compiler.tree.debugger prettyprint definitions compiler.units sequences ;
IN: typed.tests
TYPED: f+ ( a: float b: float -- c: float )
@ -24,14 +24,17 @@ TYPED: dee ( x: tweedle-dee -- y )
TYPED: dum ( x: tweedle-dum -- y )
drop \ tweedle-dum ;
[ \ tweedle-dum new dee ] [ input-mismatch-error? ] must-fail-with
[ \ tweedle-dee new dum ] [ input-mismatch-error? ] must-fail-with
[ \ tweedle-dum new dee ]
[ { [ input-mismatch-error? ] [ expected-type>> tweedle-dee = ] [ value>> tweedle-dum? ] } 1&& ] must-fail-with
[ \ tweedle-dee new dum ]
[ { [ input-mismatch-error? ] [ expected-type>> tweedle-dum = ] [ value>> tweedle-dee? ] } 1&& ] must-fail-with
TYPED: dumdum ( x -- y: tweedle-dum )
drop \ tweedle-dee new ;
[ f dumdum ] [ output-mismatch-error? ] must-fail-with
[ f dumdum ]
[ { [ output-mismatch-error? ] [ expected-type>> tweedle-dum = ] [ value>> tweedle-dee? ] } 1&& ] must-fail-with
TYPED:: f+locals ( a: float b: float -- c: float )
a b + ;

View File

@ -7,7 +7,7 @@ locals.parser macros stack-checker.dependencies ;
FROM: classes.tuple.private => tuple-layout ;
IN: typed
ERROR: type-mismatch-error word expected-types ;
ERROR: type-mismatch-error value expected-type word expected-types ;
ERROR: input-mismatch-error < type-mismatch-error ;
ERROR: output-mismatch-error < type-mismatch-error ;
@ -28,9 +28,6 @@ PREDICATE: typed-word < word "typed-word" word-prop >boolean ;
: typed-stack-effect? ( effect -- ? )
[ object = ] all? not ;
: input-mismatch-quot ( word types -- quot )
[ input-mismatch-error ] 2curry ;
: depends-on-unboxing ( class -- )
[ dup tuple-layout depends-on-tuple-layout ]
[ depends-on-final ]
@ -47,7 +44,7 @@ PREDICATE: typed-word < word "typed-word" word-prop >boolean ;
:: unboxer ( error-quot word types type -- quot )
type "coercer" word-prop [ ] or
[ dup type instance? [ word types error-quot call ] unless ]
type type word types error-quot '[ dup _ instance? [ _ _ _ @ ] unless ]
type (unboxer)
compose compose ;

View File

@ -11,7 +11,7 @@ $nl
$nl
"The second way is to create a configuration file. You can list additional vocabulary roots in a file that Factor reads at startup:"
{ $subsections "factor-roots" }
"Finally, you can add vocabulary roots dynamically using a word:"
"Finally, you can add vocabulary roots by calling a word from your " { $snippet "factor-rc" } " file (see " { $link "factor-rc" } "):"
{ $subsections add-vocab-root } ;
ARTICLE: "vocabs.roots" "Vocabulary roots"

View File

@ -0,0 +1 @@
Joe Groff

View File

@ -0,0 +1,45 @@
! (c)2010 Joe Groff bsd license
USING: accessors alien alien.c-types alien.handles alien.syntax
destructors kernel math tools.test ;
IN: alien.handles.tests
TUPLE: thingy { x integer } ;
C: <thingy> thingy
CALLBACK: int thingy-callback ( uint thingy-handle ) ;
CALLBACK: int thingy-ptr-callback ( void* thingy-handle ) ;
: test-thingy-callback ( -- alien )
[ alien-handle> x>> 1 + ] thingy-callback ;
: test-thingy-ptr-callback ( -- alien )
[ alien-handle-ptr> x>> 1 + ] thingy-ptr-callback ;
: invoke-test-thingy-callback ( thingy -- n )
test-thingy-callback int { uint } cdecl alien-indirect ;
: invoke-test-thingy-ptr-callback ( thingy -- n )
test-thingy-ptr-callback int { void* } cdecl alien-indirect ;
[ t f ] [
[ 5 <thingy> <alien-handle> &release-alien-handle [ alien-handle? ] keep ] with-destructors
alien-handle?
] unit-test
[ t f ] [
[ 5 <thingy> <alien-handle-ptr> &release-alien-handle-ptr [ alien-handle-ptr? ] keep ] with-destructors
alien-handle-ptr?
] unit-test
[ 6 ] [
[
5 <thingy> <alien-handle> &release-alien-handle
invoke-test-thingy-callback
] with-destructors
] unit-test
[ 6 ] [
[
5 <thingy> <alien-handle-ptr> &release-alien-handle-ptr
invoke-test-thingy-ptr-callback
] with-destructors
] unit-test

View File

@ -0,0 +1,49 @@
! (c)2010 Joe Groff bsd license
USING: alien alien.destructors assocs kernel math math.bitwise
namespaces ;
IN: alien.handles
<PRIVATE
SYMBOLS: alien-handle-counter alien-handles ;
alien-handle-counter [ 0 ] initialize
alien-handles [ H{ } clone ] initialize
: biggest-handle ( -- n )
-1 32 bits ; inline
: (next-handle) ( -- n )
alien-handle-counter [ 1 + biggest-handle bitand dup ] change-global ; inline
: next-handle ( -- n )
[ (next-handle) dup alien-handles get-global key? ] [ drop ] while ;
PRIVATE>
: <alien-handle> ( object -- int )
next-handle [ alien-handles get-global set-at ] keep ; inline
: alien-handle> ( int -- object )
alien-handles get-global at ; inline
: alien-handle? ( int -- ? )
alien-handles get-global key? >boolean ; inline
: release-alien-handle ( int -- )
alien-handles get-global delete-at ; inline
DESTRUCTOR: release-alien-handle
: <alien-handle-ptr> ( object -- void* )
<alien-handle> <alien> ; inline
: alien-handle-ptr> ( void* -- object )
alien-address alien-handle> ; inline
: alien-handle-ptr? ( alien -- ? )
alien-address alien-handle? ; inline
: release-alien-handle-ptr ( alien -- )
alien-address release-alien-handle ; inline
DESTRUCTOR: release-alien-handle-ptr

View File

@ -0,0 +1 @@
Generate integer handle values to allow Factor object references to be passed through the FFI

View File

@ -19,6 +19,16 @@ TUPLE: oid { a initial: 0 } { b initial: 0 } ;
TUPLE: dbref ref id db ;
TUPLE: mongo-timestamp incr seconds ;
: <mongo-timestamp> ( incr seconds -- mongo-timestamp )
mongo-timestamp boa ;
TUPLE: mongo-scoped-code code object ;
: <mongo-scoped-code> ( code object -- mongo-scoped-code )
mongo-scoped-code boa ;
CONSTRUCTOR: dbref ( ref id -- dbref ) ;
: dbref>assoc ( dbref -- assoc )
@ -47,30 +57,31 @@ TUPLE: mdbregexp { regexp string } { options string } ;
CONSTANT: MDB_OID_FIELD "_id"
CONSTANT: MDB_META_FIELD "_mfd"
CONSTANT: T_EOO 0
CONSTANT: T_Double 1
CONSTANT: T_Integer 16
CONSTANT: T_Boolean 8
CONSTANT: T_String 2
CONSTANT: T_Object 3
CONSTANT: T_Array 4
CONSTANT: T_Binary 5
CONSTANT: T_Undefined 6
CONSTANT: T_OID 7
CONSTANT: T_Date 9
CONSTANT: T_NULL 10
CONSTANT: T_Regexp 11
CONSTANT: T_DBRef 12
CONSTANT: T_Code 13
CONSTANT: T_ScopedCode 17
CONSTANT: T_Symbol 14
CONSTANT: T_JSTypeMax 16
CONSTANT: T_MaxKey 127
CONSTANT: T_Binary_Function 1
CONSTANT: T_Binary_Bytes 2
CONSTANT: T_Binary_UUID 3
CONSTANT: T_Binary_MD5 5
CONSTANT: T_Binary_Custom 128
CONSTANT: T_EOO 0
CONSTANT: T_Double HEX: 1
CONSTANT: T_String HEX: 2
CONSTANT: T_Object HEX: 3
CONSTANT: T_Array HEX: 4
CONSTANT: T_Binary HEX: 5
CONSTANT: T_Undefined HEX: 6
CONSTANT: T_OID HEX: 7
CONSTANT: T_Boolean HEX: 8
CONSTANT: T_Date HEX: 9
CONSTANT: T_NULL HEX: A
CONSTANT: T_Regexp HEX: B
CONSTANT: T_DBRef HEX: C
CONSTANT: T_Code HEX: D
CONSTANT: T_Symbol HEX: E
CONSTANT: T_ScopedCode HEX: F
CONSTANT: T_Integer HEX: 10
CONSTANT: T_Timestamp HEX: 11
CONSTANT: T_Integer64 HEX: 12
CONSTANT: T_MinKey HEX: FF
CONSTANT: T_MaxKey HEX: 7F
CONSTANT: T_Binary_Function HEX: 1
CONSTANT: T_Binary_Bytes HEX: 2
CONSTANT: T_Binary_UUID HEX: 3
CONSTANT: T_Binary_MD5 HEX: 5
CONSTANT: T_Binary_Custom HEX: 80

View File

@ -10,65 +10,46 @@ FROM: typed => TYPED: ;
IN: bson.reader
SYMBOL: state
DEFER: stream>assoc
<PRIVATE
TUPLE: element { type integer } name ;
DEFER: read-elements
TUPLE: state
{ size initial: -1 }
{ exemplar assoc }
result
{ scope vector }
{ elements vector } ;
TYPED: (prepare-elements) ( -- elements-vector: vector )
V{ } clone [ T_Object "" element boa swap push ] [ ] bi ; inline
: <state> ( exemplar -- state )
[ state new ] dip
{
[ clone >>exemplar ]
[ clone >>result ]
[ V{ } clone [ push ] keep >>scope ]
} cleave
(prepare-elements) >>elements ;
TYPED: get-state ( -- state: state )
state get ; inline
TYPED: read-int32 ( -- int32: integer )
: read-int32 ( -- int32 )
4 read signed-le> ; inline
TYPED: read-longlong ( -- longlong: integer )
: read-longlong ( -- longlong )
8 read signed-le> ; inline
TYPED: read-double ( -- double: float )
: read-double ( -- double )
8 read le> bits>double ; inline
TYPED: read-byte-raw ( -- byte-raw: byte-array )
: read-byte-raw ( -- byte-raw )
1 read ; inline
TYPED: read-byte ( -- byte: integer )
: read-byte ( -- byte )
read-byte-raw first ; inline
TYPED: read-cstring ( -- string: string )
: read-cstring ( -- string )
"\0" read-until drop >string ; inline
TYPED: read-sized-string ( length: integer -- string: string )
: read-sized-string ( length -- string )
read 1 head-slice* >string ; inline
TYPED: push-element ( type: integer name: string state: state -- )
[ element boa ] dip elements>> push ; inline
: read-timestamp ( -- timestamp )
8 read [ 4 head signed-le> ] [ 4 tail signed-le> ] bi <mongo-timestamp> ;
TYPED: pop-element ( state: state -- element: element )
elements>> pop ; inline
: object-result ( quot -- object )
[
state get clone
[ clear-assoc ] [ ] [ ] tri state
] dip with-variable ; inline
TYPED: peek-scope ( state: state -- ht )
scope>> last ; inline
: bson-object-data-read ( -- object )
read-int32 drop get-state
[ exemplar>> clone dup ] [ scope>> ] bi push ; inline
: bson-object-data-read ( -- )
read-int32 drop read-elements ; inline recursive
: bson-binary-read ( -- binary )
read-int32 read-byte
@ -86,68 +67,35 @@ TYPED: bson-regexp-read ( -- mdbregexp: mdbregexp )
TYPED: bson-oid-read ( -- oid: oid )
read-longlong read-int32 oid boa ; inline
TYPED: element-data-read ( type: integer -- object )
{
{ T_OID [ bson-oid-read ] }
{ T_String [ read-int32 read-sized-string ] }
{ T_Integer [ read-int32 ] }
{ T_Binary [ bson-binary-read ] }
{ T_Object [ bson-object-data-read ] }
{ T_Array [ bson-object-data-read ] }
{ T_Double [ read-double ] }
{ T_Boolean [ read-byte 1 = ] }
{ T_Date [ read-longlong millis>timestamp ] }
{ T_Regexp [ bson-regexp-read ] }
{ T_NULL [ f ] }
} case ; inline
TYPED: bson-array? ( type: integer -- ?: boolean )
T_Array = ; inline
TYPED: bson-object? ( type: integer -- ?: boolean )
T_Object = ; inline
: check-object ( assoc -- object )
dup dbref-assoc? [ assoc>dbref ] when ; inline
TYPED: fix-result ( assoc type: integer -- result )
TYPED: element-data-read ( type: integer -- object )
{
{ T_Array [ values ] }
{ T_Object [ check-object ] }
} case ; inline
{ T_OID [ bson-oid-read ] }
{ T_String [ read-int32 read-sized-string ] }
{ T_Integer [ read-int32 ] }
{ T_Integer64 [ read-longlong ] }
{ T_Binary [ bson-binary-read ] }
{ T_Object [ [ bson-object-data-read ] object-result check-object ] }
{ T_Array [ [ bson-object-data-read ] object-result values ] }
{ T_Double [ read-double ] }
{ T_Boolean [ read-byte 1 = ] }
{ T_Date [ read-longlong millis>timestamp ] }
{ T_Regexp [ bson-regexp-read ] }
{ T_Timestamp [ read-timestamp ] }
{ T_Code [ read-int32 read-sized-string ] }
{ T_ScopedCode [ read-int32 drop read-cstring H{ } clone stream>assoc <mongo-scoped-code> ] }
{ T_NULL [ f ] }
} case ; inline recursive
TYPED: end-element ( type: integer -- )
{ [ bson-object? ] [ bson-array? ] } 1||
[ get-state pop-element drop ] unless ; inline
TYPED: (>state<) ( -- state: state scope: vector element: element )
get-state [ ] [ scope>> ] [ pop-element ] tri ; inline
TYPED: (prepare-result) ( scope: vector element: element -- result )
[ pop ] [ type>> ] bi* fix-result ; inline
: bson-eoo-element-read ( -- cont?: boolean )
(>state<)
[ (prepare-result) ] [ ] [ drop empty? ] 2tri
[ 2drop >>result drop f ]
[ swap [ name>> ] [ last ] bi* set-at drop t ] if ; inline
TYPED: (prepare-object) ( type: integer -- object )
[ element-data-read ] [ end-element ] bi ; inline
:: (read-object) ( type name state -- )
state peek-scope :> scope
type (prepare-object) name scope set-at ; inline
TYPED: bson-not-eoo-element-read ( type: integer -- cont?: boolean )
read-cstring get-state
[ push-element ]
[ (read-object) t ] 3bi ; inline
TYPED: (read-object) ( type: integer name: string -- )
[ element-data-read ] dip state get set-at ; inline recursive
TYPED: (element-read) ( type: integer -- cont?: boolean )
dup T_EOO >
[ bson-not-eoo-element-read ]
[ drop bson-eoo-element-read ] if ; inline
[ read-cstring (read-object) t ]
[ drop f ] if ; inline recursive
: read-elements ( -- )
read-byte (element-read)
@ -156,6 +104,6 @@ TYPED: (element-read) ( type: integer -- cont?: boolean )
PRIVATE>
: stream>assoc ( exemplar -- assoc )
<state> read-int32 >>size
[ state [ read-elements ] with-variable ]
[ result>> ] bi ;
clone [
state [ bson-object-data-read ] with-variable
] keep ;

View File

@ -1,7 +1,7 @@
! Copyright (C) 2005 Alex Chapman.
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types alien.libraries alien.syntax kernel
sequences words system combinators opengl.gl ;
sequences words system combinators opengl.gl alien.destructors ;
IN: opengl.glu
<<
@ -267,5 +267,21 @@ FUNCTION: GLint gluUnProject ( GLdouble winX, GLdouble winY, GLdouble winZ, GLdo
! FUNCTION: GLboolean gluCheckExtension ( GLubyte* extName, GLubyte* extString ) ;
! FUNCTION: GLint gluUnProject4 ( GLdouble winX, GLdouble winY, GLdouble winZ, GLdouble clipW, GLdouble* model, GLdouble* proj, GLint* view, GLdouble nearVal, GLdouble farVal, GLdouble* objX, GLdouble* objY, GLdouble* objZ, GLdouble* objW ) ;
DESTRUCTOR: gluDeleteNurbsRenderer
DESTRUCTOR: gluDeleteQuadric
DESTRUCTOR: gluDeleteTess
CALLBACK: void GLUtessBeginCallback ( GLenum type ) ;
CALLBACK: void GLUtessBeginDataCallback ( GLenum type, void* data ) ;
CALLBACK: void GLUtessEdgeFlagCallback ( GLboolean flag ) ;
CALLBACK: void GLUtessEdgeFlagDataCallback ( GLboolean flag, void* data ) ;
CALLBACK: void GLUtessVertexCallback ( void* vertex_data ) ;
CALLBACK: void GLUtessVertexDataCallback ( void* vertex_data, void* data ) ;
CALLBACK: void GLUtessEndCallback ( ) ;
CALLBACK: void GLUtessEndDataCallback ( void* data ) ;
CALLBACK: void GLUtessCombineDataCallback ( GLdouble* coords, void** vertex_data, GLfloat* weight, void** out_data, void* data ) ;
CALLBACK: void GLUtessErrorCallback ( GLenum errno ) ;
CALLBACK: void GLUtessErrorDataCallback ( GLenum errno, void* data ) ;
: gl-look-at ( eye focus up -- )
[ first3 ] tri@ gluLookAt ;

View File

@ -1,7 +1,7 @@
! Copyright (C) 2009 Elie Chaftari.
! See http://factorcode.org/license.txt for BSD license.
USING: concurrency.promises namespaces kernel pop3 pop3.server
sequences tools.test accessors ;
sequences tools.test accessors calendar ;
IN: pop3.tests
FROM: pop3 => count delete ;
@ -12,7 +12,7 @@ FROM: pop3 => count delete ;
[ ] [
<pop3-account>
"127.0.0.1" >>host
"p1" get ?promise >>port
"p1" get 5 seconds ?promise-timeout >>port
connect
] unit-test
[ ] [ "username@host.com" >user ] unit-test
@ -59,7 +59,7 @@ FROM: pop3 => count delete ;
[ ] [
<pop3-account>
"127.0.0.1" >>host
"p2" get ?promise >>port
"p2" get 5 seconds ?promise-timeout >>port
"username@host.com" >>user
"password" >>pwd
connect

View File

@ -59,6 +59,7 @@
(ratio constant "ratios")
(declaration keyword "declaration words")
(ebnf-form constant "EBNF: ... ;EBNF form")
(error-form warning "ERROR: ... ; form")
(parsing-word keyword "parsing words")
(postpone-body comment "postponed form")
(setter-word function-name "setter words (>>foo)")
@ -101,6 +102,9 @@
(,fuel-syntax--brace-words-regex 1 'factor-font-lock-parsing-word)
(,fuel-syntax--alien-function-regex (1 'factor-font-lock-type-name)
(2 'factor-font-lock-word))
(,fuel-syntax--alien-function-alias-regex (1 'factor-font-lock-word)
(2 'factor-font-lock-type-name)
(3 'factor-font-lock-word))
(,fuel-syntax--alien-callback-regex (1 'factor-font-lock-type-name)
(2 'factor-font-lock-word))
(,fuel-syntax--vocab-ref-regexp 2 'factor-font-lock-vocabulary-name)
@ -111,6 +115,11 @@
(,fuel-syntax--typedef-regex (1 'factor-font-lock-type-name)
(2 'factor-font-lock-type-name)
(3 'factor-font-lock-invalid-syntax nil t))
(,fuel-syntax--c-global-regex (1 'factor-font-lock-type-name)
(2 'factor-font-lock-word)
(3 'factor-font-lock-invalid-syntax nil t))
(,fuel-syntax--c-type-regex (1 'factor-font-lock-type-name)
(2 'factor-font-lock-invalid-syntax nil t))
(,fuel-syntax--rename-regex (1 'factor-font-lock-word)
(2 'factor-font-lock-vocabulary-name)
(3 'factor-font-lock-word)
@ -124,6 +133,7 @@
(,fuel-syntax--float-regex . 'factor-font-lock-number)
(,fuel-syntax--ratio-regex . 'factor-font-lock-ratio)
(,fuel-syntax--type-definition-regex 2 'factor-font-lock-type-name)
(,fuel-syntax--error-regex 2 'factor-font-lock-error-form)
(,fuel-syntax--method-definition-regex (1 'factor-font-lock-type-name)
(2 'factor-font-lock-word))
(,fuel-syntax--before-definition-regex (1 'factor-font-lock-type-name)

View File

@ -47,10 +47,10 @@
'(":" "::" ";" "&:" "<<" "<PRIVATE" ">>"
"ABOUT:" "AFTER:" "ALIAS:" "ALIEN:" "ARTICLE:"
"B" "BEFORE:" "BIN:"
"C:" "CALLBACK:" "ENUM:" "C-TYPE:" "CHAR:" "COM-INTERFACE:" "CONSTANT:" "CONSULT:" "call-next-method"
"DEFER:"
"EBNF:" ";EBNF" "ERROR:" "EXCLUDE:"
"f" "FORGET:" "FROM:" "FUNCTION:"
"C:" "CALLBACK:" "C-GLOBAL:" "C-TYPE:" "CHAR:" "COM-INTERFACE:" "CONSTANT:" "CONSULT:" "call-next-method"
"DEFER:" "DESTRUCTOR:"
"EBNF:" ";EBNF" "ENUM:" "ERROR:" "EXCLUDE:"
"f" "FORGET:" "FROM:" "FUNCTION:" "FUNCTION-ALIAS:"
"GAME:" "GENERIC#" "GENERIC:"
"GLSL-SHADER:" "GLSL-PROGRAM:"
"HELP:" "HEX:" "HOOK:"
@ -135,6 +135,9 @@
(fuel-syntax--second-word-regex
'("C-STRUCT:" "C-UNION:" "COM-INTERFACE:" "MIXIN:" "TUPLE:" "SINGLETON:" "SPECIALIZED-ARRAY:" "STRUCT:" "UNION:" "UNION-STRUCT:")))
(defconst fuel-syntax--error-regex
(fuel-syntax--second-word-regex '("ERROR:")))
(defconst fuel-syntax--tuple-decl-regex
"^TUPLE: +\\([^ \n]+\\) +< +\\([^ \n]+\\)\\_>")
@ -158,15 +161,19 @@
(defconst fuel-syntax--sub-vocab-regex "^<\\([^ \n]+\\) *$")
(defconst fuel-syntax--alien-function-regex
"\\_<FUNCTION: \\(\\w+\\) \\(\\w+\\)")
"\\_<FUNCTION: +\\(\\w+\\)[\n ]+\\(\\w+\\)")
(defconst fuel-syntax--alien-function-alias-regex
"\\_<FUNCTION-ALIAS: +\\(\\w+\\)[\n ]+\\(\\w+\\)[\n ]+\\(\\w+\\)")
(defconst fuel-syntax--alien-callback-regex
"\\_<CALLBACK: \\(\\w+\\) \\(\\w+\\)")
"\\_<CALLBACK: +\\(\\w+\\) +\\(\\w+\\)")
(defconst fuel-syntax--indent-def-starts '("" ":"
"AFTER" "BEFORE"
"ENUM" "COM-INTERFACE" "CONSULT"
"FROM" "FUNCTION:"
"COM-INTERFACE" "CONSULT"
"ENUM" "ERROR"
"FROM" "FUNCTION:" "FUNCTION-ALIAS:"
"INTERSECTION:"
"M" "M:" "MACRO" "MACRO:"
"MEMO" "MEMO:" "METHOD"
@ -197,10 +204,10 @@
(defconst fuel-syntax--single-liner-regex
(regexp-opt '("ABOUT:"
"ALIAS:"
"CONSTANT:" "C:" "C-TYPE:"
"DEFER:"
"CONSTANT:" "C:" "C-GLOBAL:" "C-TYPE:"
"DEFER:" "DESTRUCTOR:"
"FORGET:"
"GAME:" "GENERIC:" "GENERIC#" "GLSL-PROGRAM:"
"GAME:" "GENERIC:" "GENERIC#" "GLSL-PROGRAM:"
"HEX:" "HOOK:"
"IN:" "INSTANCE:"
"LIBRARY:"
@ -242,6 +249,12 @@
(defconst fuel-syntax--typedef-regex
"\\_<TYPEDEF: +\\(\\w+\\) +\\(\\w+\\)\\( .*\\)?$")
(defconst fuel-syntax--c-global-regex
"\\_<C-GLOBAL: +\\(\\w+\\) +\\(\\w+\\)\\( .*\\)?$")
(defconst fuel-syntax--c-type-regex
"\\_<C-TYPE: +\\(\\w+\\)\\( .*\\)?$")
(defconst fuel-syntax--rename-regex
"\\_<RENAME: +\\(\\w+\\) +\\(\\w+\\) +=> +\\(\\w+\\)\\( .*\\)?$")

View File

@ -108,7 +108,25 @@ stack_frame *factor_vm::frame_successor(stack_frame *frame)
return (stack_frame *)((cell)frame - frame->size);
}
/* Allocates memory */
cell factor_vm::frame_offset(stack_frame *frame)
{
char *entry_point = (char *)frame_code(frame)->entry_point();
char *return_address = (char *)FRAME_RETURN_ADDRESS(frame,this);
if(return_address)
return return_address - entry_point;
else
return (cell)-1;
}
void factor_vm::set_frame_offset(stack_frame *frame, cell offset)
{
char *entry_point = (char *)frame_code(frame)->entry_point();
if(offset == (cell)-1)
FRAME_RETURN_ADDRESS(frame,this) = NULL;
else
FRAME_RETURN_ADDRESS(frame,this) = entry_point + offset;
}
cell factor_vm::frame_scan(stack_frame *frame)
{
switch(frame_type(frame))
@ -120,13 +138,7 @@ cell factor_vm::frame_scan(stack_frame *frame)
obj = obj.as<word>()->def;
if(obj.type_p(QUOTATION_TYPE))
{
char *return_addr = (char *)FRAME_RETURN_ADDRESS(frame,this);
char *quot_entry_point = (char *)frame_code(frame)->entry_point();
return tag_fixnum(quot_code_offset_to_scan(
obj.value(),(cell)(return_addr - quot_entry_point)));
}
return tag_fixnum(quot_code_offset_to_scan(obj.value(),frame_offset(frame)));
else
return false_object;
}
@ -138,11 +150,6 @@ cell factor_vm::frame_scan(stack_frame *frame)
}
}
cell factor_vm::frame_offset(stack_frame *frame)
{
return (cell)FRAME_RETURN_ADDRESS(frame,this) - (cell)frame_code(frame)->entry_point();
}
struct stack_frame_accumulator {
factor_vm *parent;
growable_array frames;
@ -209,9 +216,9 @@ void factor_vm::primitive_set_innermost_stack_frame_quot()
jit_compile_quot(quot.value(),true);
stack_frame *inner = innermost_stack_frame(callstack.untagged());
cell offset = (char *)FRAME_RETURN_ADDRESS(inner,this) - (char *)inner->entry_point;
cell offset = frame_offset(inner);
inner->entry_point = quot->entry_point;
FRAME_RETURN_ADDRESS(inner,this) = (char *)quot->entry_point + offset;
set_frame_offset(inner,offset);
}
void factor_vm::primitive_callstack_bounds()

View File

@ -42,13 +42,10 @@ struct call_frame_code_block_visitor {
void operator()(stack_frame *frame)
{
code_block *old_block = parent->frame_code(frame);
cell offset = (char *)FRAME_RETURN_ADDRESS(frame,parent) - (char *)old_block;
const code_block *new_block = fixup.fixup_code(old_block);
frame->entry_point = new_block->entry_point();
FRAME_RETURN_ADDRESS(frame,parent) = (char *)new_block + offset;
cell offset = parent->frame_offset(frame);
code_block *compiled = fixup.fixup_code(parent->frame_code(frame));
frame->entry_point = compiled->entry_point();
parent->set_frame_offset(frame,offset);
}
};

View File

@ -43,6 +43,8 @@ template<typename TargetGeneration, typename Policy> struct gc_workhorse : no_fi
object *fixup_data(object *obj)
{
parent->check_data_pointer(obj);
if(!policy.should_copy_p(obj))
{
policy.visited_object(obj);

View File

@ -65,7 +65,12 @@ void context::scrub_stacks(gc_info *info, cell index)
for(cell loc = 0; loc < info->scrub_d_count; loc++)
{
if(bitmap_p(bitmap,base + loc))
{
#ifdef DEBUG_GC_MAPS
std::cout << "scrubbing datastack location " << loc << std::endl;
#endif
((cell *)datastack)[-loc] = 0;
}
}
}
@ -75,7 +80,12 @@ void context::scrub_stacks(gc_info *info, cell index)
for(cell loc = 0; loc < info->scrub_r_count; loc++)
{
if(bitmap_p(bitmap,base + loc))
{
#ifdef DEBUG_GC_MAPS
std::cout << "scrubbing retainstack location " << loc << std::endl;
#endif
((cell *)retainstack)[-loc] = 0;
}
}
}
}

View File

@ -164,7 +164,7 @@ template<typename Block, typename Iterator> struct heap_compactor {
{
if(this->state->marked_p(block))
{
*finger = block;
*finger = (Block *)((char *)block + size);
memmove((Block *)address,block,size);
iter(block,(Block *)address,size);
address += size;

View File

@ -207,13 +207,15 @@ struct call_frame_scrubber {
void operator()(stack_frame *frame)
{
const code_block *compiled = parent->frame_code(frame);
cell return_address = parent->frame_offset(frame);
if(return_address == (cell)-1)
return;
code_block *compiled = parent->frame_code(frame);
gc_info *info = compiled->block_gc_info();
cell return_address = parent->frame_offset(frame);
assert(return_address < compiled->size());
int index = info->return_address_index(return_address);
if(index != -1)
ctx->scrub_stacks(info,index);
}

View File

@ -284,22 +284,33 @@ struct call_frame_slot_visitor {
*/
void operator()(stack_frame *frame)
{
const code_block *compiled = visitor->fixup.translate_code(parent->frame_code(frame));
gc_info *info = compiled->block_gc_info();
cell return_address = parent->frame_offset(frame);
if(return_address == (cell)-1)
return;
code_block *compiled = visitor->fixup.translate_code(parent->frame_code(frame));
gc_info *info = compiled->block_gc_info();
assert(return_address < compiled->size());
int index = info->return_address_index(return_address);
if(index == -1)
return;
if(index != -1)
#ifdef DEBUG_GC_MAPS
std::cout << "call frame code block " << compiled << " with offset " << return_address << std::endl;
#endif
u8 *bitmap = info->gc_info_bitmap();
cell base = info->spill_slot_base(index);
cell *stack_pointer = (cell *)(parent->frame_successor(frame) + 1);
for(cell spill_slot = 0; spill_slot < info->gc_root_count; spill_slot++)
{
u8 *bitmap = info->gc_info_bitmap();
cell base = info->spill_slot_base(index);
cell *stack_pointer = (cell *)(parent->frame_successor(frame) + 1);
for(cell spill_slot = 0; spill_slot < info->gc_root_count; spill_slot++)
if(bitmap_p(bitmap,base + spill_slot))
{
if(bitmap_p(bitmap,base + spill_slot))
visitor->visit_handle(&stack_pointer[spill_slot]);
#ifdef DEBUG_GC_MAPS
std::cout << "visiting spill slot " << spill_slot << std::endl;
#endif
visitor->visit_handle(&stack_pointer[spill_slot]);
}
}
}

View File

@ -597,6 +597,7 @@ struct factor_vm
stack_frame *frame_successor(stack_frame *frame);
cell frame_scan(stack_frame *frame);
cell frame_offset(stack_frame *frame);
void set_frame_offset(stack_frame *frame, cell offset);
void primitive_callstack_to_array();
stack_frame *innermost_stack_frame(callstack *stack);
void primitive_innermost_stack_frame_executing();