]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge branch 'master' of git://factorcode.org/git/factor
authorSam Anklesaria <sam@Tintin.local>
Mon, 3 Aug 2009 15:13:27 +0000 (10:13 -0500)
committerSam Anklesaria <sam@Tintin.local>
Mon, 3 Aug 2009 15:13:27 +0000 (10:13 -0500)
145 files changed:
README.txt
basis/alien/fortran/fortran.factor
basis/alien/libraries/libraries.factor
basis/bootstrap/compiler/compiler.factor
basis/bootstrap/compiler/timing/timing.factor [new file with mode: 0644]
basis/checksums/fnv1/authors.txt [new file with mode: 0644]
basis/checksums/fnv1/fnv1-docs.factor [new file with mode: 0644]
basis/checksums/fnv1/fnv1-tests.factor [new file with mode: 0644]
basis/checksums/fnv1/fnv1.factor [new file with mode: 0644]
basis/checksums/fnv1/summary.txt [new file with mode: 0644]
basis/compiler/cfg/branch-splitting/branch-splitting-tests.factor
basis/compiler/cfg/builder/builder.factor
basis/compiler/cfg/copy-prop/copy-prop.factor
basis/compiler/cfg/critical-edges/critical-edges-tests.factor [new file with mode: 0644]
basis/compiler/cfg/critical-edges/critical-edges.factor
basis/compiler/cfg/debugger/debugger.factor
basis/compiler/cfg/def-use/authors.txt [new file with mode: 0644]
basis/compiler/cfg/def-use/def-use-tests.factor [new file with mode: 0644]
basis/compiler/cfg/def-use/def-use.factor
basis/compiler/cfg/dominance/dominance-tests.factor
basis/compiler/cfg/gc-checks/gc-checks-tests.factor [new file with mode: 0644]
basis/compiler/cfg/gc-checks/gc-checks.factor
basis/compiler/cfg/instructions/instructions.factor
basis/compiler/cfg/intrinsics/intrinsics.factor
basis/compiler/cfg/linear-scan/allocation/allocation.factor
basis/compiler/cfg/linear-scan/allocation/spilling/spilling.factor
basis/compiler/cfg/linear-scan/allocation/splitting/splitting.factor
basis/compiler/cfg/linear-scan/debugger/debugger.factor
basis/compiler/cfg/linear-scan/linear-scan-tests.factor
basis/compiler/cfg/linear-scan/live-intervals/live-intervals.factor
basis/compiler/cfg/linear-scan/resolve/resolve-tests.factor
basis/compiler/cfg/linear-scan/resolve/resolve.factor
basis/compiler/cfg/linearization/linearization.factor
basis/compiler/cfg/liveness/liveness-tests.factor
basis/compiler/cfg/liveness/ssa/ssa.factor
basis/compiler/cfg/predecessors/predecessors.factor
basis/compiler/cfg/ssa/construction/construction-tests.factor
basis/compiler/cfg/ssa/construction/tdmsc/tdmsc-tests.factor
basis/compiler/cfg/ssa/cssa/cssa.factor [new file with mode: 0644]
basis/compiler/cfg/ssa/destruction/copies/copies.factor [deleted file]
basis/compiler/cfg/ssa/destruction/destruction.factor
basis/compiler/cfg/ssa/destruction/forest/forest-tests.factor [deleted file]
basis/compiler/cfg/ssa/destruction/forest/forest.factor [deleted file]
basis/compiler/cfg/ssa/destruction/interference/interference.factor [deleted file]
basis/compiler/cfg/ssa/destruction/live-ranges/live-ranges.factor [deleted file]
basis/compiler/cfg/ssa/destruction/process-blocks/process-blocks.factor [deleted file]
basis/compiler/cfg/ssa/destruction/renaming/renaming.factor [deleted file]
basis/compiler/cfg/ssa/destruction/state/state.factor [deleted file]
basis/compiler/cfg/ssa/interference/interference-tests.factor [new file with mode: 0644]
basis/compiler/cfg/ssa/interference/interference.factor [new file with mode: 0644]
basis/compiler/cfg/ssa/interference/live-ranges/live-ranges.factor [new file with mode: 0644]
basis/compiler/cfg/ssa/liveness/liveness-tests.factor [new file with mode: 0644]
basis/compiler/cfg/ssa/liveness/liveness.factor [new file with mode: 0644]
basis/compiler/cfg/stacks/finalize/finalize.factor
basis/compiler/cfg/stacks/global/global.factor
basis/compiler/cfg/stacks/local/local.factor
basis/compiler/cfg/stacks/stacks-tests.factor [new file with mode: 0644]
basis/compiler/cfg/stacks/stacks.factor
basis/compiler/cfg/stacks/uninitialized/uninitialized-tests.factor [new file with mode: 0644]
basis/compiler/cfg/stacks/uninitialized/uninitialized.factor [new file with mode: 0644]
basis/compiler/cfg/two-operand/two-operand-tests.factor
basis/compiler/cfg/two-operand/two-operand.factor
basis/compiler/cfg/utilities/utilities.factor
basis/compiler/cfg/value-numbering/value-numbering-tests.factor
basis/compiler/codegen/codegen.factor
basis/compiler/tests/codegen.factor
basis/compiler/tests/low-level-ir.factor
basis/compiler/tree/propagation/call-effect/call-effect-tests.factor
basis/compiler/tree/propagation/call-effect/call-effect.factor
basis/compiler/tree/propagation/copy/copy.factor
basis/compiler/tree/propagation/inlining/inlining.factor
basis/compiler/utilities/utilities.factor
basis/cpu/architecture/architecture.factor
basis/cpu/ppc/ppc.factor
basis/cpu/x86/32/32.factor
basis/cpu/x86/32/bootstrap.factor
basis/cpu/x86/64/64.factor
basis/cpu/x86/64/bootstrap.factor
basis/cpu/x86/64/unix/bootstrap.factor
basis/cpu/x86/64/unix/unix.factor
basis/cpu/x86/64/winnt/bootstrap.factor
basis/cpu/x86/64/winnt/winnt.factor
basis/cpu/x86/assembler/assembler-tests.factor
basis/cpu/x86/assembler/assembler.factor
basis/cpu/x86/assembler/authors.txt
basis/cpu/x86/assembler/operands/operands.factor [new file with mode: 0644]
basis/cpu/x86/assembler/syntax/syntax.factor
basis/cpu/x86/bootstrap.factor
basis/cpu/x86/x86.factor
basis/heaps/heaps-tests.factor
basis/help/html/html.factor
basis/interval-maps/interval-maps.factor
basis/splitting/monotonic/monotonic.factor
basis/ui/gadgets/menus/menus.factor
basis/ui/tools/inspector/inspector.factor
basis/vocabs/prettyprint/prettyprint.factor
basis/xml/tests/test.factor
basis/xml/xml.factor
core/checksums/checksums.factor
core/classes/algebra/algebra.factor
core/classes/classes-docs.factor
core/classes/classes.factor
core/combinators/combinators-docs.factor
core/combinators/combinators.factor
core/generic/single/single.factor
core/io/binary/binary.factor
core/io/pathnames/pathnames-docs.factor
core/io/pathnames/pathnames.factor
core/make/make.factor
core/sequences/sequences.factor
core/slots/slots.factor
core/sorting/sorting-docs.factor
core/sorting/sorting.factor
core/source-files/errors/errors.factor
extra/alien/marshall/syntax/syntax-docs.factor
extra/benchmark/beust2/beust2.factor
extra/benchmark/pidigits/pidigits.factor
extra/c/lexer/authors.txt [new file with mode: 0644]
extra/c/lexer/lexer-tests.factor [new file with mode: 0644]
extra/c/lexer/lexer.factor [new file with mode: 0644]
extra/c/preprocessor/preprocessor.factor
extra/classes/tuple/change-tracking/authors.txt [new file with mode: 0644]
extra/classes/tuple/change-tracking/change-tracking-tests.factor [new file with mode: 0644]
extra/classes/tuple/change-tracking/change-tracking.factor [new file with mode: 0644]
extra/classes/tuple/change-tracking/summary.txt [new file with mode: 0644]
extra/dns/util/util.factor
extra/fuel/xref/xref.factor
extra/gpu/demos/bunny/bunny.factor
extra/gpu/demos/bunny/sobel.f.glsl
extra/gpu/render/render.factor
extra/gpu/shaders/shaders.factor
extra/gpu/textures/textures-docs.factor
extra/gpu/textures/textures.factor
extra/irc/client/internals/internals.factor
extra/irc/logbot/logbot.factor
extra/pair-methods/pair-methods.factor
extra/sequence-parser/sequence-parser-tests.factor
extra/sequence-parser/sequence-parser.factor
extra/webapps/blogs/blogs.factor
extra/webapps/pastebin/pastebin.factor
extra/webapps/planet/planet.factor
extra/webapps/wiki/wiki.factor
misc/fuel/fuel-syntax.el
vm/debug.cpp
vm/image.cpp

index a33a85b218b2f8063897b886bc52e47e95d88988..016d60e68cbe3b6cb35480b38c3054cbe6e4753a 100755 (executable)
@@ -55,10 +55,13 @@ For X11 support, you need recent development libraries for libc,
 Pango, X11, and OpenGL. On a Debian-derived Linux distribution
 (like Ubuntu), you can use the following line to grab everything:
 
-    sudo apt-get install libc6-dev libpango-1.0-dev libx11-dev
+    sudo apt-get install libc6-dev libpango1.0-dev libx11-dev libgl1-mesa-dev
+
+Note that if you are using a proprietary OpenGL driver, you should
+probably leave out the last package in the list.
 
 If your DISPLAY environment variable is set, the UI will start
-automatically:
+automatically when you run Factor:
 
   ./factor
 
index 54b799f6750f2b9d3d3fb54ef72a58a43638f0b4..15840dfd66d26d5c95be292b36a00fa276cecf8c 100644 (file)
@@ -365,7 +365,7 @@ M: character-type (<fortran-result>)
     ] bi* ;
 
 : (fortran-in-shuffle) ( ret par -- seq )
-    [ [ second ] bi@ <=> ] sort append ;
+    [ second ] sort-with append ;
 
 : (fortran-out-shuffle) ( ret par -- seq )
     append ;
index b2ce66b02c69eae4d843ffd2d2e5a8d1409126ba..0d255b8d076b67ce5b0435eb9e5c346bd91133ea 100755 (executable)
@@ -29,5 +29,6 @@ M: library dispose dll>> [ dispose ] when* ;
 : remove-library ( name -- )
     libraries get delete-at* [ dispose ] [ drop ] if ;
 
-: add-library ( name path abi -- )    
-    <library> swap libraries get [ delete-at ] [ set-at ] 2bi ;
\ No newline at end of file
+: add-library ( name path abi -- )
+    [ 2drop remove-library ]
+    [ <library> swap libraries get set-at ] 3bi ;
\ No newline at end of file
index 0505dcb1841fa9610be2d61486c4e21e8bd1fc9f..d0f71474526622e14774c12940260ecd80e5f357 100755 (executable)
@@ -6,11 +6,14 @@ classes.private arrays hashtables vectors classes.tuple sbufs
 hashtables.private sequences.private math classes.tuple.private
 growable namespaces.private assocs words command-line vocabs io
 io.encodings.string libc splitting math.parser memory compiler.units
-math.order compiler.tree.builder compiler.tree.optimizer
-compiler.cfg.optimizer ;
-FROM: compiler => enable-optimizer compile-word ;
+math.order quotations quotations.private assocs.private ;
+FROM: compiler => enable-optimizer ;
 IN: bootstrap.compiler
 
+"profile-compiler" get [
+    "bootstrap.compiler.timing" require
+] when
+
 ! Don't bring this in when deploying, since it will store a
 ! reference to 'eval' in a global variable
 "deploy-vocab" get "staging" get or [
@@ -42,16 +45,24 @@ nl
 ! which are also quick to compile are replaced by
 ! compiled definitions as soon as possible.
 {
-    not
+    not ?
+
+    2over roll -roll
 
     array? hashtable? vector?
     tuple? sbuf? tombstone?
+    curry? compose? callable?
+    quotation?
 
-    array-nth set-array-nth
+    curry compose uncurry
+
+    array-nth set-array-nth length>>
 
     wrap probe
 
     namestack*
+
+    layout-of
 } compile-unoptimized
 
 "." write flush
@@ -75,7 +86,7 @@ nl
 "." write flush
 
 {
-    hashcode* = get set
+    hashcode* = equal? assoc-stack (assoc-stack) get set
 } compile-unoptimized
 
 "." write flush
@@ -83,6 +94,7 @@ nl
 {
     memq? split harvest sift cut cut-slice start index clone
     set-at reverse push-all class number>string string>number
+    like clone-like
 } compile-unoptimized
 
 "." write flush
@@ -100,22 +112,6 @@ nl
 
 "." write flush
 
-{ build-tree } compile-unoptimized
-
-"." write flush
-
-{ optimize-tree } compile-unoptimized
-
-"." write flush
-
-{ optimize-cfg } compile-unoptimized
-
-"." write flush
-
-{ compile-word } compile-unoptimized
-
-"." write flush
-
 vocabs [ words compile-unoptimized "." write flush ] each
 
 " done" print flush
diff --git a/basis/bootstrap/compiler/timing/timing.factor b/basis/bootstrap/compiler/timing/timing.factor
new file mode 100644 (file)
index 0000000..e1466e3
--- /dev/null
@@ -0,0 +1,38 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors compiler.cfg.builder compiler.cfg.linear-scan
+compiler.cfg.liveness compiler.cfg.mr compiler.cfg.optimizer
+compiler.cfg.stacks.finalize compiler.cfg.stacks.global
+compiler.codegen compiler.tree.builder compiler.tree.optimizer
+kernel make sequences tools.annotations tools.crossref ;
+IN: bootstrap.compiler.timing
+
+: passes ( word -- seq )
+    def>> uses [ vocabulary>> "compiler." head? ] filter ;
+
+: high-level-passes ( -- seq ) \ optimize-tree passes ;
+
+: low-level-passes ( -- seq ) \ optimize-cfg passes ;
+
+: machine-passes ( -- seq ) \ build-mr passes ;
+
+: linear-scan-passes ( -- seq ) \ (linear-scan) passes ;
+
+: all-passes ( -- seq )
+    [
+        \ build-tree ,
+        \ optimize-tree ,
+        high-level-passes %
+        \ build-cfg ,
+        \ compute-global-sets ,
+        \ finalize-stack-shuffling ,
+        \ optimize-cfg ,
+        low-level-passes %
+        \ compute-live-sets ,
+        \ build-mr ,
+        machine-passes %
+        linear-scan-passes %
+        \ generate ,
+    ] { } make ;
+
+all-passes [ [ reset ] [ add-timing ] bi ] each
\ No newline at end of file
diff --git a/basis/checksums/fnv1/authors.txt b/basis/checksums/fnv1/authors.txt
new file mode 100644 (file)
index 0000000..c64bb4e
--- /dev/null
@@ -0,0 +1 @@
+Alaric Snell-Pym
\ No newline at end of file
diff --git a/basis/checksums/fnv1/fnv1-docs.factor b/basis/checksums/fnv1/fnv1-docs.factor
new file mode 100644 (file)
index 0000000..4fbecd2
--- /dev/null
@@ -0,0 +1,67 @@
+USING: help.markup help.syntax ;
+IN: checksums.fnv1
+
+HELP: fnv1-32
+{ $class-description "Fowler-Noll-Vo checksum algorithm, v1, 32-bit." } ;
+
+HELP: fnv1a-32
+{ $class-description "Fowler-Noll-Vo checksum algorithm, v1a, 32-bit." } ;
+
+
+HELP: fnv1-64
+{ $class-description "Fowler-Noll-Vo checksum algorithm, v1, 64-bit." } ;
+
+HELP: fnv1a-64
+{ $class-description "Fowler-Noll-Vo checksum algorithm, v1a, 64-bit." } ;
+
+
+HELP: fnv1-128
+{ $class-description "Fowler-Noll-Vo checksum algorithm, v1, 128-bit." } ;
+
+HELP: fnv1a-128
+{ $class-description "Fowler-Noll-Vo checksum algorithm, v1a, 128-bit." } ;
+
+
+HELP: fnv1-256
+{ $class-description "Fowler-Noll-Vo checksum algorithm, v1, 256-bit." } ;
+
+HELP: fnv1a-256
+{ $class-description "Fowler-Noll-Vo checksum algorithm, v1a, 256-bit." } ;
+
+
+HELP: fnv1-512
+{ $class-description "Fowler-Noll-Vo checksum algorithm, v1, 512-bit." } ;
+
+HELP: fnv1a-512
+{ $class-description "Fowler-Noll-Vo checksum algorithm, v1a, 512-bit." } ;
+
+
+HELP: fnv1-1024
+{ $class-description "Fowler-Noll-Vo checksum algorithm, v1, 1024-bit." } ;
+
+HELP: fnv1a-1024
+{ $class-description "Fowler-Noll-Vo checksum algorithm, v1a, 1024-bit." } ;
+
+ARTICLE: "checksums.fnv1" "Fowler-Noll-Vo checksum"
+  "The Fowler-Noll-Vo checksum algorithm is another simple and fast checksum. It comes in 32, 64, 128, 256, 512 and 1024-bit versions, each in 1 and 1a variants. The 1a variants tend to produce a slightly better result. See http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash for more details."
+
+  { $subsection fnv1-32 }
+  { $subsection fnv1a-32 }
+
+  { $subsection fnv1-64 }
+  { $subsection fnv1a-64 }
+
+  { $subsection fnv1-128 }
+  { $subsection fnv1a-128 }
+
+  { $subsection fnv1-256 }
+  { $subsection fnv1a-256 }
+
+  { $subsection fnv1-512 }
+  { $subsection fnv1a-512 }
+
+  { $subsection fnv1-1024 }
+  { $subsection fnv1a-1024 }
+ ;
+
+ABOUT: "checksums.fnv1"
diff --git a/basis/checksums/fnv1/fnv1-tests.factor b/basis/checksums/fnv1/fnv1-tests.factor
new file mode 100644 (file)
index 0000000..de665a1
--- /dev/null
@@ -0,0 +1,41 @@
+USING: checksums.fnv1 checksums strings tools.test ;
+IN: checksums.fnv1.tests
+
+! A few test vectors taken from http://www.isthe.com/chongo/src/fnv/test_fnv.c
+
+[ HEX: 811c9dc5 ] [ "" fnv1-32 checksum-bytes ] unit-test
+[ HEX: 811c9dc5 ] [ "" fnv1a-32 checksum-bytes ] unit-test
+[ HEX: cbf29ce484222325 ] [ "" fnv1-64 checksum-bytes ] unit-test
+[ HEX: cbf29ce484222325 ] [ "" fnv1a-64 checksum-bytes ] unit-test
+
+[ HEX: 050c5d7e ] [ "a" fnv1-32 checksum-bytes ] unit-test
+[ HEX: e40c292c ] [ "a" fnv1a-32 checksum-bytes ] unit-test
+[ HEX: af63bd4c8601b7be ] [ "a" fnv1-64 checksum-bytes ] unit-test
+[ HEX: af63dc4c8601ec8c ] [ "a" fnv1a-64 checksum-bytes ] unit-test
+
+[ HEX: 050c5d7d ] [ "b" fnv1-32 checksum-bytes ] unit-test
+[ HEX: e70c2de5 ] [ "b" fnv1a-32 checksum-bytes ] unit-test
+[ HEX: af63bd4c8601b7bd ] [ "b" fnv1-64 checksum-bytes ] unit-test
+[ HEX: af63df4c8601f1a5 ] [ "b" fnv1a-64 checksum-bytes ] unit-test
+
+[ HEX: 31f0b262 ] [ "foobar" fnv1-32 checksum-bytes ] unit-test
+[ HEX: bf9cf968 ] [ "foobar" fnv1a-32 checksum-bytes ] unit-test
+[ HEX: 340d8765a4dda9c2 ] [ "foobar" fnv1-64 checksum-bytes ] unit-test
+[ HEX: 85944171f73967e8 ] [ "foobar" fnv1a-64 checksum-bytes ] unit-test
+
+! I couldn't find any test vectors for 128, 256, 512, or 1024 versions of FNV1 hashes.
+! So, just to check that your maths works the same as my maths, here's a few samples computed on my laptop.
+! So they may be right or wrong, but either way, them failing is cause for concern somewhere...
+
+[ 3897470310 ] [ "Hello, world!" fnv1-32 checksum-bytes ] unit-test
+[ 3985698964 ] [ "Hello, world!" fnv1a-32 checksum-bytes ] unit-test
+[ 7285062107457560934 ] [ "Hello, world!" fnv1-64 checksum-bytes ] unit-test
+[ 4094109891673226228 ] [ "Hello, world!" fnv1a-64 checksum-bytes ] unit-test
+[ 281580511747867177735318995358496831158 ] [ "Hello, world!" fnv1-128 checksum-bytes ] unit-test
+[ 303126633380056630368940439484674414572 ] [ "Hello, world!" fnv1a-128 checksum-bytes ] unit-test
+[ 104295939182568077644846978685759236849634734810631820736486253421270219742822 ] [ "Hello, world!" fnv1-256 checksum-bytes ] unit-test
+[ 9495445728692795332446740615588417456874414534608540692485745371050033741380 ] [ "Hello, world!" fnv1a-256 checksum-bytes ] unit-test
+[ 3577308325596719252093726711895047340166329831006673109476042102918876665433235513101496175651226507162015890004121912850661561110326527625579463564626958 ] [ "Hello, world!" fnv1-512 checksum-bytes ] unit-test
+[ 3577308325596719162840652138474318309664256091923081930027929425092517582111473988451078821416039944023089883981242376700859598441397004715365740906054208 ] [ "Hello, world!" fnv1a-512 checksum-bytes ] unit-test
+[ 52692754922840008511959888105094366091401994235075816792707658326855733053286986999719949898492311786648795846192078757217437117165934438286601534984230194601365788544275827382423366672856972872132009691615382991251544423521887009322211754219117294019951276080952271766377222613325328591830596794468813260226 ] [ "Hello, world!" fnv1-1024 checksum-bytes ] unit-test
+[ 52692754922840008511959888105094366091401994235075816792707658326855804920671100511873485674717442819607149127986090276849364757610838433887624184145636764448608707614141109841761957788887305179569455221243999538336208648824673027111352338809582124430199044921035232455717748500524777795242051756321605065326 ] [ "Hello, world!" fnv1a-1024 checksum-bytes ] unit-test
diff --git a/basis/checksums/fnv1/fnv1.factor b/basis/checksums/fnv1/fnv1.factor
new file mode 100644 (file)
index 0000000..f221cef
--- /dev/null
@@ -0,0 +1,106 @@
+! Copyright (C) 2009 Alaric Snell-Pym
+! See http://factorcode.org/license.txt for BSD license.
+
+USING: checksums classes.singleton kernel math math.ranges
+math.vectors sequences ;
+
+IN: checksums.fnv1
+
+SINGLETON: fnv1-32
+SINGLETON: fnv1a-32
+SINGLETON: fnv1-64
+SINGLETON: fnv1a-64
+SINGLETON: fnv1-128
+SINGLETON: fnv1a-128
+SINGLETON: fnv1-256
+SINGLETON: fnv1a-256
+SINGLETON: fnv1-512
+SINGLETON: fnv1a-512
+SINGLETON: fnv1-1024
+SINGLETON: fnv1a-1024
+
+CONSTANT: fnv1-32-prime 16777619
+CONSTANT: fnv1-64-prime 1099511628211
+CONSTANT: fnv1-128-prime 309485009821345068724781371
+CONSTANT: fnv1-256-prime 374144419156711147060143317175368453031918731002211
+CONSTANT: fnv1-512-prime 35835915874844867368919076489095108449946327955754392558399825615420669938882575126094039892345713852759
+CONSTANT: fnv1-1024-prime 5016456510113118655434598811035278955030765345404790744303017523831112055108147451509157692220295382716162651878526895249385292291816524375083746691371804094271873160484737966720260389217684476157468082573
+
+CONSTANT: fnv1-32-mod HEX: ffffffff
+CONSTANT: fnv1-64-mod HEX: ffffffffffffffff
+CONSTANT: fnv1-128-mod HEX: ffffffffffffffffffffffffffffffff
+CONSTANT: fnv1-256-mod HEX: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+CONSTANT: fnv1-512-mod HEX: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+CONSTANT: fnv1-1024-mod HEX: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+
+CONSTANT: fnv1-32-basis HEX: 811c9dc5
+CONSTANT: fnv1-64-basis HEX: cbf29ce484222325
+CONSTANT: fnv1-128-basis HEX: 6c62272e07bb014262b821756295c58d
+CONSTANT: fnv1-256-basis HEX: dd268dbcaac550362d98c384c4e576ccc8b1536847b6bbb31023b4c8caee0535
+CONSTANT: fnv1-512-basis HEX: b86db0b1171f4416dca1e50f309990acac87d059c90000000000000000000d21e948f68a34c192f62ea79bc942dbe7ce182036415f56e34bac982aac4afe9fd9
+CONSTANT: fnv1-1024-basis HEX: 5f7a76758ecc4d32e56d5a591028b74b29fc4223fdada16c3bf34eda3674da9a21d9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c6d7eb6e73802734510a555f256cc005ae556bde8cc9c6a93b21aff4b16c71ee90b3
+
+M: fnv1-32 checksum-bytes ( bytes checksum -- value )
+    drop
+    fnv1-32-basis swap
+    [ swap fnv1-32-prime * bitxor fnv1-32-mod bitand ] each ;
+
+M: fnv1a-32 checksum-bytes ( bytes checksum -- value )
+    drop
+    fnv1-32-basis swap
+    [ bitxor fnv1-32-prime * fnv1-32-mod bitand ] each ;
+
+
+M: fnv1-64 checksum-bytes ( bytes checksum -- value )
+    drop
+    fnv1-64-basis swap
+    [ swap fnv1-64-prime * bitxor fnv1-64-mod bitand ] each ;
+
+M: fnv1a-64 checksum-bytes ( bytes checksum -- value )
+    drop
+    fnv1-64-basis swap
+    [ bitxor fnv1-64-prime * fnv1-64-mod bitand ] each ;
+
+
+M: fnv1-128 checksum-bytes ( bytes checksum -- value )
+    drop
+    fnv1-128-basis swap
+    [ swap fnv1-128-prime * bitxor fnv1-128-mod bitand ] each ;
+
+M: fnv1a-128 checksum-bytes ( bytes checksum -- value )
+    drop
+    fnv1-128-basis swap
+    [ bitxor fnv1-128-prime * fnv1-128-mod bitand ] each ;
+
+
+M: fnv1-256 checksum-bytes ( bytes checksum -- value )
+    drop
+    fnv1-256-basis swap
+    [ swap fnv1-256-prime * bitxor fnv1-256-mod bitand ] each ;
+
+M: fnv1a-256 checksum-bytes ( bytes checksum -- value )
+    drop
+    fnv1-256-basis swap
+    [ bitxor fnv1-256-prime * fnv1-256-mod bitand ] each ;
+
+
+M: fnv1-512 checksum-bytes ( bytes checksum -- value )
+    drop
+    fnv1-512-basis swap
+    [ swap fnv1-512-prime * bitxor fnv1-512-mod bitand ] each ;
+
+M: fnv1a-512 checksum-bytes ( bytes checksum -- value )
+    drop
+    fnv1-512-basis swap
+    [ bitxor fnv1-512-prime * fnv1-512-mod bitand ] each ;
+
+
+M: fnv1-1024 checksum-bytes ( bytes checksum -- value )
+    drop
+    fnv1-1024-basis swap
+    [ swap fnv1-1024-prime * bitxor fnv1-1024-mod bitand ] each ;
+
+M: fnv1a-1024 checksum-bytes ( bytes checksum -- value )
+    drop
+    fnv1-1024-basis swap
+    [ bitxor fnv1-1024-prime * fnv1-1024-mod bitand ] each ;
diff --git a/basis/checksums/fnv1/summary.txt b/basis/checksums/fnv1/summary.txt
new file mode 100644 (file)
index 0000000..2c74cda
--- /dev/null
@@ -0,0 +1 @@
+Fowler-Noll-Vo checksum algorithm
index 89f26f7928216e98053c51f8e8c722a81837723c..d73bd866a0bb1013880372de12ab54ee14c2e5d1 100644 (file)
@@ -46,11 +46,11 @@ V{ T{ ##branch } } 4 test-bb
 
 V{ T{ ##branch } } 5 test-bb
 
-0 get 1 get 2 get V{ } 2sequence >>successors drop
+0 { 1 2 } edges
 
-1 get 3 get 4 get V{ } 2sequence >>successors drop
+1 { 3 4 } edges
 
-2 get 3 get 4 get V{ } 2sequence >>successors drop
+2 { 3 4 } edges
 
 [ ] [ test-branch-splitting ] unit-test
 
@@ -64,11 +64,11 @@ V{ T{ ##branch } } 3 test-bb
 
 V{ T{ ##branch } } 4 test-bb
 
-0 get 1 get 2 get V{ } 2sequence >>successors drop
+0 { 1 2 } edges
 
-1 get 3 get 4 get V{ } 2sequence >>successors drop
+1 { 3 4 } edges
 
-2 get 4 get 1vector >>successors drop
+2 4 edge
 
 [ ] [ test-branch-splitting ] unit-test
 
@@ -78,8 +78,8 @@ V{ T{ ##branch } } 1 test-bb
 
 V{ T{ ##branch } } 2 test-bb
 
-0 get 1 get 2 get V{ } 2sequence >>successors drop
+0 { 1 2 } edges
 
-1 get 2 get 1vector >>successors drop
+1 2 edge
 
 [ ] [ test-branch-splitting ] unit-test
\ No newline at end of file
index 0c40b93ba6ed27957e01c0b31a91e101972b4418..05d922545d8eb5faf988cffd1750ec06cbabcc75 100755 (executable)
@@ -19,6 +19,7 @@ compiler.cfg.instructions
 compiler.cfg.predecessors
 compiler.cfg.builder.blocks
 compiler.cfg.stacks
+compiler.cfg.stacks.local
 compiler.alien ;
 IN: compiler.cfg.builder
 
@@ -159,14 +160,32 @@ M: #push emit-node
     literal>> ^^load-literal ds-push ;
 
 ! #shuffle
+
+! Even though low level IR has its own dead code elimination pass,
+! we try not to introduce useless ##peeks here, since this reduces
+! the accuracy of global stack analysis.
+
+: make-input-map ( #shuffle -- assoc )
+    ! Assoc maps high-level IR values to stack locations.
+    [
+        [ in-d>> <reversed> [ <ds-loc> swap set ] each-index ]
+        [ in-r>> <reversed> [ <rs-loc> swap set ] each-index ] bi
+    ] H{ } make-assoc ;
+
+: make-output-seq ( values mapping input-map -- vregs )
+    '[ _ at _ at peek-loc ] map ;
+
+: load-shuffle ( #shuffle mapping input-map -- ds-vregs rs-vregs )
+    [ [ out-d>> ] 2dip make-output-seq ]
+    [ [ out-r>> ] 2dip make-output-seq ] 3bi ;
+
+: store-shuffle ( #shuffle ds-vregs rs-vregs -- )
+    [ [ in-d>> length neg inc-d ] dip ds-store ]
+    [ [ in-r>> length neg inc-r ] dip rs-store ]
+    bi-curry* bi ;
+
 M: #shuffle emit-node
-    dup
-    H{ } clone
-    [ [ in-d>> [ length ds-load ] keep ] dip '[ _ set-at ] 2each ]
-    [ [ in-r>> [ length rs-load ] keep ] dip '[ _ set-at ] 2each ]
-    [ nip ] 2tri
-    [ [ [ out-d>> ] [ mapping>> ] bi ] dip '[ _ at _ at ] map ds-store ]
-    [ [ [ out-r>> ] [ mapping>> ] bi ] dip '[ _ at _ at ] map rs-store ] 2bi ;
+    dup dup [ mapping>> ] [ make-input-map ] bi load-shuffle store-shuffle ;
 
 ! #return
 : emit-return ( -- )
index 1f2c75f28a35334258dbd2200fb8192f02d69eb8..812a5a1a7fb236e796011ee93be63d46a47c317c 100644 (file)
@@ -1,12 +1,17 @@
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel namespaces assocs accessors sequences grouping
-compiler.cfg.rpo compiler.cfg.renaming compiler.cfg.instructions ;
+combinators compiler.cfg.rpo compiler.cfg.renaming
+compiler.cfg.instructions ;
 IN: compiler.cfg.copy-prop
 
 ! The first three definitions are also used in compiler.cfg.alias-analysis.
 SYMBOL: copies
 
+! Initialized per-basic-block; a mapping from inputs to dst for eliminating
+! redundant phi instructions
+SYMBOL: phis
+
 : resolve ( vreg -- vreg )
     copies get ?at drop ;
 
@@ -22,17 +27,27 @@ GENERIC: visit-insn ( insn -- )
 
 M: ##copy visit-insn record-copy ;
 
+: useless-phi ( dst inputs -- ) first (record-copy) ;
+
+: redundant-phi ( dst inputs -- ) phis get at (record-copy) ;
+
+: record-phi ( dst inputs -- ) phis get set-at ;
+
 M: ##phi visit-insn
     [ dst>> ] [ inputs>> values [ resolve ] map ] bi
-    dup all-equal? [ first (record-copy) ] [ 2drop ] if ;
+    {
+        { [ dup all-equal? ] [ useless-phi ] }
+        { [ dup phis get key? ] [ redundant-phi ] }
+        [ record-phi ]
+    } cond ;
 
 M: insn visit-insn drop ;
 
 : collect-copies ( cfg -- )
     H{ } clone copies set
     [
-        instructions>>
-        [ visit-insn ] each
+        H{ } clone phis set
+        instructions>> [ visit-insn ] each
     ] each-basic-block ;
 
 GENERIC: update-insn ( insn -- keep? )
@@ -48,8 +63,7 @@ M: insn update-insn rename-insn-uses t ;
     copies get dup assoc-empty? [ 2drop ] [
         renamings set
         [
-            instructions>>
-            [ update-insn ] filter-here
+            instructions>> [ update-insn ] filter-here
         ] each-basic-block
     ] if ;
 
diff --git a/basis/compiler/cfg/critical-edges/critical-edges-tests.factor b/basis/compiler/cfg/critical-edges/critical-edges-tests.factor
new file mode 100644 (file)
index 0000000..88383e2
--- /dev/null
@@ -0,0 +1,37 @@
+USING: accessors assocs compiler.cfg
+compiler.cfg.critical-edges compiler.cfg.debugger
+compiler.cfg.instructions compiler.cfg.predecessors
+compiler.cfg.registers cpu.architecture kernel namespaces
+sequences tools.test compiler.cfg.utilities ;
+IN: compiler.cfg.critical-edges.tests
+
+! Make sure we update phi nodes when splitting critical edges
+
+: test-critical-edges ( -- )
+    cfg new 0 get >>entry
+    compute-predecessors
+    split-critical-edges ;
+
+V{
+    T{ ##peek f V int-regs 0 D 0 }
+    T{ ##branch }
+} 0 test-bb
+
+V{
+    T{ ##peek f V int-regs 1 D 1 }
+    T{ ##branch }
+} 1 test-bb
+
+V{
+    T{ ##phi f V int-regs 2 H{ { 0 V int-regs 0 } { 1 V int-regs 1 } } }
+    T{ ##return }
+} 2 test-bb
+
+0 { 1 2 } edges
+1 2 edge
+
+[ ] [ test-critical-edges ] unit-test
+
+[ t ] [ 0 get successors>> second successors>> first 2 get eq? ] unit-test
+
+[ V int-regs 0 ] [ 2 get instructions>> first inputs>> 0 get successors>> second swap at ] unit-test
\ No newline at end of file
index 1000c24752badbf77aaa303ce76cc60671712230..2a42df4bbf076e4046dbdaff8ba8348d1f111fbd 100644 (file)
@@ -1,14 +1,22 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel math accessors sequences
+USING: kernel math accessors sequences locals assocs fry
 compiler.cfg compiler.cfg.rpo compiler.cfg.utilities ;
 IN: compiler.cfg.critical-edges
 
 : critical-edge? ( from to -- ? )
     [ successors>> length 1 > ] [ predecessors>> length 1 > ] bi* and ;
 
+: new-key ( new-key old-key assoc -- )
+    [ delete-at* ] keep '[ swap _ set-at ] [ 2drop ] if ;
+
+:: update-phis ( from to bb -- )
+    ! Any phi nodes in 'to' which reference 'from'
+    ! should now reference 'bb'.
+    to [ [ bb from ] dip inputs>> new-key ] each-phi ;
+
 : split-critical-edge ( from to -- )
-    f <simple-block> insert-basic-block ;
+    f <simple-block> [ insert-basic-block ] [ update-phis ] 3bi ; 
 
 : split-critical-edges ( cfg -- )
     dup [
index 3c6ea1f0e4f6a64ba370134561e0f872cc9f0d67..26bf0eca564fe73d73d078be64217b9ccc7d23f5 100644 (file)
@@ -1,14 +1,14 @@
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel words sequences quotations namespaces io vectors
-classes.tuple accessors prettyprint prettyprint.config
+classes.tuple accessors prettyprint prettyprint.config assocs
 prettyprint.backend prettyprint.custom prettyprint.sections
 parser compiler.tree.builder compiler.tree.optimizer
 compiler.cfg.builder compiler.cfg.linearization
 compiler.cfg.registers compiler.cfg.stack-frame
 compiler.cfg.linear-scan compiler.cfg.two-operand
-compiler.cfg.optimizer
-compiler.cfg.mr compiler.cfg ;
+compiler.cfg.optimizer compiler.cfg.instructions
+compiler.cfg.utilities compiler.cfg.mr compiler.cfg ;
 IN: compiler.cfg.debugger
 
 GENERIC: test-cfg ( quot -- cfgs )
@@ -52,11 +52,23 @@ M: ds-loc pprint* \ D pprint-loc ;
 
 M: rs-loc pprint* \ R pprint-loc ;
 
+: resolve-phis ( bb -- )
+    [
+        [ [ [ get ] dip ] assoc-map ] change-inputs drop
+    ] each-phi ;
+
 : test-bb ( insns n -- )
-    [ <basic-block> swap >>number swap >>instructions ] keep set ;
+    [ <basic-block> swap >>number swap >>instructions dup ] keep set
+    resolve-phis ;
+
+: edge ( from to -- )
+    [ get ] bi@ 1vector >>successors drop ;
+
+: edges ( from tos -- )
+    [ get ] [ [ get ] V{ } map-as ] bi* >>successors drop ;
 
 : test-diamond ( -- )
-    1 get 1vector 0 get (>>successors)
-    2 get 3 get V{ } 2sequence 1 get (>>successors)
-    4 get 1vector 2 get (>>successors)
-    4 get 1vector 3 get (>>successors) ;
\ No newline at end of file
+    0 1 edge
+    1 { 2 3 } edges
+    2 4 edge
+    3 4 edge ;
\ No newline at end of file
diff --git a/basis/compiler/cfg/def-use/authors.txt b/basis/compiler/cfg/def-use/authors.txt
new file mode 100644 (file)
index 0000000..a44f8d7
--- /dev/null
@@ -0,0 +1,2 @@
+Slava Pestov
+Daniel Ehrenberg
diff --git a/basis/compiler/cfg/def-use/def-use-tests.factor b/basis/compiler/cfg/def-use/def-use-tests.factor
new file mode 100644 (file)
index 0000000..ca22577
--- /dev/null
@@ -0,0 +1,35 @@
+! Copyright (C) 2009 Daniel Ehrenberg.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel tools.test accessors vectors sequences namespaces
+arrays
+cpu.architecture
+compiler.cfg.def-use
+compiler.cfg
+compiler.cfg.debugger
+compiler.cfg.instructions
+compiler.cfg.registers ;
+
+V{
+    T{ ##peek f V int-regs 0 D 0 }
+    T{ ##peek f V int-regs 1 D 0 }
+    T{ ##peek f V int-regs 2 D 0 }
+} 1 test-bb
+V{
+    T{ ##replace f V int-regs 2 D 0 }
+} 2 test-bb
+1 2 edge
+V{
+    T{ ##replace f V int-regs 0 D 0 }
+} 3 test-bb
+2 3 edge
+V{ } 4 test-bb
+V{ } 5 test-bb
+3 { 4 5 } edges
+V{
+    T{ ##phi f V int-regs 2 H{ { 2 V int-regs 0 } { 3 V int-regs 1 } } }
+} 6 test-bb
+4 6 edge
+5 6 edge
+
+cfg new 1 get >>entry 0 set
+[ ] [ 0 get [ compute-defs ] [ compute-uses ] bi ] unit-test
index 1c9ac90f78c747ad3f9815231b92771356616921..c56bd807791b765a1913d4f069dd57b797bda5b8 100644 (file)
@@ -1,7 +1,7 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2009 Slava Pestov, Daniel Ehrenberg.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays kernel assocs sequences namespaces fry
-sets compiler.cfg.rpo compiler.cfg.instructions ;
+sets compiler.cfg.rpo compiler.cfg.instructions locals ;
 IN: compiler.cfg.def-use
 
 GENERIC: defs-vreg ( insn -- vreg/f )
@@ -80,18 +80,15 @@ SYMBOLS: defs insns uses ;
         ] each-basic-block
     ] keep insns set ;
 
-: compute-uses ( cfg -- )
-    H{ } clone [
-        '[
-            dup instructions>> [
-                uses-vregs [
-                    _ conjoin-at
-                ] with each
-            ] with each
-        ] each-basic-block
-    ] keep
-    [ keys ] assoc-map
-    uses set ;
-
-: compute-def-use ( cfg -- )
-    [ compute-defs ] [ compute-uses ] [ compute-insns ] tri ;
\ No newline at end of file
+:: compute-uses ( cfg -- )
+    ! Here, a phi node uses its argument in the block that it comes from.
+    H{ } clone :> use
+    cfg [| block |
+        block instructions>> [
+            dup ##phi?
+            [ inputs>> [ use conjoin-at ] assoc-each ]
+            [ uses-vregs [ block swap use conjoin-at ] each ]
+            if
+        ] each
+    ] each-basic-block
+    use [ keys ] assoc-map uses set ;
index 07bcd7bc849c65e4125b0e72603223ee35fba2ef..a3b9fc0223d2411ae314290d2726d2a2b89f0c69 100644 (file)
@@ -16,11 +16,11 @@ V{ } 3 test-bb
 V{ } 4 test-bb
 V{ } 5 test-bb
 
-0 get 1 get 2 get V{ } 2sequence >>successors drop
-1 get 3 get 1vector >>successors drop
-2 get 4 get 1vector >>successors drop
-3 get 4 get 1vector >>successors drop
-4 get 5 get 1vector >>successors drop
+0 { 1 2 } edges
+1 3 edge
+2 4 edge
+3 4 edge
+4 5 edge
 
 [ ] [ test-dominance ] unit-test
 
@@ -46,11 +46,11 @@ V{ } 2 test-bb
 V{ } 3 test-bb
 V{ } 4 test-bb
 
-0 get 1 get 2 get V{ } 2sequence >>successors drop
-1 get 3 get 1vector >>successors drop
-2 get 4 get 1vector >>successors drop
-3 get 4 get 1vector >>successors drop
-4 get 3 get 1vector >>successors drop
+0 { 1 2 } edges
+1 3 edge
+2 4 edge
+3 4 edge
+4 3 edge
 
 [ ] [ test-dominance ] unit-test
 
@@ -64,12 +64,12 @@ V{ } 3 test-bb
 V{ } 4 test-bb
 V{ } 5 test-bb
 
-0 get 1 get 2 get V{ } 2sequence >>successors drop
-1 get 5 get 1vector >>successors drop
-2 get 4 get 3 get V{ } 2sequence >>successors drop
-5 get 4 get 1vector >>successors drop
-4 get 5 get 3 get V{ } 2sequence >>successors drop
-3 get 4 get 1vector >>successors drop
+0 { 1 2 } edges
+1 5 edge
+2 { 4 3 } edges
+5 4 edge
+4 { 5 3 } edges
+3 4 edge
 
 [ ] [ test-dominance ] unit-test
 
diff --git a/basis/compiler/cfg/gc-checks/gc-checks-tests.factor b/basis/compiler/cfg/gc-checks/gc-checks-tests.factor
new file mode 100644 (file)
index 0000000..b324214
--- /dev/null
@@ -0,0 +1,26 @@
+IN: compiler.cfg.gc-checks.tests
+USING: compiler.cfg.gc-checks compiler.cfg.debugger
+compiler.cfg.registers compiler.cfg.instructions compiler.cfg
+compiler.cfg.predecessors cpu.architecture tools.test kernel vectors
+namespaces accessors sequences ;
+
+: test-gc-checks ( -- )
+    cfg new 0 get >>entry
+    compute-predecessors
+    insert-gc-checks
+    drop ;
+
+V{
+    T{ ##inc-d f 3 }
+    T{ ##replace f V int-regs 0 D 1 }
+} 0 test-bb
+
+V{
+    T{ ##box-float f V int-regs 0 V int-regs 1 }
+} 1 test-bb
+
+0 1 edge
+
+[ ] [ test-gc-checks ] unit-test
+
+[ V{ D 0 D 2 } ] [ 1 get instructions>> first uninitialized-locs>> ] unit-test
\ No newline at end of file
index 8435a231e6d3c02db325c0569f124daba42675b5..c34f2c42a38ac64b854cac7a7ae397638ec65b3d 100644 (file)
@@ -1,17 +1,27 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors kernel sequences assocs
-compiler.cfg.rpo compiler.cfg.instructions
-compiler.cfg.hats ;
+USING: accessors kernel sequences assocs fry
+compiler.cfg.rpo
+compiler.cfg.hats
+compiler.cfg.registers
+compiler.cfg.instructions
+compiler.cfg.stacks.uninitialized ;
 IN: compiler.cfg.gc-checks
 
-: gc? ( bb -- ? )
+: insert-gc-check? ( bb -- ? )
     instructions>> [ ##allocation? ] any? ;
 
-: insert-gc-check ( basic-block -- )
-    dup gc? [
-        [ i i f \ ##gc new-insn prefix ] change-instructions drop
-    ] [ drop ] if ;
+: blocks-with-gc ( cfg -- bbs )
+    post-order [ insert-gc-check? ] filter ;
+
+: insert-gc-check ( bb -- )
+    dup '[
+        i i f _ uninitialized-locs \ ##gc new-insn
+        prefix
+    ] change-instructions drop ;
 
 : insert-gc-checks ( cfg -- cfg' )
-    dup [ insert-gc-check ] each-basic-block ;
\ No newline at end of file
+    dup blocks-with-gc [
+        over compute-uninitialized-sets
+        [ insert-gc-check ] each
+    ] unless-empty ;
\ No newline at end of file
index e08b3b25bb58b958a8c5bcdd6d00e680bd3fc05d..0a52f1aa94b518ed2dfdfc3fc3f6c5335a163334 100644 (file)
@@ -190,7 +190,7 @@ INSN: ##fixnum-add < ##fixnum-overflow ;
 INSN: ##fixnum-sub < ##fixnum-overflow ;
 INSN: ##fixnum-mul < ##fixnum-overflow ;
 
-INSN: ##gc temp1 temp2 live-values ;
+INSN: ##gc temp1 temp2 live-values uninitialized-locs ;
 
 ! Instructions used by machine IR only.
 INSN: _prologue stack-frame ;
@@ -219,7 +219,7 @@ INSN: _fixnum-mul < _fixnum-overflow ;
 
 TUPLE: spill-slot n ; C: <spill-slot> spill-slot
 
-INSN: _gc temp1 temp2 gc-roots gc-root-count gc-root-size ;
+INSN: _gc temp1 temp2 gc-roots gc-root-count gc-root-size uninitialized-locs ;
 
 ! These instructions operate on machine registers and not
 ! virtual registers
index c6642d8ad9c9fef796fdde0ca1f9561ef8d20103..2618db0904d2ac0add69564a92233c91a3a90ec8 100644 (file)
@@ -48,11 +48,11 @@ IN: compiler.cfg.intrinsics
     slots.private:set-slot
     strings.private:string-nth
     strings.private:set-string-nth-fast
-    classes.tuple.private:<tuple-boa>
-    arrays:<array>
-    byte-arrays:<byte-array>
-    byte-arrays:(byte-array)
-    kernel:<wrapper>
+    classes.tuple.private:<tuple-boa>
+    arrays:<array>
+    byte-arrays:<byte-array>
+    byte-arrays:(byte-array)
+    kernel:<wrapper>
     alien.accessors:alien-unsigned-1
     alien.accessors:set-alien-unsigned-1
     alien.accessors:alien-signed-1
@@ -61,7 +61,7 @@ IN: compiler.cfg.intrinsics
     alien.accessors:set-alien-unsigned-2
     alien.accessors:alien-signed-2
     alien.accessors:set-alien-signed-2
-    alien.accessors:alien-cell
+    alien.accessors:alien-cell
     alien.accessors:set-alien-cell
 } [ t "intrinsic" set-word-prop ] each
 
@@ -90,7 +90,7 @@ IN: compiler.cfg.intrinsics
         alien.accessors:set-alien-float
         alien.accessors:alien-double
         alien.accessors:set-alien-double
-    } drop f [ t "intrinsic" set-word-prop ] each ;
+    } [ t "intrinsic" set-word-prop ] each ;
 
 : enable-fixnum-log2 ( -- )
     \ math.integers.private:fixnum-log2 t "intrinsic" set-word-prop ;
index c197da98148c48307ff2b204bb90d58e4cfc3ed9..d55266e6e4b63ef5bc3b939eaf0327ee77decf97 100644 (file)
@@ -28,29 +28,11 @@ IN: compiler.cfg.linear-scan.allocation
 : no-free-registers? ( result -- ? )
     second 0 = ; inline
 
-: split-to-fit ( new n -- before after )
-    split-interval
-    [ [ compute-start/end ] bi@ ]
-    [ >>split-next drop ]
-    [ ]
-    2tri ;
-
-: register-partially-available ( new result -- )
-    {
-        { [ 2dup second 1 - spill-live-out? ] [ drop spill-live-out ] }
-        { [ 2dup second 1 - spill-live-in? ] [ drop spill-live-in ] }
-        [
-            [ second 1 - split-to-fit ] keep
-            '[ _ register-available ] [ add-unhandled ] bi*
-        ]
-    } cond ;
-
 : assign-register ( new -- )
     dup coalesce? [ coalesce ] [
         dup register-status {
             { [ dup no-free-registers? ] [ drop assign-blocked-register ] }
             { [ 2dup register-available? ] [ register-available ] }
-            ! [ register-partially-available ]
             [ drop assign-blocked-register ]
         } cond
     ] if ;
index 14046a91f17782b9eacb0549aeb97ca1441ab1d9..4dd3c8176c2f115982bb384768051afef6c8245d 100644 (file)
@@ -28,23 +28,42 @@ ERROR: bad-live-ranges interval ;
     [ swap first (>>from) ]
     2bi ;
 
-: split-for-spill ( live-interval n -- before after )
-    split-interval
-    {
-        [ [ trim-before-ranges ] [ trim-after-ranges ] bi* ]
-        [ [ compute-start/end ] bi@ ]
-        [ [ check-ranges ] bi@ ]
-        [ ]
-    } 2cleave ;
-
 : assign-spill ( live-interval -- )
-    dup vreg>> assign-spill-slot >>spill-to f >>split-next drop ;
+    dup vreg>> assign-spill-slot >>spill-to drop ;
+
+: spill-before ( before -- before/f )
+    ! If the interval does not have any usages before the spill location,
+    ! then it is the second child of an interval that was split. We reload
+    ! the value and let the resolve pass insert a split later.
+    dup uses>> empty? [ drop f ] [
+        {
+            [ ]
+            [ assign-spill ]
+            [ trim-before-ranges ]
+            [ compute-start/end ]
+            [ check-ranges ]
+        } cleave
+    ] if ;
 
 : assign-reload ( live-interval -- )
     dup vreg>> assign-spill-slot >>reload-from drop ;
 
-: split-and-spill ( live-interval n -- before after )
-    split-for-spill 2dup [ assign-spill ] [ assign-reload ] bi* ;
+: spill-after ( after -- after/f )
+    ! If the interval has no more usages after the spill location,
+    ! then it is the first child of an interval that was split.  We
+    ! spill the value and let the resolve pass insert a reload later.
+    dup uses>> empty? [ drop f ] [
+        {
+            [ ]
+            [ assign-reload ]
+            [ trim-after-ranges ]
+            [ compute-start/end ]
+            [ check-ranges ]
+        } cleave
+    ] if ;
+
+: split-for-spill ( live-interval n -- before after )
+    split-interval [ spill-before ] [ spill-after ] bi* ;
 
 : find-use-position ( live-interval new -- n )
     [ uses>> ] [ start>> '[ _ >= ] ] bi* find nip 1/0. or ;
@@ -72,47 +91,12 @@ ERROR: bad-live-ranges interval ;
     [ uses>> first ] [ second ] bi* > ;
 
 : spill-new ( new pair -- )
-    drop
-    {
-        [ trim-after-ranges ]
-        [ compute-start/end ]
-        [ assign-reload ]
-        [ add-unhandled ]
-    } cleave ;
-
-: spill-live-out? ( live-interval n -- ? ) [ uses>> last ] dip < ;
-
-: spill-live-out ( live-interval -- )
-    ! The interval has no more usages after the spill location.  This
-    !  means it is the first child of an interval that was split.  We
-    ! spill the value and let the resolve pass insert a reload later.
-    {
-        [ trim-before-ranges ]
-        [ compute-start/end ]
-        [ assign-spill ]
-        [ add-handled ]
-    } cleave ;
-
-: spill-live-in? ( live-interval n -- ? ) [ uses>> first ] dip > ;
-
-: spill-live-in ( live-interval -- )
-    ! The interval does not have any usages before the spill location.
-    !  This means it is the second child of an interval that was
-    ! split.  We reload the value and let the resolve pass insert a
-    ! split later.
-    {
-        [ trim-after-ranges ]
-        [ compute-start/end ]
-        [ assign-reload ]
-        [ add-unhandled ]
-    } cleave ;
+    drop spill-after add-unhandled ;
 
 : spill ( live-interval n -- )
-    {
-        { [ 2dup spill-live-out? ] [ drop spill-live-out ] }
-        { [ 2dup spill-live-in? ] [ drop spill-live-in ] }
-        [ split-and-spill [ add-handled ] [ add-unhandled ] bi* ]
-    } cond ;
+    split-for-spill
+    [ [ add-handled ] when* ]
+    [ [ add-unhandled ] when* ] bi* ;
 
 :: spill-intersecting-active ( new reg -- )
     ! If there is an active interval using 'reg' (there should be at
@@ -149,8 +133,8 @@ ERROR: bad-live-ranges interval ;
     ! A register would be available for part of the new
     ! interval's lifetime if all active and inactive intervals
     ! using that register were split and spilled.
-    [ second 1 - split-and-spill add-unhandled ] keep
-    spill-available ;
+    [ second 1 - split-for-spill [ add-unhandled ] when* ] keep
+    '[ _ spill-available ] when* ;
 
 : assign-blocked-register ( new -- )
     dup spill-status {
index 0a67710bc80d1d728eb1282d6071304a7ceb1d36..874523d70a7fb57e2653fda036d4cd9425390ef2 100644 (file)
@@ -27,9 +27,6 @@ IN: compiler.cfg.linear-scan.allocation.splitting
 : split-uses ( uses n -- before after )
     '[ _ <= ] partition ;
 
-: record-split ( live-interval before after -- )
-    [ >>split-before ] [ >>split-after ] bi* drop ; inline
-
 ERROR: splitting-too-early ;
 
 ERROR: splitting-too-late ;
@@ -56,7 +53,6 @@ ERROR: splitting-atomic-interval ;
     live-interval clone :> after
     live-interval uses>> n split-uses before after [ (>>uses) ] bi-curry@ bi*
     live-interval ranges>> n split-ranges before after [ (>>ranges) ] bi-curry@ bi*
-    live-interval before after record-split
     before split-before
     after split-after ;
 
index a350ee5f43b5b42a542673a00bbe52e94042c4fd..c9c1b77a0dedb68240fc7194cfac7c2474ba7483 100644 (file)
@@ -5,25 +5,12 @@ namespaces prettyprint compiler.cfg.linear-scan.live-intervals
 compiler.cfg.linear-scan.allocation compiler.cfg assocs ;
 IN: compiler.cfg.linear-scan.debugger
 
-: check-assigned ( live-intervals -- )
-    [
-        reg>>
-        [ "Not all intervals have registers" throw ] unless
-    ] each ;
-
-: split-children ( live-interval -- seq )
-    dup split-before>> [
-        [ split-before>> ] [ split-after>> ] bi
-        [ split-children ] bi@
-        append
-    ] [ 1array ] if ;
-
 : check-linear-scan ( live-intervals machine-registers -- )
     [
         [ clone ] map dup [ [ vreg>> ] keep ] H{ } map>assoc
         live-intervals set
-    ] dip allocate-registers
-    [ split-children ] map concat check-assigned ;
+    ] dip
+    allocate-registers drop ;
 
 : picture ( uses -- str )
     dup last 1 + CHAR: space <string>
index 1673b1b365897852f72c5c95a1a58975e6b56216..2164cef4291758c8918a1f9d1783911bc9a65a09 100644 (file)
@@ -75,6 +75,9 @@ check-numbering? on
     { T{ live-range f 0 5 } } 0 split-ranges
 ] unit-test
 
+H{ { int-regs 10 } { float-regs 20 } } clone spill-counts set
+H{ } spill-slots set
+
 [
     T{ live-interval
        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
@@ -82,6 +85,7 @@ check-numbering? on
        { end 2 }
        { uses V{ 0 1 } }
        { ranges V{ T{ live-range f 0 2 } } }
+       { spill-to 10 }
     }
     T{ live-interval
        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
@@ -89,6 +93,7 @@ check-numbering? on
        { end 5 }
        { uses V{ 5 } }
        { ranges V{ T{ live-range f 5 5 } } }
+       { reload-from 10 }
     }
 ] [
     T{ live-interval
@@ -97,82 +102,61 @@ check-numbering? on
        { end 5 }
        { uses V{ 0 1 5 } }
        { ranges V{ T{ live-range f 0 5 } } }
-    } 2 split-for-spill [ f >>split-next ] bi@
+    } 2 split-for-spill
 ] unit-test
 
 [
     T{ live-interval
-       { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+       { vreg T{ vreg { reg-class int-regs } { n 2 } } }
        { start 0 }
        { end 1 }
        { uses V{ 0 } }
        { ranges V{ T{ live-range f 0 1 } } }
+       { spill-to 11 }
     }
     T{ live-interval
-       { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+       { vreg T{ vreg { reg-class int-regs } { n 2 } } }
        { start 1 }
        { end 5 }
        { uses V{ 1 5 } }
        { ranges V{ T{ live-range f 1 5 } } }
+       { reload-from 11 }
     }
 ] [
     T{ live-interval
-       { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+       { vreg T{ vreg { reg-class int-regs } { n 2 } } }
        { start 0 }
        { end 5 }
        { uses V{ 0 1 5 } }
        { ranges V{ T{ live-range f 0 5 } } }
-    } 0 split-for-spill [ f >>split-next ] bi@
+    } 0 split-for-spill
 ] unit-test
 
 [
     T{ live-interval
-       { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+       { vreg T{ vreg { reg-class int-regs } { n 3 } } }
        { start 0 }
        { end 1 }
        { uses V{ 0 } }
        { ranges V{ T{ live-range f 0 1 } } }
+       { spill-to 12 }
     }
     T{ live-interval
-       { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+       { vreg T{ vreg { reg-class int-regs } { n 3 } } }
        { start 20 }
        { end 30 }
        { uses V{ 20 30 } }
        { ranges V{ T{ live-range f 20 30 } } }
+       { reload-from 12 }
     }
 ] [
     T{ live-interval
-       { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+       { vreg T{ vreg { reg-class int-regs } { n 3 } } }
        { start 0 }
        { end 30 }
        { uses V{ 0 20 30 } }
        { ranges V{ T{ live-range f 0 8 } T{ live-range f 10 18 } T{ live-range f 20 30 } } }
-    } 10 split-for-spill [ f >>split-next ] bi@
-] unit-test
-
-[
-    T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-        { start 0 }
-        { end 4 }
-        { uses V{ 0 1 4 } }
-        { ranges V{ T{ live-range f 0 4 } } }
-    }
-    T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-        { start 5 }
-        { end 10 }
-        { uses V{ 5 10 } }
-        { ranges V{ T{ live-range f 5 10 } } }
-    }
-] [
-    T{ live-interval
-       { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-       { start 0 }
-       { end 10 }
-       { uses V{ 0 1 4 5 10 } }
-       { ranges V{ T{ live-range f 0 10 } } }
-    } 4 split-to-fit [ f >>split-next ] bi@
+    } 10 split-for-spill
 ] unit-test
 
 [
@@ -352,6 +336,78 @@ check-numbering? on
     check-linear-scan
 ] must-fail
 
+! Problem with spilling intervals with no more usages after the spill location
+
+[ ] [
+    {
+        T{ live-interval
+           { vreg T{ vreg { n 1 } { reg-class int-regs } } }
+           { start 0 }
+           { end 20 }
+           { uses V{ 0 10 20 } }
+           { ranges V{ T{ live-range f 0 2 } T{ live-range f 10 20 } } }
+        }
+        T{ live-interval
+           { vreg T{ vreg { n 2 } { reg-class int-regs } } }
+           { start 0 }
+           { end 20 }
+           { uses V{ 0 10 20 } }
+           { ranges V{ T{ live-range f 0 2 } T{ live-range f 10 20 } } }
+        }
+        T{ live-interval
+           { vreg T{ vreg { n 3 } { reg-class int-regs } } }
+           { start 4 }
+           { end 8 }
+           { uses V{ 6 } }
+           { ranges V{ T{ live-range f 4 8 } } }
+        }
+        T{ live-interval
+           { vreg T{ vreg { n 4 } { reg-class int-regs } } }
+           { start 4 }
+           { end 8 }
+           { uses V{ 8 } }
+           { ranges V{ T{ live-range f 4 8 } } }
+        }
+
+        ! This guy will invoke the 'spill partially available' code path
+        T{ live-interval
+           { vreg T{ vreg { n 5 } { reg-class int-regs } } }
+           { start 4 }
+           { end 8 }
+           { uses V{ 8 } }
+           { ranges V{ T{ live-range f 4 8 } } }
+        }
+    }
+    H{ { int-regs { "A" "B" } } }
+    check-linear-scan
+] unit-test
+
+
+! Test spill-new code path
+
+[ ] [
+    {
+        T{ live-interval
+           { vreg T{ vreg { n 1 } { reg-class int-regs } } }
+           { start 0 }
+           { end 10 }
+           { uses V{ 0 6 10 } }
+           { ranges V{ T{ live-range f 0 10 } } }
+        }
+
+        ! This guy will invoke the 'spill new' code path
+        T{ live-interval
+           { vreg T{ vreg { n 5 } { reg-class int-regs } } }
+           { start 2 }
+           { end 8 }
+           { uses V{ 8 } }
+           { ranges V{ T{ live-range f 2 8 } } }
+        }
+    }
+    H{ { int-regs { "A" } } }
+    check-linear-scan
+] unit-test
+
 SYMBOL: available
 
 SYMBOL: taken
@@ -1493,9 +1549,9 @@ V{
     T{ ##return }
 } 3 test-bb
 
-1 get 1vector 0 get (>>successors)
-2 get 3 get V{ } 2sequence 1 get (>>successors)
-3 get 1vector 2 get (>>successors)
+0 1 edge
+1 { 2 3 } edges
+2 3 edge
 
 SYMBOL: linear-scan-result
 
@@ -1508,9 +1564,7 @@ SYMBOL: linear-scan-result
         flatten-cfg 1array mr.
     ] with-scope ;
 
-! This test has a critical edge -- do we care about these?
-
-! [ { 1 2 } test-linear-scan-on-cfg ] unit-test
+[ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
 
 ! Bug in inactive interval handling
 ! [ rot dup [ -rot ] when ]
@@ -1761,11 +1815,6 @@ test-diamond
 
 [ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
 
-[ ] [
-    1 get instructions>> first regs>> V int-regs 0 swap at
-    2 get instructions>> first regs>> V int-regs 1 swap at assert=
-] unit-test
-
 ! Not until splitting is finished
 ! [ _copy ] [ 3 get instructions>> second class ] unit-test
 
@@ -1845,11 +1894,11 @@ V{
     T{ ##return }
 } 6 test-bb
 
-0 get 1 get V{ } 1sequence >>successors drop
-1 get 2 get 3 get V{ } 2sequence >>successors drop
-2 get 4 get V{ } 1sequence >>successors drop
-3 get 4 get V{ } 1sequence >>successors drop
-4 get 5 get 6 get V{ } 2sequence >>successors drop
+0 1 edge
+1 { 2 3 } edges
+2 4 edge
+3 4 edge
+4 { 5 6 } edges
 
 [ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
 
@@ -1905,14 +1954,14 @@ V{
     T{ ##return }
 } 9 test-bb
 
-0 get 1 get 1vector >>successors drop
-1 get 2 get 7 get V{ } 2sequence >>successors drop
-7 get 8 get 1vector >>successors drop
-8 get 9 get 1vector >>successors drop
-2 get 3 get 5 get V{ } 2sequence >>successors drop
-3 get 4 get 1vector >>successors drop
-4 get 9 get 1vector >>successors drop
-5 get 6 get 1vector >>successors drop
+0 1 edge
+1 { 2 7 } edges
+7 8 edge
+8 9 edge
+2 { 3 5 } edges
+3 4 edge
+4 9 edge
+5 6 edge
 
 [ ] [ { 1 2 3 4 } test-linear-scan-on-cfg ] unit-test
 
@@ -2088,11 +2137,11 @@ V{
     T{ ##return }
 } 5 test-bb
 
-0 get 1 get 1vector >>successors drop
-1 get 2 get 4 get V{ } 2sequence >>successors drop
-2 get 3 get 1vector >>successors drop
-3 get 5 get 1vector >>successors drop
-4 get 5 get 1vector >>successors drop
+0 1 edge
+1 { 2 4 } edges
+2 3 edge
+3 5 edge
+4 5 edge
 
 [ ] [ { 1 2 3 4 5 } test-linear-scan-on-cfg ] unit-test
 
@@ -2235,12 +2284,12 @@ V{
     T{ ##return }
 } 6 test-bb
 
-0 get 1 get 1vector >>successors drop
-1 get 2 get 5 get V{ } 2sequence >>successors drop
-2 get 3 get 1vector >>successors drop
-3 get 4 get 1vector >>successors drop
-4 get 6 get 1vector >>successors drop
-5 get 6 get 1vector >>successors drop
+0 1 edge
+1 { 2 5 } edges
+2 3 edge
+3 4 edge
+4 6 edge
+5 6 edge
 
 [ ] [ { 1 2 3 4 5 } test-linear-scan-on-cfg ] unit-test
 
@@ -2368,8 +2417,8 @@ V{
     T{ ##return }
 } 2 test-bb
 
-0 get 1 get 1vector >>successors drop
-1 get 2 get 1vector >>successors drop
+0 1 edge
+1 2 edge
 
 [ ] [ { 1 2 3 } test-linear-scan-on-cfg ] unit-test
 
@@ -2393,7 +2442,7 @@ V{
     T{ ##return }
 } 2 test-bb
 
-0 get 1 get 2 get V{ } 2sequence >>successors drop
+0 { 1 2 } edges
 
 [ ] [ { 1 2 3 } test-linear-scan-on-cfg ] unit-test
 
index 77aae14503eafc8a6eb7e64b4974cee23aecd57e..48bef197e62b2284ae55ec576a420296369a03c9 100644 (file)
@@ -13,7 +13,6 @@ C: <live-range> live-range
 TUPLE: live-interval
 vreg
 reg spill-to reload-from
-split-before split-after split-next
 start end ranges uses
 copy-from ;
 
index b1b44cde44d68a24ec1e677f6f4b1d57851dedfa..ee3595dd065a598f740f4abd8c54e22f7c6874ba 100644 (file)
@@ -1,6 +1,6 @@
 IN: compiler.cfg.linear-scan.resolve.tests
 USING: compiler.cfg.linear-scan.resolve tools.test kernel namespaces
-compiler.cfg.instructions cpu.architecture make
+compiler.cfg.instructions cpu.architecture make sequences
 compiler.cfg.linear-scan.allocation.state ;
 
 [
index 932e3dc6d6e32c9c11eee775ba9a57fe6c313755..b1fe1572cdaae94c8f9fa3c1776d6096f8a36d39 100644 (file)
@@ -26,10 +26,9 @@ SYMBOL: spill-temps
     2dup = [ 2drop ] [ vreg reg-class>> add-mapping ] if ;
 
 : compute-mappings ( bb to -- mappings )
-    [
-        dup live-in keys
-        [ resolve-value-data-flow ] with with each
-    ] { } make ;
+    dup live-in dup assoc-empty? [ 3drop f ] [
+        [ keys [ resolve-value-data-flow ] with with each ] { } make
+    ] if ;
 
 : memory->register ( from to -- )
     swap [ first2 ] [ first n>> ] bi* _reload ;
index 97fb3205c2b5c3e6b36e81219d54f9fa418af2f5..cbeb301901b12dc4dbf2425598c3301975af712f 100755 (executable)
@@ -98,15 +98,18 @@ M: ##dispatch linearize-insn
 
 M: ##gc linearize-insn
     nip
-    [ temp1>> ]
-    [ temp2>> ]
-    [
-        live-values>>
-        [ compute-gc-roots ]
-        [ count-gc-roots ]
-        [ gc-roots-size ]
-        tri
-    ] tri
+    {
+        [ temp1>> ]
+        [ temp2>> ]
+        [
+            live-values>>
+            [ compute-gc-roots ]
+            [ count-gc-roots ]
+            [ gc-roots-size ]
+            tri
+        ]
+        [ uninitialized-locs>> ]
+    } cleave
     _gc ;
 
 : linearize-basic-blocks ( cfg -- insns )
index eb497a9bae8f766dd65d1a2021cb695f19cae35b..0bb5f85fa5e177ce8123c1a620927bef51564357 100644 (file)
@@ -29,7 +29,7 @@ V{
     T{ ##return }
 } 3 test-bb
 
-1 get 2 get 3 get V{ } 2sequence >>successors drop
+1 { 2 3 } edges
 
 test-liveness
 
@@ -55,7 +55,7 @@ V{
     T{ ##return }
 } 2 test-bb
 
-1 get 2 get 1vector >>successors drop
+1 2 edge
 
 test-liveness
 
index 9fa22d22b15339c629e668f2e74322f777ef296b..82af084f06ddc5b2d2f4e2f1426aad7a269bede8 100644 (file)
@@ -2,13 +2,13 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel namespaces deques accessors sets sequences assocs fry
 hashtables dlists compiler.cfg.def-use compiler.cfg.instructions
-compiler.cfg.rpo compiler.cfg.liveness ;
+compiler.cfg.rpo compiler.cfg.liveness compiler.cfg.utilities ;
 IN: compiler.cfg.liveness.ssa
 
 ! TODO: merge with compiler.cfg.liveness
 
 ! Assoc mapping basic blocks to sequences of sets of vregs; each sequence
-! is in conrrespondence with a predecessor
+! is in correspondence with a predecessor
 SYMBOL: phi-live-ins
 
 : phi-live-in ( predecessor basic-block -- set ) phi-live-ins get at at ;
@@ -22,16 +22,14 @@ SYMBOL: work-list
     [ live-out ] keep instructions>> transfer-liveness ;
 
 : compute-phi-live-in ( basic-block -- phi-live-in )
-    instructions>> [ ##phi? ] filter [ f ] [
-        H{ } clone [
-            '[ inputs>> [ swap _ conjoin-at ] assoc-each ] each
-        ] keep
-    ] if-empty ;
+    H{ } clone [
+        '[ inputs>> [ swap _ conjoin-at ] assoc-each ] each-phi
+    ] keep ;
 
 : update-live-in ( basic-block -- changed? )
     [ [ compute-live-in ] keep live-ins get maybe-set-at ]
     [ [ compute-phi-live-in ] keep phi-live-ins get maybe-set-at ]
-    bi and ; 
+    bi or ;
 
 : compute-live-out ( basic-block -- live-out )
     [ successors>> [ live-in ] map ]
@@ -55,3 +53,7 @@ SYMBOL: work-list
     H{ } clone live-outs set
     dup post-order add-to-work-list
     work-list get [ liveness-step ] slurp-deque ;
+
+: live-in? ( vreg bb -- ? ) live-in key? ;
+
+: live-out? ( vreg bb -- ? ) live-out key? ;
\ No newline at end of file
index 73ae3ee242365c07933ac300dd23185a35419723..c972197dd8459e22d6e76b16f0c678fc59aba0d0 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel accessors combinators fry sequences assocs compiler.cfg.rpo
-compiler.cfg.instructions ;
+compiler.cfg.instructions compiler.cfg.utilities ;
 IN: compiler.cfg.predecessors
 
 : update-predecessors ( bb -- )
@@ -14,9 +14,7 @@ IN: compiler.cfg.predecessors
     ] change-inputs drop ;
 
 : update-phis ( bb -- )
-    dup instructions>> [
-        dup ##phi? [ update-phi ] [ 2drop ] if
-    ] with each ;
+    dup [ update-phi ] with each-phi ;
 
 : compute-predecessors ( cfg -- cfg' )
     {
index da0f320130aec4819b86ec6b412d756b1e369fcf..e7ba5bbabacb3593445494c27704a1cc50464942 100644 (file)
@@ -34,9 +34,9 @@ V{
     T{ ##return }
 } 3 test-bb
 
-0 get 1 get 2 get V{ } 2sequence >>successors drop
-1 get 3 get 1vector >>successors drop
-2 get 3 get 1vector >>successors drop
+0 { 1 2 } edges
+1 3 edge
+2 3 edge
 
 : test-ssa ( -- )
     cfg new 0 get >>entry
@@ -93,12 +93,12 @@ V{ T{ ##replace f V int-regs 0 D 0 } } 4 test-bb
 V{ } 5 test-bb
 V{ } 6 test-bb
 
-0 get 1 get 5 get V{ } 2sequence >>successors drop
-1 get 2 get 3 get V{ } 2sequence >>successors drop
-2 get 4 get 1vector >>successors drop
-3 get 4 get 1vector >>successors drop
-4 get 6 get 1vector >>successors drop
-5 get 6 get 1vector >>successors drop
+0 { 1 5 } edges
+1 { 2 3 } edges
+2 4 edge
+3 4 edge
+4 6 edge
+5 6 edge
 
 [ ] [ test-ssa ] unit-test
 
index 7691d0e6ce0c8e9dd00da933c38290f89aff8f3f..433dcfee64996742a9d15c42bc15582ea566d6a1 100644 (file)
@@ -17,11 +17,11 @@ V{ } 3 test-bb
 V{ } 4 test-bb
 V{ } 5 test-bb
 
-0 get 1 get 2 get V{ } 2sequence >>successors drop
-1 get 3 get 1vector >>successors drop
-2 get 4 get 1vector >>successors drop
-3 get 4 get 1vector >>successors drop
-4 get 5 get 1vector >>successors drop
+0 { 1 2 } edges
+1 3 edge
+2 4 edge
+3 4 edge
+4 5 edge
 
 [ ] [ test-tdmsc ] unit-test
 
@@ -38,12 +38,12 @@ V{ } 4 test-bb
 V{ } 5 test-bb
 V{ } 6 test-bb
 
-0 get 1 get 5 get V{ } 2sequence >>successors drop
-1 get 2 get 3 get V{ } 2sequence >>successors drop
-2 get 4 get 1vector >>successors drop
-3 get 4 get 1vector >>successors drop
-4 get 6 get 1vector >>successors drop
-5 get 6 get 1vector >>successors drop
+0 { 1 5 } edges
+1 { 2 3 } edges
+2 4 edge
+3 4 edge
+4 6 edge
+5 6 edge
 
 [ ] [ test-tdmsc ] unit-test
 
@@ -61,13 +61,13 @@ V{ } 5 test-bb
 V{ } 6 test-bb
 V{ } 7 test-bb
 
-0 get 1 get 1vector >>successors drop
-1 get 2 get 1vector >>successors drop
-2 get 3 get 6 get V{ } 2sequence >>successors drop
-3 get 4 get 1vector >>successors drop
-6 get 7 get 1vector >>successors drop
-4 get 5 get 1vector >>successors drop
-5 get 2 get 1vector >>successors drop
+0 1 edge
+1 2 edge
+2 { 3 6 } edges
+3 4 edge
+6 7 edge
+4 5 edge
+5 2 edge
 
 [ ] [ test-tdmsc ] unit-test
 
diff --git a/basis/compiler/cfg/ssa/cssa/cssa.factor b/basis/compiler/cfg/ssa/cssa/cssa.factor
new file mode 100644 (file)
index 0000000..37fa790
--- /dev/null
@@ -0,0 +1,21 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors assocs kernel locals
+compiler.cfg.rpo
+compiler.cfg.hats
+compiler.cfg.utilities
+compiler.cfg.instructions ;
+IN: compiler.cfg.ssa.cssa
+
+! Convert SSA to conventional SSA.
+
+:: insert-copy ( bb src -- bb dst )
+    i :> dst
+    bb [ dst src ##copy ] add-instructions
+    bb dst ;
+
+: convert-phi ( ##phi -- )
+    [ [ insert-copy ] assoc-map ] change-inputs drop ;
+
+: construct-cssa ( cfg -- )
+    [ [ convert-phi ] each-phi ] each-basic-block ;
\ No newline at end of file
diff --git a/basis/compiler/cfg/ssa/destruction/copies/copies.factor b/basis/compiler/cfg/ssa/destruction/copies/copies.factor
deleted file mode 100644 (file)
index 063704e..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-! Copyright (C) 2009 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: accessors assocs hashtables fry kernel make namespaces
-sequences compiler.cfg.ssa.destruction.state compiler.cfg.parallel-copy ;
-IN: compiler.cfg.ssa.destruction.copies
-
-ERROR: bad-copy ;
-
-: compute-copies ( assoc -- assoc' )
-    dup assoc-size <hashtable> [
-        '[
-            [
-                2dup eq? [ 2drop ] [
-                    _ 2dup key?
-                    [ bad-copy ] [ set-at ] if
-                ] if
-            ] with each
-        ] assoc-each
-    ] keep ;
-
-: insert-copies ( -- )
-    waiting get [
-        [ instructions>> building ] dip '[
-            building get pop
-            _ compute-copies parallel-copy
-            ,
-        ] with-variable
-    ] assoc-each ;
\ No newline at end of file
index c650782582a0813356f82e30335710ba5df7c465..3e6172229ab86ee6da122b5d5502de3ad6eef873 100644 (file)
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors assocs fry kernel locals math math.order
-sequences namespaces sets
+USING: accessors arrays assocs fry kernel namespaces
+sequences sequences.deep
+sets vectors
 compiler.cfg.rpo
 compiler.cfg.def-use
-compiler.cfg.utilities
+compiler.cfg.renaming
 compiler.cfg.dominance
 compiler.cfg.instructions
 compiler.cfg.liveness.ssa
-compiler.cfg.critical-edges
-compiler.cfg.ssa.destruction.state
-compiler.cfg.ssa.destruction.forest
-compiler.cfg.ssa.destruction.copies
-compiler.cfg.ssa.destruction.renaming
-compiler.cfg.ssa.destruction.live-ranges
-compiler.cfg.ssa.destruction.process-blocks ;
+compiler.cfg.ssa.cssa
+compiler.cfg.ssa.interference
+compiler.cfg.ssa.interference.live-ranges
+compiler.cfg.utilities
+compiler.utilities ;
 IN: compiler.cfg.ssa.destruction
 
-! Based on "Fast Copy Coalescing and Live-Range Identification"
-! http://www.cs.ucsd.edu/classes/sp02/cse231/kenpldi.pdf
+! Maps vregs to leaders.
+SYMBOL: leader-map
+
+: leader ( vreg -- vreg' ) leader-map get compress-path ;
+
+! Maps leaders to equivalence class elements.
+SYMBOL: class-element-map
+
+: class-elements ( vreg -- elts ) class-element-map get at ;
+
+! Sequence of vreg pairs
+SYMBOL: copies
+
+: init-coalescing ( -- )
+    H{ } clone leader-map set
+    H{ } clone class-element-map set
+    V{ } clone copies set ;
+
+: classes-interfere? ( vreg1 vreg2 -- ? )
+    [ leader ] bi@ 2dup eq? [ 2drop f ] [
+        [ class-elements flatten ] bi@ sets-interfere?
+    ] if ;
 
-! Dominance, liveness and def-use need to be computed
+: update-leaders ( vreg1 vreg2 -- )
+    swap leader-map get set-at ;
 
-: process-blocks ( cfg -- )
-    [ [ process-block ] if-has-phis ] each-basic-block ;
+: merge-classes ( vreg1 vreg2 -- )
+    [ [ class-elements ] bi@ push ]
+    [ drop class-element-map get delete-at ] 2bi ;
 
-SYMBOL: seen
+: eliminate-copy ( vreg1 vreg2 -- )
+    [ leader ] bi@
+    2dup eq? [ 2drop ] [
+        [ update-leaders ] [ merge-classes ] 2bi
+    ] if ;
 
-:: visit-renaming ( dst assoc src bb -- )
-    src seen get key? [
-        src dst bb waiting-for push-at
-        src assoc delete-at
-    ] [ src seen get conjoin ] if ;
+: introduce-vreg ( vreg -- )
+    [ leader-map get conjoin ]
+    [ [ 1vector ] keep class-element-map get set-at ] bi ;
 
-:: break-interferences ( -- )
-    V{ } clone seen set
-    renaming-sets get [| dst assoc |
-        assoc [| src bb |
-            dst assoc src bb visit-renaming
-        ] assoc-each
+GENERIC: prepare-insn ( insn -- )
+
+M: ##copy prepare-insn
+    [ dst>> ] [ src>> ] bi 2array copies get push ;
+
+M: ##phi prepare-insn
+    [ dst>> ] [ inputs>> values ] bi
+    [ eliminate-copy ] with each ;
+
+M: insn prepare-insn drop ;
+
+: prepare-block ( bb -- )
+    instructions>> [ prepare-insn ] each ;
+
+: prepare-coalescing ( cfg -- )
+    init-coalescing
+    defs get keys [ introduce-vreg ] each
+    [ prepare-block ] each-basic-block ;
+
+: process-copies ( -- )
+    copies get [
+        2dup classes-interfere?
+        [ 2drop ] [ eliminate-copy ] if
     ] assoc-each ;
 
-: remove-phis-from-block ( bb -- )
-    instructions>> [ ##phi? not ] filter-here ;
+: useless-copy? ( ##copy -- ? )
+    dup ##copy? [ [ dst>> ] [ src>> ] bi eq? ] [ drop f ] if ;
 
-: remove-phis ( cfg -- )
-    [ [ remove-phis-from-block ] if-has-phis ] each-basic-block ;
+: perform-renaming ( cfg -- )
+    leader-map get keys [ dup leader ] H{ } map>assoc renamings set
+    [
+        instructions>> [
+            [ rename-insn-defs ]
+            [ rename-insn-uses ]
+            [ [ useless-copy? ] [ ##phi? ] bi or not ] tri
+        ] filter-here
+    ] each-basic-block ;
 
 : destruct-ssa ( cfg -- cfg' )
     dup cfg-has-phis? [
-        init-coalescing
-        compute-ssa-live-sets
-        dup split-critical-edges
-        dup compute-def-use
+        dup construct-cssa
+        dup compute-defs
         dup compute-dominance
+        compute-ssa-live-sets
         dup compute-live-ranges
-        dup process-blocks
-        break-interferences
+        dup prepare-coalescing
+        process-copies
         dup perform-renaming
-        insert-copies
-        dup remove-phis
     ] when ;
\ No newline at end of file
diff --git a/basis/compiler/cfg/ssa/destruction/forest/forest-tests.factor b/basis/compiler/cfg/ssa/destruction/forest/forest-tests.factor
deleted file mode 100644 (file)
index 64c04b7..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-USING: accessors compiler.cfg compiler.cfg.ssa.destruction.forest
-compiler.cfg.debugger compiler.cfg.dominance compiler.cfg.instructions
-compiler.cfg.predecessors compiler.cfg.registers compiler.cfg.def-use
-cpu.architecture kernel namespaces sequences tools.test vectors sorting
-math.order ;
-IN: compiler.cfg.ssa.destruction.forest.tests
-
-V{ T{ ##peek f V int-regs 0 D 0 } } clone 0 test-bb
-V{ T{ ##peek f V int-regs 1 D 0 } } clone 1 test-bb
-V{ T{ ##peek f V int-regs 2 D 0 } } clone 2 test-bb
-V{ T{ ##peek f V int-regs 3 D 0 } } clone 3 test-bb
-V{ T{ ##peek f V int-regs 4 D 0 } } clone 4 test-bb
-V{ T{ ##peek f V int-regs 5 D 0 } } clone 5 test-bb
-V{ T{ ##peek f V int-regs 6 D 0 } } clone 6 test-bb
-
-0 get 1 get 2 get V{ } 2sequence >>successors drop
-2 get 3 get 4 get V{ } 2sequence >>successors drop
-3 get 5 get 1vector >>successors drop
-4 get 5 get 1vector >>successors drop
-1 get 6 get 1vector >>successors drop
-5 get 6 get 1vector >>successors drop
-
-: clean-up-forest ( forest -- forest' )
-    [ [ vreg>> n>> ] compare ] sort
-    [
-        [ clean-up-forest ] change-children
-        [ number>> ] change-bb
-    ] V{ } map-as ;
-
-: test-dom-forest ( vregs -- forest )
-    cfg new 0 get >>entry
-    compute-predecessors
-    dup compute-dominance
-    compute-def-use
-    compute-dom-forest
-    clean-up-forest ;
-
-[ V{ } ] [ { } test-dom-forest ] unit-test
-
-[ V{ T{ dom-forest-node f V int-regs 0 0 V{ } } } ]
-[ { V int-regs 0 } test-dom-forest ]
-unit-test
-
-[
-    V{
-        T{ dom-forest-node
-           f
-           V int-regs 0
-           0
-           V{ T{ dom-forest-node f V int-regs 1 1 V{ } } }
-        }
-    }
-]
-[ { V int-regs 0 V int-regs 1 } test-dom-forest ]
-unit-test
-
-[
-    V{
-        T{ dom-forest-node
-           f
-           V int-regs 1
-           1
-           V{ }
-        }
-        T{ dom-forest-node
-           f
-           V int-regs 2
-           2
-           V{
-               T{ dom-forest-node f V int-regs 3 3 V{ } }
-               T{ dom-forest-node f V int-regs 4 4 V{ } }
-               T{ dom-forest-node f V int-regs 5 5 V{ } }
-           }
-        }
-        T{ dom-forest-node
-           f
-           V int-regs 6
-           6
-           V{ }
-        }
-    }
-]
-[
-    { V int-regs 1 V int-regs 6 V int-regs 2 V int-regs 3 V int-regs 4 V int-regs 5 }
-    test-dom-forest
-] unit-test
\ No newline at end of file
diff --git a/basis/compiler/cfg/ssa/destruction/forest/forest.factor b/basis/compiler/cfg/ssa/destruction/forest/forest.factor
deleted file mode 100644 (file)
index a196be1..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-! Copyright (C) 2009 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: accessors assocs fry kernel math math.order
-namespaces sequences sorting vectors compiler.cfg.def-use
-compiler.cfg.dominance compiler.cfg.registers ;
-IN: compiler.cfg.ssa.destruction.forest
-
-TUPLE: dom-forest-node vreg bb children ;
-
-<PRIVATE
-
-: sort-vregs-by-bb ( vregs -- alist )
-    defs get
-    '[ dup _ at ] { } map>assoc
-    [ [ second pre-of ] compare ] sort ;
-
-: <dom-forest-node> ( vreg bb parent -- node )
-    [ V{ } clone dom-forest-node boa dup ] dip children>> push ;
-
-: <virtual-root> ( -- node )
-    f f V{ } clone dom-forest-node boa ;
-
-: find-parent ( pre stack -- parent )
-    2dup last vreg>> def-of maxpre-of > [
-        dup pop* find-parent
-    ] [ nip last ] if ;
-
-: (compute-dom-forest) ( vreg bb stack -- )
-    [ dup pre-of ] dip [ find-parent <dom-forest-node> ] keep push ;
-
-PRIVATE>
-
-: compute-dom-forest ( vregs -- forest )
-    <virtual-root> [
-        1vector
-        [ sort-vregs-by-bb ] dip
-        '[ _ (compute-dom-forest) ] assoc-each
-    ] keep children>> ;
diff --git a/basis/compiler/cfg/ssa/destruction/interference/interference.factor b/basis/compiler/cfg/ssa/destruction/interference/interference.factor
deleted file mode 100644 (file)
index 4bb55a0..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-! Copyright (C) 2009 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: accessors assocs combinators combinators.short-circuit
-kernel math namespaces sequences locals compiler.cfg.def-use
-compiler.cfg.dominance compiler.cfg.ssa.destruction.live-ranges ;
-IN: compiler.cfg.ssa.destruction.interference
-
-<PRIVATE
-
-: kill-after-def? ( vreg1 vreg2 bb -- ? )
-    ! If first register is used after second one is defined, they interfere.
-    ! If they are used in the same instruction, no interference. If the
-    ! instruction is a def-is-use-insn, then there will be a use at +1
-    ! (instructions are 2 apart) and so outputs will interfere with
-    ! inputs.
-    [ kill-index ] [ def-index ] bi-curry bi* > ;
-
-: interferes-same-block? ( vreg1 vreg2 bb1 bb2 -- ? )
-    ! If both are defined in the same basic block, they interfere if their
-    ! local live ranges intersect.
-    drop
-    { [ kill-after-def? ] [ swapd kill-after-def? ] } 3|| ;
-
-: interferes-first-dominates? ( vreg1 vreg2 bb1 bb2 -- ? )
-    ! If vreg1 dominates vreg2, then they interfere if vreg2's definition
-    ! occurs before vreg1 is killed.
-    nip
-    kill-after-def? ;
-
-: interferes-second-dominates? ( vreg1 vreg2 bb1 bb2 -- ? )
-    ! If vreg2 dominates vreg1, then they interfere if vreg1's definition
-    ! occurs before vreg2 is killed.
-    drop
-    swapd kill-after-def? ;
-
-PRIVATE>
-
-: interferes? ( vreg1 vreg2 -- ? )
-    2dup [ def-of ] bi@ {
-        { [ 2dup eq? ] [ interferes-same-block? ] }
-        { [ 2dup dominates? ] [ interferes-first-dominates? ] }
-        { [ 2dup swap dominates? ] [ interferes-second-dominates? ] }
-        [ 2drop 2drop f ]
-    } cond ;
diff --git a/basis/compiler/cfg/ssa/destruction/live-ranges/live-ranges.factor b/basis/compiler/cfg/ssa/destruction/live-ranges/live-ranges.factor
deleted file mode 100644 (file)
index 536f5e1..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-! Copyright (C) 2009 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: accessors assocs fry kernel namespaces sequences math
-arrays compiler.cfg.def-use compiler.cfg.instructions
-compiler.cfg.liveness compiler.cfg.rpo ;
-IN: compiler.cfg.ssa.destruction.live-ranges
-
-! Live ranges for interference testing
-
-<PRIVATE
-
-SYMBOLS: local-def-indices local-kill-indices ;
-
-: record-def ( n vregs -- )
-    dup [ local-def-indices get set-at ] [ 2drop ] if ;
-
-: record-uses ( n vregs -- )
-    local-kill-indices get '[ _ set-at ] with each ;
-
-: visit-insn ( insn n -- )
-    ! Instructions are numbered 2 apart. If the instruction requires
-    ! that outputs are in different registers than the inputs, then
-    ! a use will be registered for every output immediately after
-    ! this instruction and before the next one, ensuring that outputs
-    ! interfere with inputs.
-    2 *
-    [ swap defs-vreg record-def ]
-    [ swap uses-vregs record-uses ]
-    [ over def-is-use-insn? [ 1 + swap defs-vreg 1array record-uses ] [ 2drop ] if ]
-    2tri ;
-
-SYMBOLS: def-indices kill-indices ;
-
-: compute-local-live-ranges ( bb -- )
-    H{ } clone local-def-indices set
-    H{ } clone local-kill-indices set
-    [ instructions>> [ visit-insn ] each-index ]
-    [ [ local-def-indices get ] dip def-indices get set-at ]
-    [ [ local-kill-indices get ] dip kill-indices get set-at ]
-    tri ;
-
-PRIVATE>
-
-: compute-live-ranges ( cfg -- )
-    H{ } clone def-indices set
-    H{ } clone kill-indices set
-    [ compute-local-live-ranges ] each-basic-block ;
-
-: def-index ( vreg bb -- n )
-    def-indices get at at ;
-
-ERROR: bad-kill-index vreg bb ;
-
-: kill-index ( vreg bb -- n )
-    2dup live-out key? [ 2drop 1/0. ] [
-        2dup kill-indices get at at* [ 2nip ] [
-            drop 2dup live-in key?
-            [ bad-kill-index ] [ 2drop -1/0. ] if
-        ] if
-    ] if ;
diff --git a/basis/compiler/cfg/ssa/destruction/process-blocks/process-blocks.factor b/basis/compiler/cfg/ssa/destruction/process-blocks/process-blocks.factor
deleted file mode 100644 (file)
index f8c8a4d..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-! Copyright (C) 2009 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: accessors assocs fry kernel locals math math.order arrays
-namespaces sequences sorting sets combinators combinators.short-circuit make
-compiler.cfg.def-use
-compiler.cfg.instructions
-compiler.cfg.liveness
-compiler.cfg.dominance
-compiler.cfg.ssa.destruction.state
-compiler.cfg.ssa.destruction.forest
-compiler.cfg.ssa.destruction.interference ;
-IN: compiler.cfg.ssa.destruction.process-blocks
-
-! phi-union maps a vreg to the predecessor block
-! that carries it to the phi node's block
-
-! unioned-blocks is a set of bb's which defined
-! the source vregs above
-SYMBOLS: phi-union unioned-blocks ;
-
-:: operand-live-into-phi-node's-block? ( bb src dst -- ? )
-    src bb live-in key? ;
-
-:: phi-node-is-live-out-of-operand's-block? ( bb src dst -- ? )
-    dst src def-of live-out key? ;
-
-:: operand-is-phi-node-and-live-into-operand's-block? ( bb src dst -- ? )
-    { [ src insn-of ##phi? ] [ src src def-of live-in key? ] } 0&& ;
-
-:: operand-being-renamed? ( bb src dst -- ? )
-    src processed-names get key? ;
-
-:: two-operands-in-same-block? ( bb src dst -- ? )
-    src def-of unioned-blocks get key? ;
-
-: trivial-interference? ( bb src dst -- ? )
-    {
-        [ operand-live-into-phi-node's-block? ]
-        [ phi-node-is-live-out-of-operand's-block? ]
-        [ operand-is-phi-node-and-live-into-operand's-block? ]
-        [ operand-being-renamed? ]
-        [ two-operands-in-same-block? ]
-    } 3|| ;
-
-: don't-coalesce ( bb src dst -- )
-    2nip processed-name ;
-
-:: trivial-interference ( bb src dst -- )
-    dst src bb waiting-for push-at
-    src used-by-another get push ;
-
-:: add-to-renaming-set ( bb src dst -- )
-    bb src phi-union get set-at
-    src def-of unioned-blocks get conjoin ;
-
-: process-phi-operand ( bb src dst -- )
-    {
-        { [ 2dup eq? ] [ don't-coalesce ] }
-        { [ 3dup trivial-interference? ] [ trivial-interference ] }
-        [ add-to-renaming-set ]
-    } cond ;
-
-: node-is-live-in-of-child? ( node child -- ? )
-    [ vreg>> ] [ bb>> live-in ] bi* key? ;
-
-: node-is-live-out-of-child? ( node child -- ? )
-    [ vreg>> ] [ bb>> live-out ] bi* key? ;
-
-:: insert-copy ( bb src dst -- )
-    bb src dst trivial-interference
-    src phi-union get delete-at ;
-
-:: insert-copy-for-parent ( bb src node dst -- )
-    src node vreg>> eq? [ bb src dst insert-copy ] when ;
-
-: insert-copies-for-parent ( ##phi node child -- )
-    drop
-    [ [ inputs>> ] [ dst>> ] bi ] dip
-    '[ _ _ insert-copy-for-parent ] assoc-each ;
-
-: defined-in-same-block? ( node child -- ? ) [ bb>> ] bi@ eq? ;
-
-: add-interference ( ##phi node child -- )
-    [ vreg>> ] bi@ 2array , drop ;
-
-: process-df-child ( ##phi node child -- )
-    {
-        { [ 2dup node-is-live-out-of-child? ] [ insert-copies-for-parent ] }
-        { [ 2dup node-is-live-in-of-child? ] [ add-interference ] }
-        { [ 2dup defined-in-same-block? ] [ add-interference ] }
-        [ 3drop ]
-    } cond ;
-
-: process-df-node ( ##phi node -- )
-    dup children>>
-    [ [ process-df-child ] with with each ]
-    [ nip [ process-df-node ] with each ]
-    3bi ;
-
-: process-phi-union ( ##phi dom-forest -- )
-    [ process-df-node ] with each ;
-
-: add-local-interferences ( ##phi -- )
-    [ phi-union get ] dip dst>> '[ drop _ 2array , ] assoc-each ;
-
-: compute-local-interferences ( ##phi -- pairs )
-    [
-        [ phi-union get keys compute-dom-forest process-phi-union ]
-        [ add-local-interferences ]
-        bi
-    ] { } make ;
-
-:: insert-copies-for-interference ( ##phi src -- )
-    ##phi inputs>> [| bb src' |
-        src src' eq? [ bb src ##phi dst>> insert-copy ] when
-    ] assoc-each ;
-
-: process-local-interferences ( ##phi pairs -- )
-    [
-        first2 2dup interferes?
-        [ drop insert-copies-for-interference ] [ 3drop ] if
-    ] with each ;
-
-: add-renaming-set ( ##phi -- )
-    [ phi-union get ] dip dst>> renaming-sets get set-at
-    phi-union get [ drop processed-name ] assoc-each ;
-
-: process-phi ( ##phi -- )
-    H{ } clone phi-union set
-    H{ } clone unioned-blocks set
-    [ [ inputs>> ] [ dst>> ] bi '[ _ process-phi-operand ] assoc-each ]
-    [ dup compute-local-interferences process-local-interferences ]
-    [ add-renaming-set ]
-    tri ;
-
-: process-block ( bb -- )
-    instructions>>
-    [ dup ##phi? [ process-phi t ] [ drop f ] if ] all? drop ;
diff --git a/basis/compiler/cfg/ssa/destruction/renaming/renaming.factor b/basis/compiler/cfg/ssa/destruction/renaming/renaming.factor
deleted file mode 100644 (file)
index e5c547f..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-! Copyright (C) 2009 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: accessors assocs fry kernel namespaces sequences
-compiler.cfg.ssa.destruction.state compiler.cfg.renaming compiler.cfg.rpo
-disjoint-sets ;
-IN: compiler.cfg.ssa.destruction.renaming
-
-: build-disjoint-set ( assoc -- disjoint-set )
-    <disjoint-set> dup [
-        '[
-            [ _ add-atom ]
-            [ [ drop _ add-atom ] assoc-each ]
-            bi*
-        ] assoc-each
-    ] keep ;
-
-: update-congruence-class ( dst assoc disjoint-set -- )
-    [ keys swap ] dip equate-all-with ;
-        
-: build-congruence-classes ( -- disjoint-set )
-    renaming-sets get
-    dup build-disjoint-set
-    [ '[ _ update-congruence-class ] assoc-each ] keep ;
-
-: compute-renaming ( disjoint-set -- assoc )
-    [ parents>> ] keep
-    '[ drop dup _ representative ] assoc-map ;
-
-: rename-blocks ( cfg -- )
-    [
-        instructions>> [
-            [ rename-insn-defs ]
-            [ rename-insn-uses ] bi
-        ] each
-    ] each-basic-block ;
-
-: rename-copies ( -- )
-    waiting renamings get '[
-        [
-            [ _ [ ?at drop ] [ '[ _ ?at drop ] map ] bi-curry bi* ] assoc-map
-        ] assoc-map
-    ] change ;
-
-: perform-renaming ( cfg -- )
-    build-congruence-classes compute-renaming renamings set
-    rename-blocks
-    rename-copies ;
diff --git a/basis/compiler/cfg/ssa/destruction/state/state.factor b/basis/compiler/cfg/ssa/destruction/state/state.factor
deleted file mode 100644 (file)
index 30e6952..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-! Copyright (C) 2009 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: namespaces sets kernel assocs ;
-IN: compiler.cfg.ssa.destruction.state
-
-SYMBOLS: processed-names waiting used-by-another renaming-sets ;
-
-: init-coalescing ( -- )
-    H{ } clone renaming-sets set
-    H{ } clone processed-names set
-    H{ } clone waiting set
-    V{ } clone used-by-another set ;
-
-: processed-name ( vreg -- ) processed-names get conjoin ;
-
-: waiting-for ( bb -- assoc ) waiting get [ drop H{ } clone ] cache ;
diff --git a/basis/compiler/cfg/ssa/interference/interference-tests.factor b/basis/compiler/cfg/ssa/interference/interference-tests.factor
new file mode 100644 (file)
index 0000000..f887675
--- /dev/null
@@ -0,0 +1,52 @@
+USING: accessors compiler.cfg compiler.cfg.debugger
+compiler.cfg.def-use compiler.cfg.dominance
+compiler.cfg.instructions compiler.cfg.liveness.ssa
+compiler.cfg.registers compiler.cfg.predecessors
+compiler.cfg.ssa.interference
+compiler.cfg.ssa.interference.live-ranges cpu.architecture
+kernel namespaces tools.test ;
+IN: compiler.cfg.ssa.interference.tests
+
+: test-interference ( -- )
+    cfg new 0 get >>entry
+    compute-ssa-live-sets
+    compute-predecessors
+    dup compute-defs
+    dup compute-dominance
+    compute-live-ranges ;
+
+V{
+    T{ ##peek f V int-regs 0 D 0 }
+    T{ ##peek f V int-regs 2 D 0 }
+    T{ ##copy f V int-regs 1 V int-regs 0 }
+    T{ ##copy f V int-regs 3 V int-regs 2 }
+    T{ ##branch }
+} 0 test-bb
+
+V{
+    T{ ##peek f V int-regs 4 D 0 }
+    T{ ##peek f V int-regs 5 D 0 }
+    T{ ##replace f V int-regs 3 D 0 }
+    T{ ##peek f V int-regs 6 D 0 }
+    T{ ##replace f V int-regs 5 D 0 }
+    T{ ##return }
+} 1 test-bb
+
+0 1 edge
+
+[ ] [ test-interference ] unit-test
+
+[ f ] [ V int-regs 0 V int-regs 1 vregs-interfere? ] unit-test
+[ f ] [ V int-regs 1 V int-regs 0 vregs-interfere? ] unit-test
+[ f ] [ V int-regs 2 V int-regs 3 vregs-interfere? ] unit-test
+[ f ] [ V int-regs 3 V int-regs 2 vregs-interfere? ] unit-test
+[ t ] [ V int-regs 0 V int-regs 2 vregs-interfere? ] unit-test
+[ t ] [ V int-regs 2 V int-regs 0 vregs-interfere? ] unit-test
+[ f ] [ V int-regs 1 V int-regs 3 vregs-interfere? ] unit-test
+[ f ] [ V int-regs 3 V int-regs 1 vregs-interfere? ] unit-test
+[ t ] [ V int-regs 3 V int-regs 4 vregs-interfere? ] unit-test
+[ t ] [ V int-regs 4 V int-regs 3 vregs-interfere? ] unit-test
+[ t ] [ V int-regs 3 V int-regs 5 vregs-interfere? ] unit-test
+[ t ] [ V int-regs 5 V int-regs 3 vregs-interfere? ] unit-test
+[ f ] [ V int-regs 3 V int-regs 6 vregs-interfere? ] unit-test
+[ f ] [ V int-regs 6 V int-regs 3 vregs-interfere? ] unit-test
\ No newline at end of file
diff --git a/basis/compiler/cfg/ssa/interference/interference.factor b/basis/compiler/cfg/ssa/interference/interference.factor
new file mode 100644 (file)
index 0000000..dd002ec
--- /dev/null
@@ -0,0 +1,86 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors assocs combinators combinators.short-circuit fry
+kernel math math.order sorting namespaces sequences locals
+compiler.cfg.def-use compiler.cfg.dominance
+compiler.cfg.ssa.interference.live-ranges ;
+IN: compiler.cfg.ssa.interference
+
+<PRIVATE
+
+:: kill-after-def? ( vreg1 vreg2 bb -- ? )
+    ! If first register is used after second one is defined, they interfere.
+    ! If they are used in the same instruction, no interference. If the
+    ! instruction is a def-is-use-insn, then there will be a use at +1
+    ! (instructions are 2 apart) and so outputs will interfere with
+    ! inputs.
+    vreg1 bb kill-index
+    vreg2 bb def-index > ;
+
+:: interferes-same-block? ( vreg1 vreg2 bb1 bb2 -- ? )
+    ! If both are defined in the same basic block, they interfere if their
+    ! local live ranges intersect.
+    vreg1 bb1 def-index
+    vreg2 bb1 def-index <
+    [ vreg1 vreg2 ] [ vreg2 vreg1 ] if
+    bb1 kill-after-def? ;
+
+: interferes-first-dominates? ( vreg1 vreg2 bb1 bb2 -- ? )
+    ! If vreg1 dominates vreg2, then they interfere if vreg2's definition
+    ! occurs before vreg1 is killed.
+    nip
+    kill-after-def? ;
+
+: interferes-second-dominates? ( vreg1 vreg2 bb1 bb2 -- ? )
+    ! If vreg2 dominates vreg1, then they interfere if vreg1's definition
+    ! occurs before vreg2 is killed.
+    drop
+    swapd kill-after-def? ;
+
+PRIVATE>
+
+: vregs-interfere? ( vreg1 vreg2 -- ? )
+    2dup [ def-of ] bi@ {
+        { [ 2dup eq? ] [ interferes-same-block? ] }
+        { [ 2dup dominates? ] [ interferes-first-dominates? ] }
+        { [ 2dup swap dominates? ] [ interferes-second-dominates? ] }
+        [ 2drop 2drop f ]
+    } cond ;
+
+! Debug this stuff later
+<PRIVATE
+
+: quadratic-test? ( seq1 seq2 -- ? ) [ length ] bi@ + 10 < ;
+
+: quadratic-test ( seq1 seq2 -- ? )
+    '[ _ [ vregs-interfere? ] with any? ] any? ;
+
+: sort-vregs-by-bb ( vregs -- alist )
+    defs get
+    '[ dup _ at ] { } map>assoc
+    [ second pre-of ] sort-with ;
+
+: ?last ( seq -- elt/f ) [ f ] [ last ] if-empty ; inline
+
+: find-parent ( dom current -- parent )
+    over empty? [ 2drop f ] [
+        over last over dominates? [ drop last ] [
+            over pop* find-parent
+        ] if
+    ] if ;
+
+:: linear-test ( seq1 seq2 -- ? )
+    ! Instead of sorting, SSA destruction should keep equivalence
+    ! classes sorted by merging them on append
+    V{ } clone :> dom
+    seq1 seq2 append sort-vregs-by-bb [| pair |
+        pair first :> current
+        dom current find-parent
+        dup [ current vregs-interfere? ] when
+        [ t ] [ current dom push f ] if
+    ] any? ;
+
+PRIVATE>
+
+: sets-interfere? ( seq1 seq2 -- ? )
+    quadratic-test ;
\ No newline at end of file
diff --git a/basis/compiler/cfg/ssa/interference/live-ranges/live-ranges.factor b/basis/compiler/cfg/ssa/interference/live-ranges/live-ranges.factor
new file mode 100644 (file)
index 0000000..151af8b
--- /dev/null
@@ -0,0 +1,60 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors assocs fry kernel namespaces sequences math
+arrays compiler.cfg.def-use compiler.cfg.instructions
+compiler.cfg.liveness.ssa compiler.cfg.rpo ;
+IN: compiler.cfg.ssa.interference.live-ranges
+
+! Live ranges for interference testing
+
+<PRIVATE
+
+SYMBOLS: local-def-indices local-kill-indices ;
+
+: record-def ( n vregs -- )
+    dup [ local-def-indices get set-at ] [ 2drop ] if ;
+
+: record-uses ( n vregs -- )
+    local-kill-indices get '[ _ set-at ] with each ;
+
+: visit-insn ( insn n -- )
+    ! Instructions are numbered 2 apart. If the instruction requires
+    ! that outputs are in different registers than the inputs, then
+    ! a use will be registered for every output immediately after
+    ! this instruction and before the next one, ensuring that outputs
+    ! interfere with inputs.
+    2 *
+    [ swap defs-vreg record-def ]
+    [ swap uses-vregs record-uses ]
+    [ over def-is-use-insn? [ 1 + swap defs-vreg 1array record-uses ] [ 2drop ] if ]
+    2tri ;
+
+SYMBOLS: def-indices kill-indices ;
+
+: compute-local-live-ranges ( bb -- )
+    H{ } clone local-def-indices set
+    H{ } clone local-kill-indices set
+    [ instructions>> [ visit-insn ] each-index ]
+    [ [ local-def-indices get ] dip def-indices get set-at ]
+    [ [ local-kill-indices get ] dip kill-indices get set-at ]
+    tri ;
+
+PRIVATE>
+
+: compute-live-ranges ( cfg -- )
+    H{ } clone def-indices set
+    H{ } clone kill-indices set
+    [ compute-local-live-ranges ] each-basic-block ;
+
+: def-index ( vreg bb -- n )
+    def-indices get at at ;
+
+ERROR: bad-kill-index vreg bb ;
+
+: kill-index ( vreg bb -- n )
+    2dup live-out? [ 2drop 1/0. ] [
+        2dup kill-indices get at at* [ 2nip ] [
+            drop 2dup live-in?
+            [ bad-kill-index ] [ 2drop -1/0. ] if
+        ] if
+    ] if ;
diff --git a/basis/compiler/cfg/ssa/liveness/liveness-tests.factor b/basis/compiler/cfg/ssa/liveness/liveness-tests.factor
new file mode 100644 (file)
index 0000000..20c0574
--- /dev/null
@@ -0,0 +1,292 @@
+! Copyright (C) 2009 Daniel Ehrenberg
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel tools.test namespaces sequences vectors accessors sets
+arrays math.ranges assocs
+cpu.architecture
+compiler.cfg
+compiler.cfg.ssa.liveness.private
+compiler.cfg.ssa.liveness 
+compiler.cfg.debugger
+compiler.cfg.instructions
+compiler.cfg.predecessors
+compiler.cfg.registers
+compiler.cfg.dominance
+compiler.cfg.def-use ;
+IN: compiler.cfg.ssa.liveness
+
+[ t ] [ { 1 } 1 only? ] unit-test
+[ t ] [ { } 1 only? ] unit-test
+[ f ] [ { 2 1 } 1 only? ] unit-test
+[ f ] [ { 2 } 1 only? ] unit-test
+
+: test-liveness ( -- )
+    cfg new 0 get >>entry
+    compute-predecessors
+    dup compute-defs
+    dup compute-uses
+    dup compute-dominance
+    precompute-liveness ;
+
+V{
+    T{ ##peek f V int-regs 0 D 0 }
+    T{ ##replace f V int-regs 0 D 0 }
+    T{ ##replace f V int-regs 1 D 1 }
+} 0 test-bb
+
+V{
+    T{ ##replace f V int-regs 2 D 0 }
+} 1 test-bb
+
+V{
+    T{ ##replace f V int-regs 3 D 0 }
+} 2 test-bb
+
+0 { 1 2 } edges
+
+[ ] [ test-liveness ] unit-test
+
+[ H{ } ] [ back-edge-targets get ] unit-test
+[ t ] [ 0 get R_q { 0 1 2 } [ get ] map unique = ] unit-test
+[ t ] [ 1 get R_q { 1 } [ get ] map unique = ] unit-test
+[ t ] [ 2 get R_q { 2 } [ get ] map unique = ] unit-test
+
+: self-T_q ( n -- ? )
+    get [ T_q ] [ 1array unique ] bi = ;
+
+[ t ] [ 0 self-T_q ] unit-test
+[ t ] [ 1 self-T_q ] unit-test
+[ t ] [ 2 self-T_q ] unit-test
+
+[ f ] [ V int-regs 0 0 get live-in? ] unit-test
+[ t ] [ V int-regs 1 0 get live-in? ] unit-test
+[ t ] [ V int-regs 2 0 get live-in? ] unit-test
+[ t ] [ V int-regs 3 0 get live-in? ] unit-test
+
+[ f ] [ V int-regs 0 0 get live-out? ] unit-test
+[ f ] [ V int-regs 1 0 get live-out? ] unit-test
+[ t ] [ V int-regs 2 0 get live-out? ] unit-test
+[ t ] [ V int-regs 3 0 get live-out? ] unit-test
+
+[ f ] [ V int-regs 0 1 get live-in? ] unit-test
+[ f ] [ V int-regs 1 1 get live-in? ] unit-test
+[ t ] [ V int-regs 2 1 get live-in? ] unit-test
+[ f ] [ V int-regs 3 1 get live-in? ] unit-test
+
+[ f ] [ V int-regs 0 1 get live-out? ] unit-test
+[ f ] [ V int-regs 1 1 get live-out? ] unit-test
+[ f ] [ V int-regs 2 1 get live-out? ] unit-test
+[ f ] [ V int-regs 3 1 get live-out? ] unit-test
+
+[ f ] [ V int-regs 0 2 get live-in? ] unit-test
+[ f ] [ V int-regs 1 2 get live-in? ] unit-test
+[ f ] [ V int-regs 2 2 get live-in? ] unit-test
+[ t ] [ V int-regs 3 2 get live-in? ] unit-test
+
+[ f ] [ V int-regs 0 2 get live-out? ] unit-test
+[ f ] [ V int-regs 1 2 get live-out? ] unit-test
+[ f ] [ V int-regs 2 2 get live-out? ] unit-test
+[ f ] [ V int-regs 3 2 get live-out? ] unit-test
+
+V{ } 0 test-bb
+V{ } 1 test-bb
+V{ } 2 test-bb
+V{ } 3 test-bb
+V{
+    T{ ##phi f V int-regs 2 H{ { 2 V int-regs 0 } { 3 V int-regs 1 } } }
+} 4 test-bb
+test-diamond
+
+[ ] [ test-liveness ] unit-test
+
+[ t ] [ V int-regs 0 1 get live-in? ] unit-test
+[ t ] [ V int-regs 1 1 get live-in? ] unit-test
+[ f ] [ V int-regs 2 1 get live-in? ] unit-test
+
+[ t ] [ V int-regs 0 1 get live-out? ] unit-test
+[ t ] [ V int-regs 1 1 get live-out? ] unit-test
+[ f ] [ V int-regs 2 1 get live-out? ] unit-test
+
+[ t ] [ V int-regs 0 2 get live-in? ] unit-test
+[ f ] [ V int-regs 1 2 get live-in? ] unit-test
+[ f ] [ V int-regs 2 2 get live-in? ] unit-test
+
+[ f ] [ V int-regs 0 2 get live-out? ] unit-test
+[ f ] [ V int-regs 1 2 get live-out? ] unit-test
+[ f ] [ V int-regs 2 2 get live-out? ] unit-test
+
+[ f ] [ V int-regs 0 3 get live-in? ] unit-test
+[ t ] [ V int-regs 1 3 get live-in? ] unit-test
+[ f ] [ V int-regs 2 3 get live-in? ] unit-test
+
+[ f ] [ V int-regs 0 3 get live-out? ] unit-test
+[ f ] [ V int-regs 1 3 get live-out? ] unit-test
+[ f ] [ V int-regs 2 3 get live-out? ] unit-test
+
+[ f ] [ V int-regs 0 4 get live-in? ] unit-test
+[ f ] [ V int-regs 1 4 get live-in? ] unit-test
+[ f ] [ V int-regs 2 4 get live-in? ] unit-test
+
+[ f ] [ V int-regs 0 4 get live-out? ] unit-test
+[ f ] [ V int-regs 1 4 get live-out? ] unit-test
+[ f ] [ V int-regs 2 4 get live-out? ] unit-test
+
+! This is the CFG in Figure 3 from the paper
+V{ } 0 test-bb
+V{ } 1 test-bb
+0 1 edge
+V{ } 2 test-bb
+1 2 edge
+V{
+    T{ ##peek f V int-regs 0 D 0 }
+    T{ ##peek f V int-regs 1 D 0 }
+    T{ ##peek f V int-regs 2 D 0 }
+} 3 test-bb
+V{ } 11 test-bb
+2 { 3 11 } edges
+V{
+    T{ ##replace f V int-regs 0 D 0 }
+} 4 test-bb
+V{ } 8 test-bb
+3 { 8 4 } edges
+V{
+    T{ ##replace f V int-regs 1 D 0 }
+} 9 test-bb
+8 9 edge
+V{
+    T{ ##replace f V int-regs 2 D 0 }
+} 5 test-bb
+4 5 edge
+V{ } 10 test-bb
+V{ } 6 test-bb
+5 6 edge
+9 { 6 10 } edges
+V{ } 7 test-bb
+6 { 5 7 } edges
+10 8 edge
+7 2 edge
+
+[ ] [ test-liveness ] unit-test
+
+[ t ] [ 1 get R_q 1 11 [a,b] [ get ] map unique = ] unit-test
+[ t ] [ 2 get R_q 2 11 [a,b] [ get ] map unique = ] unit-test
+[ t ] [ 3 get R_q 3 10 [a,b] [ get ] map unique = ] unit-test
+[ t ] [ 4 get R_q 4 7 [a,b] [ get ] map unique = ] unit-test
+[ t ] [ 5 get R_q 5 7 [a,b] [ get ] map unique = ] unit-test
+[ t ] [ 6 get R_q 6 7 [a,b] [ get ] map unique = ] unit-test
+[ t ] [ 7 get R_q 7 7 [a,b] [ get ] map unique = ] unit-test
+[ t ] [ 8 get R_q 6 10 [a,b] [ get ] map unique = ] unit-test
+[ t ] [ 9 get R_q 8 6 10 [a,b] remove [ get ] map unique = ] unit-test
+[ t ] [ 10 get R_q 10 10 [a,b] [ get ] map unique = ] unit-test
+[ t ] [ 11 get R_q 11 11 [a,b] [ get ] map unique = ] unit-test
+
+[ t ] [ 1 get T_q 1 get 1array unique = ] unit-test
+[ t ] [ 2 get T_q 2 get 1array unique = ] unit-test
+[ t ] [ 3 get T_q 3 get 2 get 2array unique = ] unit-test
+[ t ] [ 4 get T_q 4 get 2 get 2array unique = ] unit-test
+[ t ] [ 5 get T_q 5 get 2 get 2array unique = ] unit-test
+[ t ] [ 6 get T_q { 6 2 5 } [ get ] map unique = ] unit-test
+[ t ] [ 7 get T_q { 7 2 } [ get ] map unique = ] unit-test
+[ t ] [ 8 get T_q { 8 2 5 } [ get ] map unique = ] unit-test
+[ t ] [ 9 get T_q { 2 5 8 9 } [ get ] map unique = ] unit-test
+[ t ] [ 10 get T_q { 2 5 8 10 } [ get ] map unique = ] unit-test
+[ t ] [ 11 get T_q 11 get 1array unique = ] unit-test
+
+[ f ] [ 1 get back-edge-target? ] unit-test
+[ t ] [ 2 get back-edge-target? ] unit-test
+[ f ] [ 3 get back-edge-target? ] unit-test
+[ f ] [ 4 get back-edge-target? ] unit-test
+[ t ] [ 5 get back-edge-target? ] unit-test
+[ f ] [ 6 get back-edge-target? ] unit-test
+[ f ] [ 7 get back-edge-target? ] unit-test
+[ t ] [ 8 get back-edge-target? ] unit-test
+[ f ] [ 9 get back-edge-target? ] unit-test
+[ f ] [ 10 get back-edge-target? ] unit-test
+[ f ] [ 11 get back-edge-target? ] unit-test
+
+[ f ] [ V int-regs 0 1 get live-in? ] unit-test
+[ f ] [ V int-regs 1 1 get live-in? ] unit-test
+[ f ] [ V int-regs 2 1 get live-in? ] unit-test
+
+[ f ] [ V int-regs 0 1 get live-out? ] unit-test
+[ f ] [ V int-regs 1 1 get live-out? ] unit-test
+[ f ] [ V int-regs 2 1 get live-out? ] unit-test
+
+[ f ] [ V int-regs 0 2 get live-in? ] unit-test
+[ f ] [ V int-regs 1 2 get live-in? ] unit-test
+[ f ] [ V int-regs 2 2 get live-in? ] unit-test
+
+[ f ] [ V int-regs 0 2 get live-out? ] unit-test
+[ f ] [ V int-regs 1 2 get live-out? ] unit-test
+[ f ] [ V int-regs 2 2 get live-out? ] unit-test
+
+[ f ] [ V int-regs 0 3 get live-in? ] unit-test
+[ f ] [ V int-regs 1 3 get live-in? ] unit-test
+[ f ] [ V int-regs 2 3 get live-in? ] unit-test
+
+[ t ] [ V int-regs 0 3 get live-out? ] unit-test
+[ t ] [ V int-regs 1 3 get live-out? ] unit-test
+[ t ] [ V int-regs 2 3 get live-out? ] unit-test
+
+[ t ] [ V int-regs 0 4 get live-in? ] unit-test
+[ f ] [ V int-regs 1 4 get live-in? ] unit-test
+[ t ] [ V int-regs 2 4 get live-in? ] unit-test
+
+[ f ] [ V int-regs 0 4 get live-out? ] unit-test
+[ f ] [ V int-regs 1 4 get live-out? ] unit-test
+[ t ] [ V int-regs 2 4 get live-out? ] unit-test
+
+[ f ] [ V int-regs 0 5 get live-in? ] unit-test
+[ f ] [ V int-regs 1 5 get live-in? ] unit-test
+[ t ] [ V int-regs 2 5 get live-in? ] unit-test
+
+[ f ] [ V int-regs 0 5 get live-out? ] unit-test
+[ f ] [ V int-regs 1 5 get live-out? ] unit-test
+[ t ] [ V int-regs 2 5 get live-out? ] unit-test
+
+[ f ] [ V int-regs 0 6 get live-in? ] unit-test
+[ f ] [ V int-regs 1 6 get live-in? ] unit-test
+[ t ] [ V int-regs 2 6 get live-in? ] unit-test
+
+[ f ] [ V int-regs 0 6 get live-out? ] unit-test
+[ f ] [ V int-regs 1 6 get live-out? ] unit-test
+[ t ] [ V int-regs 2 6 get live-out? ] unit-test
+
+[ f ] [ V int-regs 0 7 get live-in? ] unit-test
+[ f ] [ V int-regs 1 7 get live-in? ] unit-test
+[ f ] [ V int-regs 2 7 get live-in? ] unit-test
+
+[ f ] [ V int-regs 0 7 get live-out? ] unit-test
+[ f ] [ V int-regs 1 7 get live-out? ] unit-test
+[ f ] [ V int-regs 2 7 get live-out? ] unit-test
+
+[ f ] [ V int-regs 0 8 get live-in? ] unit-test
+[ t ] [ V int-regs 1 8 get live-in? ] unit-test
+[ t ] [ V int-regs 2 8 get live-in? ] unit-test
+
+[ f ] [ V int-regs 0 8 get live-out? ] unit-test
+[ t ] [ V int-regs 1 8 get live-out? ] unit-test
+[ t ] [ V int-regs 2 8 get live-out? ] unit-test
+
+[ f ] [ V int-regs 0 9 get live-in? ] unit-test
+[ t ] [ V int-regs 1 9 get live-in? ] unit-test
+[ t ] [ V int-regs 2 9 get live-in? ] unit-test
+
+[ f ] [ V int-regs 0 9 get live-out? ] unit-test
+[ t ] [ V int-regs 1 9 get live-out? ] unit-test
+[ t ] [ V int-regs 2 9 get live-out? ] unit-test
+
+[ f ] [ V int-regs 0 10 get live-in? ] unit-test
+[ t ] [ V int-regs 1 10 get live-in? ] unit-test
+[ t ] [ V int-regs 2 10 get live-in? ] unit-test
+
+[ f ] [ V int-regs 0 10 get live-out? ] unit-test
+[ t ] [ V int-regs 1 10 get live-out? ] unit-test
+[ t ] [ V int-regs 2 10 get live-out? ] unit-test
+
+[ f ] [ V int-regs 0 11 get live-in? ] unit-test
+[ f ] [ V int-regs 1 11 get live-in? ] unit-test
+[ f ] [ V int-regs 2 11 get live-in? ] unit-test
+
+[ f ] [ V int-regs 0 11 get live-out? ] unit-test
+[ f ] [ V int-regs 1 11 get live-out? ] unit-test
+[ f ] [ V int-regs 2 11 get live-out? ] unit-test
diff --git a/basis/compiler/cfg/ssa/liveness/liveness.factor b/basis/compiler/cfg/ssa/liveness/liveness.factor
new file mode 100644 (file)
index 0000000..1ed6010
--- /dev/null
@@ -0,0 +1,130 @@
+! Copyright (C) 2009 Daniel Ehrenberg
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel sequences assocs accessors
+namespaces fry math sets combinators locals
+compiler.cfg.rpo
+compiler.cfg.dominance
+compiler.cfg.def-use
+compiler.cfg.instructions ;
+IN: compiler.cfg.ssa.liveness
+
+! Liveness checking on SSA IR, as described in
+! "Fast Liveness Checking for SSA-Form Programs", Sebastian Hack et al.
+! http://hal.archives-ouvertes.fr/docs/00/19/22/19/PDF/fast_liveness.pdf
+
+<PRIVATE
+
+! The sets T_q and R_q are described there
+SYMBOL: T_q-sets
+SYMBOL: R_q-sets
+
+! Targets of back edges
+SYMBOL: back-edge-targets
+
+: T_q ( q -- T_q )
+    T_q-sets get at ;
+
+: R_q ( q -- R_q )
+    R_q-sets get at ;
+
+: back-edge-target? ( block -- ? )
+    back-edge-targets get key? ;
+
+: next-R_q ( q -- R_q )
+    [ ] [ successors>> ] [ number>> ] tri
+    '[ number>> _ >= ] filter
+    [ R_q ] map assoc-combine
+    [ conjoin ] keep ;
+
+: set-R_q ( q -- )
+    [ next-R_q ] keep R_q-sets get set-at ;
+
+: set-back-edges ( q -- )
+    [ successors>> ] [ number>> ] bi '[
+        dup number>> _ < 
+        [ back-edge-targets get conjoin ] [ drop ] if
+    ] each ;
+
+: init-R_q ( -- )
+    H{ } clone R_q-sets set
+    H{ } clone back-edge-targets set ;
+
+: compute-R_q ( cfg -- )
+    init-R_q
+    post-order [
+        [ set-R_q ] [ set-back-edges ] bi
+    ] each ;
+
+! This algorithm for computing T_q uses equation (1)
+! but not the faster algorithm described in the paper
+
+: back-edges-from ( q -- edges )
+    R_q keys [
+        [ successors>> ] [ number>> ] bi
+        '[ number>> _ < ] filter
+    ] gather ;
+
+: T^_q ( q -- T^_q )
+    [ back-edges-from ] [ R_q ] bi
+    '[ _ key? not ] filter ;
+
+: next-T_q ( q -- T_q )
+    dup dup T^_q [ next-T_q keys ] map 
+    concat unique [ conjoin ] keep
+    [ swap T_q-sets get set-at ] keep ;
+
+: compute-T_q ( cfg -- )
+    H{ } T_q-sets set
+    [ next-T_q drop ] each-basic-block ;
+
+PRIVATE>
+
+: precompute-liveness ( cfg -- )
+    [ compute-R_q ] [ compute-T_q ] bi ;
+
+<PRIVATE
+
+! This doesn't take advantage of ordering T_q,a so you 
+! only have to check one if the CFG is reducible.
+! It should be changed to be more efficient.
+
+: only? ( seq obj -- ? )
+    '[ _ eq? ] all? ;
+
+: strictly-dominates? ( bb1 bb2 -- ? )
+    [ dominates? ] [ eq? not ] 2bi and ;
+
+: T_q,a ( a q -- T_q,a )
+    ! This could take advantage of the structure of dominance,
+    ! but probably I'll replace it with the algorithm that works
+    ! on reducible CFGs anyway
+    T_q keys swap def-of 
+    [ '[ _ swap strictly-dominates? ] filter ] when* ;
+
+: live? ( vreg node quot -- ? )
+    [ [ T_q,a ] [ drop uses-of ] 2bi ] dip
+    '[ [ R_q keys _ ] keep @ intersects? ] any? ; inline
+
+PRIVATE>
+
+: live-in? ( vreg node -- ? )
+    [ drop ] live? ;
+
+<PRIVATE
+
+: (live-out?) ( vreg node -- ? )
+    dup dup dup '[
+        _ = _ back-edge-target? not and
+        [ _ swap remove ] when
+    ] live? ;
+
+PRIVATE>
+
+:: live-out? ( vreg node -- ? )
+    [let | def [ vreg def-of ] |
+        {
+            { [ node def eq? ] [ vreg uses-of def only? not ] }
+            { [ def node strictly-dominates? ] [ vreg node (live-out?) ] }
+            [ f ]
+        } cond
+    ] ;
index 5c8c1343d0ec77abedff21474a2ec18c90d5b666..148104a465b6fd276bd7c113006834cdafc47985 100644 (file)
@@ -1,6 +1,6 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: namespaces assocs kernel fry accessors sequences make math
+USING: namespaces assocs kernel fry accessors sequences make math locals
 combinators compiler.cfg compiler.cfg.hats compiler.cfg.instructions
 compiler.cfg.utilities compiler.cfg.rpo compiler.cfg.stacks.local
 compiler.cfg.stacks.global compiler.cfg.stacks.height ;
@@ -8,13 +8,23 @@ IN: compiler.cfg.stacks.finalize
 
 ! This pass inserts peeks and replaces.
 
-: inserting-peeks ( from to -- assoc )
-    peek-in swap [ peek-out ] [ avail-out ] bi
-    assoc-union assoc-diff ;
-
-: inserting-replaces ( from to -- assoc )
-    [ replace-out ] [ [ kill-in ] [ replace-in ] bi ] bi*
-    assoc-union assoc-diff ;
+:: inserting-peeks ( from to -- assoc )
+    ! A peek is inserted on an edge if the destination anticipates
+    ! the stack location, the source does not anticipate it and
+    ! it is not available from the source in a register.
+    to anticip-in
+    from anticip-out from avail-out assoc-union
+    assoc-diff ;
+
+:: inserting-replaces ( from to -- assoc )
+    ! A replace is inserted on an edge if two conditions hold:
+    ! - the location is not dead at the destination, OR
+    !   the location is live at the destination but not available
+    !   at the destination
+    ! - the location is pending in the source but not the destination
+    from pending-out to pending-in assoc-diff
+    to dead-in to live-in to anticip-in assoc-diff assoc-diff
+    assoc-diff ;
 
 : each-insertion ( assoc bb quot: ( vreg loc -- ) -- )
     '[ drop [ loc>vreg ] [ _ untranslate-loc ] bi @ ] assoc-each ; inline
@@ -30,8 +40,12 @@ ERROR: bad-peek dst loc ;
     [ dup n>> 0 < [ 2drop ] [ ##replace ] if ] each-insertion ;
 
 : visit-edge ( from to -- )
-    2dup [ [ insert-peeks ] [ insert-replaces ] 2bi ] V{ } make
-    [ 2drop ] [ <simple-block> insert-basic-block ] if-empty ;
+    ! If both blocks are subroutine calls, don't bother
+    ! computing anything.
+    2dup [ kill-block? ] both? [ 2drop ] [
+        2dup [ [ insert-replaces ] [ insert-peeks ] 2bi ] V{ } make
+        [ 2drop ] [ <simple-block> insert-basic-block ] if-empty
+    ] if ;
 
 : visit-block ( bb -- )
     [ predecessors>> ] keep '[ _ visit-edge ] each ;
index 129d7e74cdc62910f7be2eddc9fb10ba7e7e2ade..c0ca385d906f7321c1d6b7ce44ae2daca7c098cb 100644 (file)
@@ -4,36 +4,56 @@ USING: assocs kernel combinators compiler.cfg.dataflow-analysis
 compiler.cfg.stacks.local ;
 IN: compiler.cfg.stacks.global
 
-! Peek analysis. Peek-in is the set of all locations anticipated at
-! the start of a basic block.
-BACKWARD-ANALYSIS: peek
+: transfer-peeked-locs ( assoc bb -- assoc' )
+    [ replace-set assoc-diff ] [ peek-set assoc-union ] bi ;
 
-M: peek-analysis transfer-set drop [ replace-set assoc-diff ] keep peek-set assoc-union ;
+! A stack location is anticipated at a location if every path from
+! the location to an exit block will read the stack location
+! before writing it.
+BACKWARD-ANALYSIS: anticip
 
-! Replace analysis. Replace-in is the set of all locations which
-! will be overwritten at some point after the start of a basic block.
-FORWARD-ANALYSIS: replace
+M: anticip-analysis transfer-set drop transfer-peeked-locs ;
 
-M: replace-analysis transfer-set drop replace-set assoc-union ;
+! A stack location is live at a location if some path from
+! the location to an exit block will read the stack location
+! before writing it.
+BACKWARD-ANALYSIS: live
 
-! Availability analysis. Avail-out is the set of all locations
-! in registers at the end of a basic block.
+M: live-analysis transfer-set drop transfer-peeked-locs ;
+
+M: live-analysis join-sets drop assoc-combine ;
+
+! A stack location is available at a location if all paths from
+! the entry block to the location load the location into a
+! register.
 FORWARD-ANALYSIS: avail
 
-M: avail-analysis transfer-set drop [ peek-set ] [ replace-set ] bi assoc-union assoc-union ;
+M: avail-analysis transfer-set
+    drop [ peek-set assoc-union ] [ replace-set assoc-union ] bi ;
+
+! A stack location is pending at a location if all paths from
+! the entry block to the location write the location.
+FORWARD-ANALYSIS: pending
+
+M: pending-analysis transfer-set
+    drop replace-set assoc-union ;
 
-! Kill analysis. Kill-in is the set of all locations
-! which are going to be overwritten.
-BACKWARD-ANALYSIS: kill
+! A stack location is dead at a location if no paths from the
+! location to the exit block read the location before writing it.
+BACKWARD-ANALYSIS: dead
 
-M: kill-analysis transfer-set drop replace-set assoc-union ;
+M: dead-analysis transfer-set
+    drop
+    [ kill-set assoc-union ]
+    [ replace-set assoc-union ] bi ;
 
 ! Main word
 : compute-global-sets ( cfg -- cfg' )
     {
-        [ compute-peek-sets ]
-        [ compute-replace-sets ]
+        [ compute-anticip-sets ]
+        [ compute-live-sets ]
+        [ compute-pending-sets ]
+        [ compute-dead-sets ]
         [ compute-avail-sets ]
-        [ compute-kill-sets ]
         [ ]
     } cleave ;
\ No newline at end of file
index 754789042a079c063fb99d48a57e3b7c149fb81b..c6558b1fb8d0d0b521200bdc605f9a9a39a4c22d 100644 (file)
@@ -1,6 +1,7 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors assocs kernel math namespaces sets make sequences
+USING: accessors assocs kernel math math.order namespaces sets make
+sequences combinators fry
 compiler.cfg
 compiler.cfg.hats
 compiler.cfg.instructions
@@ -9,17 +10,26 @@ compiler.cfg.stacks.height
 compiler.cfg.parallel-copy ;
 IN: compiler.cfg.stacks.local
 
-! Local stack analysis. We build local peek and replace sets for every basic
-! block while constructing the CFG.
+! Local stack analysis. We build three sets for every basic block
+! in the CFG:
+! - peek-set: all stack locations that the block reads before writing
+! - replace-set: all stack locations that the block writes
+! - kill-set: all stack locations which become unavailable after the
+!   block ends because of the stack height being decremented
+! This is done while constructing the CFG.
 
-SYMBOLS: peek-sets replace-sets ;
+SYMBOLS: peek-sets replace-sets kill-sets ;
 
 SYMBOL: locs>vregs
 
 : loc>vreg ( loc -- vreg ) locs>vregs get [ drop i ] cache ;
 : vreg>loc ( vreg -- loc/f ) locs>vregs get value-at ;
 
-TUPLE: current-height { d initial: 0 } { r initial: 0 } { emit-d initial: 0 } { emit-r initial: 0 } ;
+TUPLE: current-height
+{ d initial: 0 }
+{ r initial: 0 }
+{ emit-d initial: 0 }
+{ emit-r initial: 0 } ;
 
 SYMBOLS: local-peek-set local-replace-set replace-mapping ;
 
@@ -72,20 +82,31 @@ M: rs-loc translate-local-loc n>> current-height get r>> - <rs-loc> ;
         bi
     ] if ;
 
+: compute-local-kill-set ( -- assoc )
+    basic-block get current-height get
+    [ [ ds-heights get at dup ] [ d>> ] bi* [-] iota [ swap - <ds-loc> ] with map ]
+    [ [ rs-heights get at dup ] [ r>> ] bi* [-] iota [ swap - <rs-loc> ] with map ] 2bi
+    append unique ;
+
 : begin-local-analysis ( -- )
     H{ } clone local-peek-set set
     H{ } clone local-replace-set set
     H{ } clone replace-mapping set
-    current-height get 0 >>emit-d 0 >>emit-r drop
-    current-height get [ d>> ] [ r>> ] bi basic-block get record-stack-heights ;
+    current-height get
+    [ 0 >>emit-d 0 >>emit-r drop ]
+    [ [ d>> ] [ r>> ] bi basic-block get record-stack-heights ] bi ;
 
 : end-local-analysis ( -- )
     emit-changes
-    local-peek-set get basic-block get peek-sets get set-at
-    local-replace-set get basic-block get replace-sets get set-at ;
+    basic-block get {
+        [ [ local-peek-set get ] dip peek-sets get set-at ]
+        [ [ local-replace-set get ] dip replace-sets get set-at ]
+        [ [ compute-local-kill-set ] dip kill-sets get set-at ]
+    } cleave ;
 
 : clone-current-height ( -- )
     current-height [ clone ] change ;
 
 : peek-set ( bb -- assoc ) peek-sets get at ;
 : replace-set ( bb -- assoc ) replace-sets get at ;
+: kill-set ( bb -- assoc ) kill-sets get at ;
\ No newline at end of file
diff --git a/basis/compiler/cfg/stacks/stacks-tests.factor b/basis/compiler/cfg/stacks/stacks-tests.factor
new file mode 100644 (file)
index 0000000..e69de29
index 2683222fb8bc719e0c5eb7179dab3a04b186290d..1896b0a7fb5fb54e9b17657a7f12335f06cea695 100755 (executable)
@@ -13,6 +13,7 @@ IN: compiler.cfg.stacks
     H{ } clone rs-heights set
     H{ } clone peek-sets set
     H{ } clone replace-sets set
+    H{ } clone kill-sets set
     current-height new current-height set ;
 
 : end-stack-analysis ( -- )
diff --git a/basis/compiler/cfg/stacks/uninitialized/uninitialized-tests.factor b/basis/compiler/cfg/stacks/uninitialized/uninitialized-tests.factor
new file mode 100644 (file)
index 0000000..39b2f77
--- /dev/null
@@ -0,0 +1,61 @@
+IN: compiler.cfg.stacks.uninitialized.tests
+USING: compiler.cfg.stacks.uninitialized compiler.cfg.debugger
+compiler.cfg.registers compiler.cfg.instructions compiler.cfg
+compiler.cfg.predecessors cpu.architecture tools.test kernel vectors
+namespaces accessors sequences ;
+
+: test-uninitialized ( -- )
+    cfg new 0 get >>entry
+    compute-predecessors
+    compute-uninitialized-sets ;
+
+V{
+    T{ ##inc-d f 3 }
+} 0 test-bb
+
+V{
+    T{ ##replace f V int-regs 0 D 0 }
+    T{ ##replace f V int-regs 0 D 1 }
+    T{ ##replace f V int-regs 0 D 2 }
+    T{ ##inc-r f 1 }
+} 1 test-bb
+
+V{
+    T{ ##peek f V int-regs 0 D 0 }
+    T{ ##inc-d f 1 }
+} 2 test-bb
+
+0 1 edge
+1 2 edge
+
+[ ] [ 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
+
+! When merging, if a location is uninitialized in one branch and
+! initialized in another, we have to consider it uninitialized,
+! since it cannot be safely read from by a ##peek, or traced by GC.
+
+V{ } 0 test-bb
+
+V{
+    T{ ##inc-d f 1 }
+} 1 test-bb
+
+V{
+    T{ ##call f namestack }
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##return }
+} 3 test-bb
+
+0 { 1 2 } edges
+1 3 edge
+2 3 edge
+
+[ ] [ test-uninitialized ] unit-test
+
+[ V{ D 0 } ] [ 3 get uninitialized-locs ] unit-test
diff --git a/basis/compiler/cfg/stacks/uninitialized/uninitialized.factor b/basis/compiler/cfg/stacks/uninitialized/uninitialized.factor
new file mode 100644 (file)
index 0000000..97211eb
--- /dev/null
@@ -0,0 +1,76 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel sequences byte-arrays namespaces accessors classes math
+math.order fry arrays combinators compiler.cfg.registers
+compiler.cfg.instructions compiler.cfg.dataflow-analysis ;
+IN: compiler.cfg.stacks.uninitialized
+
+! Uninitialized stack location analysis.
+
+! Consider the following sequence of instructions:
+! ##inc-d 2
+! _gc
+! ##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.
+
+<PRIVATE
+
+GENERIC: visit-insn ( insn -- )
+
+: handle-inc ( n symbol -- )
+    [
+        swap {
+            { [ dup 0 < ] [ neg short tail ] }
+            { [ dup 0 > ] [ <byte-array> prepend ] }
+        } cond
+    ] 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 ;
+
+M: ##peek visit-insn
+    dup loc>> [ n>> ] [ class get ] bi ?nth 0 =
+    [ uninitialized-peek ] [ drop ] if ;
+
+M: ##replace visit-insn
+    loc>> [ n>> ] [ class get ] bi
+    2dup length < [ [ 1 ] 2dip set-nth ] [ 2drop ] if ;
+
+M: insn visit-insn drop ;
+
+: prepare ( pair -- )
+    [ first2 [ [ clone ] [ B{ } ] if* ] bi@ ] [ B{ } B{ } ] if*
+    [ ds-loc set ] [ rs-loc set ] bi* ;
+
+: visit-block ( bb -- ) instructions>> [ visit-insn ] each ;
+
+: finish ( -- pair ) ds-loc get rs-loc get 2array ;
+
+: (join-sets) ( seq1 seq2 -- seq )
+    2dup [ length ] bi@ max '[ _ 1 pad-tail ] bi@ [ bitand ] 2map ;
+
+: (uninitialized-locs) ( seq quot -- seq' )
+    [ dup length [ drop 0 = ] pusher [ 2each ] dip ] dip map ; inline
+
+PRIVATE>
+
+FORWARD-ANALYSIS: uninitialized
+
+M: uninitialized-analysis transfer-set ( pair bb analysis -- pair' )
+    drop [ prepare ] dip visit-block finish ;
+
+M: uninitialized-analysis join-sets ( sets analysis -- pair )
+    drop 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
+    ] when ;
\ No newline at end of file
index 0d0c57e0f736d87342e4779ed76c3c4305c9e070..0717f1c536238621b861ec3ca1925971b3ac2564 100644 (file)
@@ -27,19 +27,12 @@ compiler.cfg.registers cpu.architecture namespaces tools.test ;
 
 [
     V{
-        T{ ##copy f V int-regs 4 V int-regs 2 }
-        T{ ##sub f V int-regs 4 V int-regs 4 V int-regs 1 }
-        T{ ##copy f V int-regs 1 V int-regs 4 }
+        T{ ##copy f V int-regs 4 V int-regs 1 }
+        T{ ##copy f V int-regs 1 V int-regs 2 }
+        T{ ##sub f V int-regs 1 V int-regs 1 V int-regs 4 }
     }
 ] [
     {
         T{ ##sub f V int-regs 1 V int-regs 2 V int-regs 1 }
     } (convert-two-operand)
 ] unit-test
-
-! This should never come up after coalescing
-[
-    V{
-        T{ ##fixnum-add f V int-regs 2 V int-regs 4 V int-regs 2 }
-    } (convert-two-operand)
-] must-fail
index db3462bf0df8f10d8adb614a687255fb68914941..7a8b160acdcd8b9e1803968a55dc0a125d0a7240 100644 (file)
@@ -65,15 +65,11 @@ GENERIC: convert-two-operand* ( insn -- )
 
 : case-2? ( insn -- ? ) [ dst>> ] [ src2>> ] bi = ; inline
 
-ERROR: bad-case-2 insn ;
-
 : case-2 ( insn -- )
-    ! This can't work with a ##fixnum-overflow since it branches
-    dup ##fixnum-overflow? [ bad-case-2 ] when
     dup dst>> reg-class>> next-vreg
-    [ swap src1>> emit-copy ]
-    [ [ >>src1 ] [ >>dst ] bi , ]
-    [ [ src2>> ] dip emit-copy ]
+    [ swap src2>> emit-copy ]
+    [ drop [ src2>> ] [ src1>> ] bi emit-copy ]
+    [ >>src2 dup dst>> >>src1 , ]
     2tri ; inline
 
 : case-3 ( insn -- )
@@ -97,8 +93,10 @@ M: ##not convert-two-operand*
 
 M: insn convert-two-operand* , ;
 
-: (convert-two-operand) ( cfg -- cfg' )
-    [ [ convert-two-operand* ] each ] V{ } make ;
+: (convert-two-operand) ( insns -- insns' )
+    dup first kill-vreg-insn? [
+        [ [ convert-two-operand* ] each ] V{ } make
+    ] unless ;
 
 : convert-two-operand ( cfg -- cfg' )
     two-operand? [ [ (convert-two-operand) ] local-optimization ] when ;
\ No newline at end of file
index f01b10f6eb9d6475e16296776ed58942ce271e16..9246084325e482be75f550d08f2c1a6fe02ade6d 100644 (file)
@@ -43,6 +43,13 @@ SYMBOL: visited
     to predecessors>> [ dup from eq? [ drop bb ] when ] change-each
     from successors>> [ dup to eq? [ drop bb ] when ] change-each ;
 
+: add-instructions ( bb quot -- )
+    [ instructions>> building ] dip '[
+        building get pop
+        @
+        ,
+    ] with-variable ; inline
+
 : <simple-block> ( insns -- bb )
     <basic-block>
     swap >vector
@@ -58,6 +65,10 @@ SYMBOL: visited
 : if-has-phis ( bb quot: ( bb -- ) -- )
     [ dup has-phis? ] dip [ drop ] if ; inline
 
+: each-phi ( bb quot: ( ##phi -- ) -- )
+    [ instructions>> ] dip
+    '[ dup ##phi? [ @ t ] [ drop f ] if ] all? drop ; inline
+
 : predecessor ( bb -- pred )
     predecessors>> first ; inline
 
index 087b73e2c0b11800e8fa9fe75c9c6193da1045d2..519cea617a73f9dc8ddb828c67fee58be6b8ec7e 100644 (file)
@@ -1175,16 +1175,11 @@ V{
 } 3 test-bb
 
 V{
-    T{ ##phi f V int-regs 3 { } }
+    T{ ##phi f V int-regs 3 H{ { 2 V int-regs 1 } { 3 V int-regs 2 } } }
     T{ ##replace f V int-regs 3 D 0 }
     T{ ##return }
 } 4 test-bb
 
-4 get instructions>> first
-2 get V int-regs 1 2array
-3 get V int-regs 2 2array 2array
->>inputs drop
-
 test-diamond
 
 [ ] [
@@ -1296,10 +1291,10 @@ V{
     T{ ##return }
 } 5 test-bb
 
-0 get 1 get 1vector >>successors drop
-1 get 2 get 4 get V{ } 2sequence >>successors drop
-2 get 3 get 1vector >>successors drop
-4 get 5 get 1vector >>successors drop
+0 1 edge
+1 { 2 4 } edges
+2 3 edge
+4 5 edge
 
 [ ] [
     cfg new 0 get >>entry
index f9a4786eb519ecac82dfc65360c220c2a265ddfc..672ed9ce02aaf5c668c663490e6c6b5d98084ab5 100755 (executable)
@@ -4,7 +4,7 @@ USING: namespaces make math math.order math.parser sequences accessors
 kernel kernel.private layouts assocs words summary arrays
 combinators classes.algebra alien alien.c-types alien.structs
 alien.strings alien.arrays alien.complex alien.libraries sets libc
-continuations.private fry cpu.architecture classes
+continuations.private fry cpu.architecture classes locals
 source-files.errors
 compiler.errors
 compiler.alien
@@ -215,13 +215,44 @@ M: ##write-barrier generate-insn
     [ table>> ]
     tri %write-barrier ;
 
+! GC checks
+: wipe-locs ( locs temp -- )
+    '[
+        _
+        [ 0 %load-immediate ]
+        [ swap [ %replace ] with each ] bi
+    ] unless-empty ;
+
+GENERIC# save-gc-root 1 ( gc-root operand temp -- )
+
+M:: spill-slot save-gc-root ( gc-root operand temp -- )
+    temp operand n>> %reload-integer
+    gc-root temp %save-gc-root ;
+
+M: object save-gc-root drop %save-gc-root ;
+
+: save-gc-roots ( gc-roots temp -- ) '[ _ save-gc-root ] assoc-each ;
+
+GENERIC# load-gc-root 1 ( gc-root operand temp -- )
+
+M:: spill-slot load-gc-root ( gc-root operand temp -- )
+    gc-root temp %load-gc-root
+    temp operand n>> %spill-integer ;
+
+M: object load-gc-root drop %load-gc-root ;
+
+: load-gc-roots ( gc-roots temp -- ) '[ _ load-gc-root ] assoc-each ;
+
 M: _gc generate-insn
+    "no-gc" define-label
     {
-        [ temp1>> ]
-        [ temp2>> ]
-        [ gc-roots>> ]
-        [ gc-root-count>> ]
-    } cleave %gc ;
+        [ [ "no-gc" get ] dip [ temp1>> ] [ temp2>> ] bi %check-nursery ]
+        [ [ uninitialized-locs>> ] [ temp1>> ] bi wipe-locs ]
+        [ [ gc-roots>> ] [ temp1>> ] bi save-gc-roots ]
+        [ gc-root-count>> %call-gc ]
+        [ [ gc-roots>> ] [ temp1>> ] bi load-gc-roots ]
+    } cleave
+    "no-gc" resolve-label ;
 
 M: _loop-entry generate-insn drop %loop-entry ;
 
index f1d17fe4a26c03479e5dd5a09eee1e7a7e508fe7..5f06fc8d2a617d3782245aadae2b971f0783c57e 100644 (file)
@@ -2,7 +2,8 @@ USING: generalizations accessors arrays compiler kernel kernel.private
 math hashtables.private math.private namespaces sequences tools.test
 namespaces.private slots.private sequences.private byte-arrays alien
 alien.accessors layouts words definitions compiler.units io
-combinators vectors grouping make alien.c-types ;
+combinators vectors grouping make alien.c-types combinators.short-circuit
+math.order ;
 QUALIFIED: namespaces.private
 IN: compiler.tests.codegen
 
@@ -345,4 +346,59 @@ cell 4 = [
         dup [ \ vector eq? ] [ drop f ] if
         over rot [ drop ] [ nip ] if
     ] compile-call
-] unit-test
\ No newline at end of file
+] unit-test
+
+! Coalesing bug reduced from sequence-parser:take-sequence
+: coalescing-bug-1 ( a b c d -- a b c d )
+    3dup {
+        [ 2drop 0 < ]
+        [ [ drop ] 2dip length > ]
+        [ drop > ]
+    } 3|| [ 3drop f ] [ slice boa ] if swap [ [ length ] bi@ ] 2keep ;
+
+[ 0 3 f { 1 2 3 } ] [ { 1 2 3 } -10 3 "hello" coalescing-bug-1 ] unit-test
+[ 0 3 f { 1 2 3 } ] [ { 1 2 3 } 0 7 "hello" coalescing-bug-1 ] unit-test
+[ 0 3 f { 1 2 3 } ] [ { 1 2 3 } 3 2 "hello" coalescing-bug-1 ] unit-test
+[ 2 3 T{ slice f 1 3 "hello" } { 1 2 3 } ] [ { 1 2 3 } 1 3 "hello" coalescing-bug-1 ] unit-test
+
+! Another one, found by Dan
+: coalescing-bug-2 ( a -- b )
+    dup dup 10 fixnum< [ 1 fixnum+fast ] when
+    fixnum+fast 2 fixnum*fast 2 fixnum-fast 2 fixnum*fast 2 fixnum+fast ;
+
+[ 10 ] [ 1 coalescing-bug-2 ] unit-test
+[ 86 ] [ 11 coalescing-bug-2 ] unit-test
+
+! Regression in suffix-arrays code
+: coalescing-bug-3 ( from/f to/f seq -- slice )
+    [
+        [ drop 0 or ] [ length or ] bi-curry bi*
+        [ min ] keep
+    ] keep <slice> ;
+
+[ T{ slice f 0 5 "hello" } ] [ f f "hello" coalescing-bug-3 ] unit-test
+[ T{ slice f 1 5 "hello" } ] [ 1 f "hello" coalescing-bug-3 ] unit-test
+[ T{ slice f 0 3 "hello" } ] [ f 3 "hello" coalescing-bug-3 ] unit-test
+[ T{ slice f 1 3 "hello" } ] [ 1 3 "hello" coalescing-bug-3 ] unit-test
+[ T{ slice f 3 3 "hello" } ] [ 4 3 "hello" coalescing-bug-3 ] unit-test
+[ T{ slice f 5 5 "hello" } ] [ 6 f "hello" coalescing-bug-3 ] unit-test
+
+! Reduction
+: coalescing-bug-4 ( a b c -- a b c )
+     [ [ min ] keep ] dip vector? [ 1 ] [ 2 ] if ;
+
+ [ 2 3 2 ] [ 2 3 "" coalescing-bug-4 ] unit-test
+ [ 3 3 2 ] [ 4 3 "" coalescing-bug-4 ] unit-test
+ [ 3 3 2 ] [ 4 3 "" coalescing-bug-4 ] unit-test
+ [ 2 3 1 ] [ 2 3 V{ } coalescing-bug-4 ] unit-test
+ [ 3 3 1 ] [ 4 3 V{ } coalescing-bug-4 ] unit-test
+ [ 3 3 1 ] [ 4 3 V{ } coalescing-bug-4 ] unit-test
+! Global stack analysis dataflow equations are wrong
+: some-word ( a -- b ) 2 + ;
+: global-dcn-bug-1 ( a b -- c d )
+    dup [ [ drop 1 ] dip ] [ [ some-word ] dip ] if
+    dup [ [ 1 fixnum+fast ] dip ] [ [ drop 1 ] dip ] if ;
+
+[ 2 t ] [ 0 t global-dcn-bug-1 ] unit-test
+[ 1 f ] [ 0 f global-dcn-bug-1 ] unit-test
\ No newline at end of file
index eb8c0fbf98199943d65b635b56f198d8861f7a77..f1ebeded7bbaa49bb1755e0a6c4e5db1669e095c 100644 (file)
@@ -27,8 +27,8 @@ IN: compiler.tests.low-level-ir
         T{ ##epilogue }
         T{ ##return }
     } [ clone ] map 2 test-bb
-    0 get 1 get 1vector >>successors drop
-    1 get 2 get 1vector >>successors drop
+    0 1 edge
+    1 2 edge
     compile-test-cfg
     execute( -- result ) ;
 
index 5964bcee35487c7bda79561f1a83d9555758b200..0c4bf9040c3b8193100ea59c91dab0073a5ba7b1 100644 (file)
@@ -49,3 +49,7 @@ IN: compiler.tree.propagation.call-effect.tests
 [ f ] [ [ [ [ ] [ 1 ] if ] ] final-info first infer-value ] unit-test
 [ f ] [ [ [ 1 ] '[ @ ] ] final-info first infer-value ] unit-test
 [ f ] [ [ dup drop ] final-info first infer-value ] unit-test
+
+! This should not hang
+[ ] [ [ [ dup call( quot -- ) ] dup call( quot -- ) ] final-info drop ] unit-test
+[ ] [ [ [ dup curry call( quot -- ) ] dup curry call( quot -- ) ] final-info drop ] unit-test
\ No newline at end of file
index bc18aa6ec1ade38c9c04878e94361af9314dc473..ec2a4b1ece4edbaae8f3aee9a26c870c7ed347a5 100644 (file)
@@ -3,7 +3,8 @@
 USING: accessors combinators combinators.private effects fry
 kernel kernel.private make sequences continuations quotations
 words math stack-checker stack-checker.transforms
-compiler.tree.propagation.info slots.private ;
+compiler.tree.propagation.info
+compiler.tree.propagation.inlining ;
 IN: compiler.tree.propagation.call-effect
 
 ! call( and execute( have complex expansions.
@@ -130,8 +131,9 @@ ERROR: uninferable ;
 : (infer-value) ( value-info -- effect )
     dup class>> {
         { \ quotation [
-            literal>> [ uninferable ] unless* cached-effect
-            dup +unknown+ = [ uninferable ] when
+            literal>> [ uninferable ] unless*
+            dup already-inlined? [ uninferable ] when
+            cached-effect dup +unknown+ = [ uninferable ] when
         ] }
         { \ curry [
             slots>> third (infer-value)
@@ -151,7 +153,7 @@ ERROR: uninferable ;
 
 : (value>quot) ( value-info -- quot )
     dup class>> {
-        { \ quotation [ literal>> '[ drop @ ] ] }
+        { \ quotation [ literal>> dup remember-inlining '[ drop @ ] ] }
         { \ curry [
             slots>> third (value>quot)
             '[ [ obj>> ] [ quot>> @ ] bi ]
index c989aaf672eee27756450024190328100c672a24..e5595daeed97ef049bed37f24426a2272e15e4d7 100644 (file)
@@ -5,7 +5,8 @@ combinators sets locals columns grouping
 stack-checker.branches
 compiler.tree
 compiler.tree.def-use
-compiler.tree.combinators ;
+compiler.tree.combinators
+compiler.utilities ;
 IN: compiler.tree.propagation.copy
 
 ! Two values are copy-equivalent if they are always identical
@@ -15,18 +16,6 @@ IN: compiler.tree.propagation.copy
 ! Mapping from values to their canonical leader
 SYMBOL: copies
 
-:: compress-path ( source assoc -- destination )
-    [let | destination [ source assoc at ] |
-        source destination = [ source ] [
-            [let | destination' [ destination assoc compress-path ] |
-                destination' destination = [
-                    destination' source assoc set-at
-                ] unless
-                destination'
-            ]
-        ] if
-    ] ;
-
 : resolve-copy ( copy -- val ) copies get compress-path ;
 
 : is-copy-of ( val copy -- ) copies get set-at ;
index 6be3bed8d3adfa451c12f3a93a9e0f77b4a8c8e9..4d54dc5e397d777a4439245a4ace2ca938bf312a 100755 (executable)
@@ -163,13 +163,17 @@ DEFER: (flat-length)
 
 SYMBOL: history
 
+: already-inlined? ( obj -- ? ) history get memq? ;
+
+: add-to-history ( obj -- ) history [ swap suffix ] change ;
+
 : remember-inlining ( word -- )
     [ inlining-count get inc-at ]
-    [ history [ swap suffix ] change ]
+    [ add-to-history ]
     bi ;
 
 :: inline-word ( #call word -- ? )
-    word history get memq? [ f ] [
+    word already-inlined? [ f ] [
         #call word splicing-body [
             [
                 word remember-inlining
index c21be39adbc346b0d7cfa228b38a5d7c54cb6f8f..c6b7b2adc5286876fd4180aaee7971ad4c9f8df8 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel sequences sequences.private arrays vectors fry
-math math.order namespaces assocs ;
+math math.order namespaces assocs locals ;
 IN: compiler.utilities
 
 : flattener ( seq quot -- seq vector quot' )
@@ -30,3 +30,15 @@ yield-hook [ [ ] ] initialize
     [ ] [ [ [ second ] bi@ > ] most ] map-reduce ;
 
 : penultimate ( seq -- elt ) [ length 2 - ] keep nth ;
+
+:: compress-path ( source assoc -- destination )
+    [let | destination [ source assoc at ] |
+        source destination = [ source ] [
+            [let | destination' [ destination assoc compress-path ] |
+                destination' destination = [
+                    destination' source assoc set-at
+                ] unless
+                destination'
+            ]
+        ] if
+    ] ;
index deb44db41abad25fe8cb2c17e9ee51889dd2f2ba..e4c8f3246da7479311fe4873acafa475a078bbe6 100644 (file)
@@ -128,7 +128,12 @@ HOOK: %alien-global cpu ( dst symbol library -- )
 
 HOOK: %allot cpu ( dst size class temp -- )
 HOOK: %write-barrier cpu ( src card# table -- )
-HOOK: %gc cpu ( temp1 temp2 live-registers live-spill-slots -- )
+
+! GC checks
+HOOK: %check-nursery cpu ( label temp1 temp2 -- )
+HOOK: %save-gc-root cpu ( gc-root register -- )
+HOOK: %load-gc-root cpu ( gc-root register -- )
+HOOK: %call-gc cpu ( gc-root-count -- )
 
 HOOK: %prologue cpu ( n -- )
 HOOK: %epilogue cpu ( n -- )
index 003eccfa18a23cdb36cb5c921f12af65c0ae0a7f..14d271c31c99b6f78d3ff81ec3b6c9d4ea437e20 100644 (file)
@@ -4,10 +4,10 @@ USING: accessors assocs sequences kernel combinators make math
 math.order math.ranges system namespaces locals layouts words
 alien alien.accessors alien.c-types literals cpu.architecture
 cpu.ppc.assembler cpu.ppc.assembler.backend compiler.cfg.registers
-compiler.cfg.instructions compiler.constants compiler.codegen
+compiler.cfg.instructions compiler.cfg.comparisons
 compiler.codegen.fixup compiler.cfg.intrinsics
 compiler.cfg.stack-frame compiler.cfg.build-stack-frame
-compiler.units ;
+compiler.units compiler.constants compiler.codegen ;
 FROM: cpu.ppc.assembler => B ;
 IN: cpu.ppc
 
@@ -76,8 +76,12 @@ HOOK: reserved-area-size os ( -- n )
 : xt-save ( n -- i ) 2 cells - ;
 
 ! Next, we have the spill area as well as the FFI parameter area.
-! They overlap, since basic blocks with FFI calls will never
-! spill.
+! It is safe for them to overlap, since basic blocks with FFI calls
+! will never spill -- indeed, basic blocks with FFI calls do not
+! use vregs at all, and the FFI call is a stack analysis sync point.
+! In the future this will change and the stack frame logic will
+! need to be untangled somewhat.
+
 : param@ ( n -- x ) reserved-area-size + ; inline
 
 : param-save-size ( -- n ) 8 cells ; foldable
@@ -85,32 +89,30 @@ HOOK: reserved-area-size os ( -- n )
 : local@ ( n -- x )
     reserved-area-size param-save-size + + ; inline
 
-: spill-integer-base ( -- n )
-    stack-frame get spill-counts>> double-float-regs swap at
-    double-float-regs reg-size * ;
-
 : spill-integer@ ( n -- offset )
-    cells spill-integer-base + param@ ;
+    spill-integer-offset local@ ;
 
 : spill-float@ ( n -- offset )
-    double-float-regs reg-size * param@ ;
+    spill-float-offset local@ ;
 
 ! Some FP intrinsics need a temporary scratch area in the stack
-! frame, 8 bytes in size
+! frame, 8 bytes in size. This is in the param-save area so it
+! does not overlap with spill slots.
 : scratch@ ( n -- offset )
     stack-frame get total-size>>
     factor-area-size -
     param-save-size -
     + ;
 
+! GC root area
+: gc-root@ ( n -- offset )
+    gc-root-offset local@ ;
+
 ! Finally we have the linkage area
 HOOK: lr-save os ( -- n )
 
 M: ppc stack-frame-size ( stack-frame -- i )
-    [ spill-counts>> [ swap reg-size * ] { } assoc>map sum ]
-    [ params>> ]
-    [ return>> ]
-    tri + +
+    (stack-frame-size)
     param-save-size +
     reserved-area-size +
     factor-area-size +
@@ -176,95 +178,28 @@ M: ppc %or      OR ;
 M: ppc %or-imm  ORI ;
 M: ppc %xor     XOR ;
 M: ppc %xor-imm XORI ;
+M: ppc %shl     SLW ;
 M: ppc %shl-imm swapd SLWI ;
+M: ppc %shr     SRW ;
 M: ppc %shr-imm swapd SRWI ;
+M: ppc %sar     SRAW ;
 M: ppc %sar-imm SRAWI ;
 M: ppc %not     NOT ;
 
-: %alien-invoke-tail ( func dll -- )
-    [ scratch-reg ] 2dip %alien-global scratch-reg MTCTR BCTR ;
-
-:: exchange-regs ( r1 r2 -- )
-    scratch-reg r1 MR
-    r1 r2 MR
-    r2 scratch-reg MR ;
-
-: ?MR ( r1 r2 -- ) 2dup = [ 2drop ] [ MR ] if ;
-
-:: move>args ( src1 src2 -- )
-    {
-        { [ src1 4 = ] [ 3 src2 ?MR 3 4 exchange-regs ] }
-        { [ src1 3 = ] [ 4 src2 ?MR ] }
-        { [ src2 3 = ] [ 4 src1 ?MR 3 4 exchange-regs ] }
-        { [ src2 4 = ] [ 3 src1 ?MR ] }
-        [ 3 src1 MR 4 src2 MR ]
-    } cond ;
-
-: clear-xer ( -- )
+:: overflow-template ( label dst src1 src2 insn -- )
     0 0 LI
-    0 MTXER ; inline
-
-:: overflow-template ( src1 src2 insn func -- )
-    "no-overflow" define-label
-    clear-xer
-    scratch-reg src2 src1 insn call
-    scratch-reg ds-reg 0 STW
-    "no-overflow" get BNO
-    src1 src2 move>args
-    %prepare-alien-invoke
-    func f %alien-invoke
-    "no-overflow" resolve-label ; inline
-
-:: overflow-template-tail ( src1 src2 insn func -- )
-    "overflow" define-label
-    clear-xer
-    scratch-reg src2 src1 insn call
-    "overflow" get BO
-    scratch-reg ds-reg 0 STW
-    BLR
-    "overflow" resolve-label
-    src1 src2 move>args
-    %prepare-alien-invoke
-    func f %alien-invoke-tail ; inline
+    0 MTXER
+    dst src2 src1 insn call
+    label BO ; inline
 
-M: ppc %fixnum-add ( src1 src2 -- )
-    [ ADDO. ] "overflow_fixnum_add" overflow-template ;
+M: ppc %fixnum-add ( label dst src1 src2 -- )
+    [ ADDO. ] overflow-template ;
 
-M: ppc %fixnum-add-tail ( src1 src2 -- )
-    [ ADDO. ] "overflow_fixnum_add" overflow-template-tail ;
+M: ppc %fixnum-sub ( label dst src1 src2 -- )
+    [ SUBFO. ] overflow-template ;
 
-M: ppc %fixnum-sub ( src1 src2 -- )
-    [ SUBFO. ] "overflow_fixnum_subtract" overflow-template ;
-
-M: ppc %fixnum-sub-tail ( src1 src2 -- )
-    [ SUBFO. ] "overflow_fixnum_subtract" overflow-template-tail ;
-
-M:: ppc %fixnum-mul ( src1 src2 temp1 temp2 -- )
-    "no-overflow" define-label
-    clear-xer
-    temp1 src1 tag-bits get SRAWI
-    temp2 temp1 src2 MULLWO.
-    temp2 ds-reg 0 STW
-    "no-overflow" get BNO
-    src2 src2 tag-bits get SRAWI
-    temp1 src2 move>args
-    %prepare-alien-invoke
-    "overflow_fixnum_multiply" f %alien-invoke
-    "no-overflow" resolve-label ;
-
-M:: ppc %fixnum-mul-tail ( src1 src2 temp1 temp2 -- )
-    "overflow" define-label
-    clear-xer
-    temp1 src1 tag-bits get SRAWI
-    temp2 temp1 src2 MULLWO.
-    "overflow" get BO
-    temp2 ds-reg 0 STW
-    BLR
-    "overflow" resolve-label
-    src2 src2 tag-bits get SRAWI
-    temp1 src2 move>args
-    %prepare-alien-invoke
-    "overflow_fixnum_multiply" f %alien-invoke-tail ;
+M: ppc %fixnum-mul ( label dst src1 src2 -- )
+    [ MULLWO. ] overflow-template ;
 
 : bignum@ ( n -- offset ) cells bignum tag-number - ; inline
 
@@ -462,19 +397,27 @@ M:: ppc %write-barrier ( src card# table -- )
     src card# deck-bits SRWI
     table scratch-reg card# STBX ;
 
-M:: ppc %gc ( temp1 temp2 gc-roots gc-root-count -- )
-    "end" define-label
+M:: ppc %check-nursery ( label temp1 temp2 -- )
     temp2 load-zone-ptr
     temp1 temp2 cell LWZ
     temp2 temp2 3 cells LWZ
-    temp1 temp1 1024 ADDI ! add ALLOT_BUFFER_ZONE to here
-    temp1 0 temp2 CMP ! is here >= end?
-    "end" get BLE
+    ! add ALLOT_BUFFER_ZONE to here
+    temp1 temp1 1024 ADDI
+    ! is here >= end?
+    temp1 0 temp2 CMP
+    label BLE ;
+
+M:: ppc %save-gc-root ( gc-root register -- )
+    register 1 gc-root gc-root@ STW ;
+
+M:: ppc %load-gc-root ( gc-root register -- )
+    register 1 gc-root gc-root@ LWZ ;
+
+M:: ppc %call-gc ( gc-root-count -- )
     %prepare-alien-invoke
-    0 3 LI
-    0 4 LI
-    "inline_gc" f %alien-invoke
-    "end" resolve-label ;
+    3 1 gc-root-base local@ ADDI
+    gc-root-count 4 LI
+    "inline_gc" f %alien-invoke ;
 
 M: ppc %prologue ( n -- )
     0 11 LOAD32 rc-absolute-ppc-2/2 rel-this
index 727131aa25d26d984b7a9d2db94b5285bef67572..76699c1306c09b142622f0d18d96ffaaf60ccd80 100755 (executable)
@@ -1,13 +1,12 @@
 ! Copyright (C) 2005, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: locals alien.c-types alien.syntax arrays kernel fry
-math namespaces sequences system layouts io vocabs.loader
-accessors init combinators command-line cpu.x86.assembler
-cpu.x86 cpu.architecture make compiler compiler.units
+USING: locals alien.c-types alien.syntax arrays kernel fry math
+namespaces sequences system layouts io vocabs.loader accessors init
+combinators command-line make compiler compiler.units
 compiler.constants compiler.alien compiler.codegen
-compiler.codegen.fixup compiler.cfg.instructions
-compiler.cfg.builder compiler.cfg.intrinsics
-compiler.cfg.stack-frame ;
+compiler.codegen.fixup compiler.cfg.instructions compiler.cfg.builder
+compiler.cfg.intrinsics compiler.cfg.stack-frame cpu.x86.assembler
+cpu.x86.assembler.operands cpu.x86 cpu.architecture ;
 IN: cpu.x86.32
 
 ! We implement the FFI for Linux, OS X and Windows all at once.
index 490d37ccbc42ef8092f41c1f2e14a28a64230803..674cc817d7a6e83a03cbddc56ab0c89f6377acc0 100644 (file)
@@ -1,7 +1,8 @@
 ! Copyright (C) 2007, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: bootstrap.image.private kernel namespaces system
-cpu.x86.assembler layouts vocabs parser compiler.constants ;
+cpu.x86.assembler cpu.x86.assembler.operands layouts
+vocabs parser compiler.constants ;
 IN: bootstrap.x86
 
 4 \ cell set
index 8eb04eb2b5e5eec8f12d9b75cce9fe8d0decf91d..f837c7de7300cd3542fc7fde298653a4e1b4b359 100644 (file)
@@ -1,12 +1,11 @@
 ! Copyright (C) 2005, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors arrays kernel math namespaces make sequences
-system layouts alien alien.c-types alien.accessors alien.structs
-slots splitting assocs combinators locals cpu.x86.assembler
-cpu.x86 cpu.architecture compiler.constants
-compiler.codegen compiler.codegen.fixup
-compiler.cfg.instructions compiler.cfg.builder
-compiler.cfg.intrinsics compiler.cfg.stack-frame ;
+USING: accessors arrays kernel math namespaces make sequences system
+layouts alien alien.c-types alien.accessors alien.structs slots
+splitting assocs combinators locals compiler.constants
+compiler.codegen compiler.codegen.fixup compiler.cfg.instructions
+compiler.cfg.builder compiler.cfg.intrinsics compiler.cfg.stack-frame
+cpu.x86.assembler cpu.x86.assembler.operands cpu.x86 cpu.architecture ;
 IN: cpu.x86.64
 
 M: x86.64 machine-registers
index c5c7e63dbc7f4be149ed4e7c5c18977472eac70c..8b0d53cda56f52075097c96f21f70c3464efae21 100644 (file)
@@ -1,7 +1,8 @@
 ! Copyright (C) 2007, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: bootstrap.image.private kernel namespaces system
-cpu.x86.assembler layouts vocabs parser compiler.constants math ;
+layouts vocabs parser compiler.constants math
+cpu.x86.assembler cpu.x86.assembler.operands ;
 IN: bootstrap.x86
 
 8 \ cell set
index e48a20a9de9fc7a834381c439a19bd7abf0fbbda..b6d56840e26e85c2d194517f75c3b8825d087059 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: bootstrap.image.private kernel namespaces system
-cpu.x86.assembler layouts vocabs parser ;
+cpu.x86.assembler cpu.x86.assembler.operands layouts vocabs parser ;
 IN: bootstrap.x86
 
 : stack-frame-size ( -- n ) 4 bootstrap-cells ;
index eea960d03dba6fe2e851acfe8fb123c7af286234..7ab25b6d3f2f04ed944178e4f807a39fd7872461 100644 (file)
@@ -1,9 +1,9 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors arrays sequences math splitting make assocs
-kernel layouts system alien.c-types alien.structs
-cpu.architecture cpu.x86.assembler cpu.x86
-compiler.codegen compiler.cfg.registers ;
+USING: accessors arrays sequences math splitting make assocs kernel
+layouts system alien.c-types alien.structs cpu.architecture
+cpu.x86.assembler cpu.x86.assembler.operands cpu.x86 compiler.codegen
+compiler.cfg.registers ;
 IN: cpu.x86.64.unix
 
 M: int-regs param-regs drop { RDI RSI RDX RCX R8 R9 } ;
index ff15ef27afc48bb096334f31c915af4bf3f040d5..0228082956a557288b6a8b63471051ac6fc70f78 100644 (file)
@@ -1,7 +1,8 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: bootstrap.image.private kernel namespaces system
-cpu.x86.assembler layouts vocabs parser ;
+layouts vocabs parser cpu.x86.assembler
+cpu.x86.assembler.operands ;
 IN: bootstrap.x86
 
 : stack-frame-size ( -- n ) 8 bootstrap-cells ;
index 8091be65ae49c31cef64b2cf2d098a56b3e99609..44e85686589990b76c04aa6b08d4efb3648ed4a0 100644 (file)
@@ -1,7 +1,8 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel layouts system math alien.c-types sequences
-compiler.cfg.registers cpu.architecture cpu.x86.assembler cpu.x86 ;
+compiler.cfg.registers cpu.architecture cpu.x86.assembler cpu.x86
+cpu.x86.assembler.operands ;
 IN: cpu.x86.64.winnt
 
 M: int-regs param-regs drop { RCX RDX R8 R9 } ;
index 66adee6bf6d59e524322813949fbac7f21d2377c..47d6434279325a6fcc8e06971ca7a039821fbeb8 100644 (file)
@@ -1,6 +1,9 @@
-USING: cpu.x86.assembler kernel tools.test namespaces make ;
+USING: cpu.x86.assembler cpu.x86.assembler.operands
+kernel tools.test namespaces make ;
 IN: cpu.x86.assembler.tests
 
+[ { HEX: 40 HEX: 8a HEX: 2a } ] [ [ BPL RDX [] MOV ] { } make ] unit-test
+
 [ { HEX: 49 HEX: 89 HEX: 04 HEX: 24 } ] [ [ R12 [] RAX MOV ] { } make ] unit-test
 [ { HEX: 49 HEX: 8b HEX: 06 } ] [ [ RAX R14 [] MOV ] { } make ] unit-test
 
@@ -68,6 +71,7 @@ IN: cpu.x86.assembler.tests
 
 ! sse shift instructions
 [ { HEX: 66 HEX: 0f HEX: 71 HEX: d0 HEX: 05 } ] [ [ XMM0 5 PSRLW ] { } make ] unit-test
+[ { HEX: 66 HEX: 0f HEX: d1 HEX: c1 } ] [ [ XMM0 XMM1 PSRLW ] { } make ] unit-test
 
 ! sse comparison instructions 
 [ { HEX: 66 HEX: 0f HEX: c2 HEX: c1 HEX: 02 } ] [ [ XMM0 XMM1 CMPLEPD ] { } make ] unit-test
index e91ebdcb1aae78e76bfc3c33ff639ff25aa40479..2b99513fc16f525d043c4e1168a24e414e1cd1c9 100644 (file)
@@ -1,90 +1,15 @@
-! Copyright (C) 2005, 2009 Slava Pestov.
+! Copyright (C) 2005, 2009 Slava Pestov, Joe Groff.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: arrays io.binary kernel combinators kernel.private math
+USING: arrays io.binary kernel combinators kernel.private math locals
 namespaces make sequences words system layouts math.order accessors
-cpu.x86.assembler.syntax ;
+cpu.x86.assembler.operands cpu.x86.assembler.operands.private ;
 QUALIFIED: sequences
 IN: cpu.x86.assembler
 
 ! A postfix assembler for x86-32 and x86-64.
 
-! In 32-bit mode, { 1234 } is absolute indirect addressing.
-! In 64-bit mode, { 1234 } is RIP-relative.
-! Beware!
-
-! Register operands -- eg, ECX
-REGISTERS: 8 AL CL DL BL SPL BPL SIL DIL R8B R9B R10B R11B R12B R13B R14B R15B ;
-
-ALIAS: AH SPL
-ALIAS: CH BPL
-ALIAS: DH SIL
-ALIAS: BH DIL
-
-REGISTERS: 16 AX CX DX BX SP BP SI DI R8W R9W R10W R11W R12W R13W R14W R15W ;
-
-REGISTERS: 32 EAX ECX EDX EBX ESP EBP ESI EDI R8D R9D R10D R11D R12D R13D R14D R15D ;
-
-REGISTERS: 64
-RAX RCX RDX RBX RSP RBP RSI RDI R8 R9 R10 R11 R12 R13 R14 R15 ;
-
-REGISTERS: 128
-XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7
-XMM8 XMM9 XMM10 XMM11 XMM12 XMM13 XMM14 XMM15 ;
-
-TUPLE: byte value ;
-
-C: <byte> byte
-
 <PRIVATE
 
-#! Extended AMD64 registers (R8-R15) return true.
-GENERIC: extended? ( op -- ? )
-
-M: object extended? drop f ;
-
-PREDICATE: register < word
-    "register" word-prop ;
-
-PREDICATE: register-8 < register
-    "register-size" word-prop 8 = ;
-
-PREDICATE: register-16 < register
-    "register-size" word-prop 16 = ;
-
-PREDICATE: register-32 < register
-    "register-size" word-prop 32 = ;
-
-PREDICATE: register-64 < register
-    "register-size" word-prop 64 = ;
-
-PREDICATE: register-128 < register
-    "register-size" word-prop 128 = ;
-
-M: register extended? "register" word-prop 7 > ;
-
-! Addressing modes
-TUPLE: indirect base index scale displacement ;
-
-M: indirect extended? base>> extended? ;
-
-: canonicalize-EBP ( indirect -- indirect )
-    #! { EBP } ==> { EBP 0 }
-    dup [ base>> { EBP RBP R13 } member? ] [ displacement>> not ] bi and
-    [ 0 >>displacement ] when ;
-
-ERROR: bad-index indirect ;
-
-: check-ESP ( indirect -- indirect )
-    dup index>> { ESP RSP } memq? [ bad-index ] when ;
-
-: canonicalize ( indirect -- indirect )
-    #! Modify the indirect to work around certain addressing mode
-    #! quirks.
-    canonicalize-EBP check-ESP ;
-
-: <indirect> ( base index scale displacement -- indirect )
-    indirect boa canonicalize ;
-
 : reg-code ( reg -- n ) "register" word-prop 7 bitand ;
 
 : indirect-base* ( op -- n ) base>> EBP or reg-code ;
@@ -159,27 +84,13 @@ M: indirect displacement,
     dup displacement>> dup [
         swap base>>
         [ dup fits-in-byte? [ , ] [ 4, ] if ] [ 4, ] if
-    ] [
-        2drop
-    ] if ;
+    ] [ 2drop ] if ;
 
 M: register displacement, drop ;
 
 : addressing ( reg# indirect -- )
     [ mod-r/m, ] [ sib, ] [ displacement, ] tri ;
 
-! Utilities
-UNION: operand register indirect ;
-
-GENERIC: operand-64? ( operand -- ? )
-
-M: indirect operand-64?
-    [ base>> ] [ index>> ] bi [ operand-64? ] either? ;
-
-M: register-64 operand-64? drop t ;
-
-M: object operand-64? drop f ;
-
 : rex.w? ( rex.w reg r/m -- ? )
     {
         { [ dup register-128? ] [ drop operand-64? ] }
@@ -192,22 +103,25 @@ M: object operand-64? drop f ;
 
 : rex.b ( m op -- n )
     [ extended? [ BIN: 00000001 bitor ] when ] keep
-    dup indirect? [
-        index>> extended? [ BIN: 00000010 bitor ] when
-    ] [
-        drop
-    ] if ;
+    dup indirect? [ index>> extended? [ BIN: 00000010 bitor ] when ] [ drop ] if ;
+
+: no-prefix? ( prefix reg r/m -- ? )
+    [ BIN: 01000000 = ]
+    [ extended-8-bit-register? not ]
+    [ extended-8-bit-register? not ] tri*
+    and and ;
 
-: rex-prefix ( reg r/m rex.w -- )
+:: rex-prefix ( reg r/m rex.w -- )
     #! Compile an AMD64 REX prefix.
-    2over rex.w? BIN: 01001000 BIN: 01000000 ?
-    swap rex.r swap rex.b
-    dup BIN: 01000000 = [ drop ] [ , ] if ;
+    rex.w reg r/m rex.w? BIN: 01001000 BIN: 01000000 ?
+    r/m rex.r
+    reg rex.b
+    dup reg r/m no-prefix? [ drop ] [ , ] if ;
 
 : 16-prefix ( reg r/m -- )
     [ register-16? ] either? [ HEX: 66 , ] when ;
 
-: prefix ( reg r/m rex.w -- ) 2over 16-prefix rex-prefix ;
+: prefix ( reg r/m rex.w -- ) [ drop 16-prefix ] [ rex-prefix ] 3bi ;
 
 : prefix-1 ( reg rex.w -- ) f swap prefix ;
 
@@ -269,22 +183,10 @@ M: object operand-64? drop f ;
 : 2-operand ( dst src op -- )
     #! Sets the opcode's direction bit. It is set if the
     #! destination is a direct register operand.
-    2over 16-prefix
-    direction-bit
-    operand-size-bit
-    (2-operand) ;
+    [ drop 16-prefix ] [ direction-bit operand-size-bit (2-operand) ] 3bi ;
 
 PRIVATE>
 
-: [] ( reg/displacement -- indirect )
-    dup integer? [ [ f f f ] dip ] [ f f f ] if <indirect> ;
-
-: [+] ( reg displacement -- indirect )
-    dup integer?
-    [ dup zero? [ drop f ] when [ f f ] dip ]
-    [ f f ] if
-    <indirect> ;
-
 ! Moving stuff
 GENERIC: PUSH ( op -- )
 M: register PUSH f HEX: 50 short-operand ;
@@ -681,24 +583,57 @@ ALIAS: PINSRQ PINSRD
 : MAXPD      ( dest src -- ) HEX: 5f HEX: 66 2-operand-rm-sse ;
 : MAXSD      ( dest src -- ) HEX: 5f HEX: f2 2-operand-rm-sse ;
 : MAXSS      ( dest src -- ) HEX: 5f HEX: f3 2-operand-rm-sse ;
+: PUNPCKLBW  ( dest src -- ) HEX: 60 HEX: 66 2-operand-rm-sse ;
+: PUNPCKLWD  ( dest src -- ) HEX: 61 HEX: 66 2-operand-rm-sse ;
+: PUNPCKLDQ  ( dest src -- ) HEX: 62 HEX: 66 2-operand-rm-sse ;
+: PACKSSWB   ( dest src -- ) HEX: 63 HEX: 66 2-operand-rm-sse ;
+: PCMPGTB    ( dest src -- ) HEX: 64 HEX: 66 2-operand-rm-sse ;
+: PCMPGTW    ( dest src -- ) HEX: 65 HEX: 66 2-operand-rm-sse ;
+: PCMPGTD    ( dest src -- ) HEX: 66 HEX: 66 2-operand-rm-sse ;
+: PACKUSWB   ( dest src -- ) HEX: 67 HEX: 66 2-operand-rm-sse ;
+: PUNPCKHBW  ( dest src -- ) HEX: 68 HEX: 66 2-operand-rm-sse ;
+: PUNPCKHWD  ( dest src -- ) HEX: 69 HEX: 66 2-operand-rm-sse ;
+: PUNPCKHDQ  ( dest src -- ) HEX: 6a HEX: 66 2-operand-rm-sse ;
+: PACKSSDW   ( dest src -- ) HEX: 6b HEX: 66 2-operand-rm-sse ;
 : PUNPCKLQDQ ( dest src -- ) HEX: 6c HEX: 66 2-operand-rm-sse ;
 : PUNPCKHQDQ ( dest src -- ) HEX: 6d HEX: 66 2-operand-rm-sse ;
 
+: MOVD       ( dest src -- ) { HEX: 6e HEX: 7e } HEX: 66 2-operand-rm-mr-sse ;
 : MOVDQA     ( dest src -- ) { HEX: 6f HEX: 7f } HEX: 66 2-operand-rm-mr-sse ;
 : MOVDQU     ( dest src -- ) { HEX: 6f HEX: 7f } HEX: f3 2-operand-rm-mr-sse ;
 
 : PSHUFD     ( dest src imm -- ) HEX: 70 HEX: 66 3-operand-rm-sse ;
 : PSHUFLW    ( dest src imm -- ) HEX: 70 HEX: f2 3-operand-rm-sse ;
 : PSHUFHW    ( dest src imm -- ) HEX: 70 HEX: f3 3-operand-rm-sse ;
-: PSRLW      ( dest imm -- ) BIN: 010 HEX: 71 HEX: 66 2-operand-sse-shift ;
-: PSRAW      ( dest imm -- ) BIN: 100 HEX: 71 HEX: 66 2-operand-sse-shift ;
-: PSLLW      ( dest imm -- ) BIN: 110 HEX: 71 HEX: 66 2-operand-sse-shift ;
-: PSRLD      ( dest imm -- ) BIN: 010 HEX: 72 HEX: 66 2-operand-sse-shift ;
-: PSRAD      ( dest imm -- ) BIN: 100 HEX: 72 HEX: 66 2-operand-sse-shift ;
-: PSLLD      ( dest imm -- ) BIN: 110 HEX: 72 HEX: 66 2-operand-sse-shift ;
-: PSRLQ      ( dest imm -- ) BIN: 010 HEX: 73 HEX: 66 2-operand-sse-shift ;
+
+: (PSRLW-imm) ( dest imm -- ) BIN: 010 HEX: 71 HEX: 66 2-operand-sse-shift ;
+: (PSRAW-imm) ( dest imm -- ) BIN: 100 HEX: 71 HEX: 66 2-operand-sse-shift ;
+: (PSLLW-imm) ( dest imm -- ) BIN: 110 HEX: 71 HEX: 66 2-operand-sse-shift ;
+: (PSRLD-imm) ( dest imm -- ) BIN: 010 HEX: 72 HEX: 66 2-operand-sse-shift ;
+: (PSRAD-imm) ( dest imm -- ) BIN: 100 HEX: 72 HEX: 66 2-operand-sse-shift ;
+: (PSLLD-imm) ( dest imm -- ) BIN: 110 HEX: 72 HEX: 66 2-operand-sse-shift ;
+: (PSRLQ-imm) ( dest imm -- ) BIN: 010 HEX: 73 HEX: 66 2-operand-sse-shift ;
+: (PSLLQ-imm) ( dest imm -- ) BIN: 110 HEX: 73 HEX: 66 2-operand-sse-shift ;
+
+: (PSRLW-reg) ( dest src -- ) HEX: d1 HEX: 66 2-operand-rm-sse ;
+: (PSRLD-reg) ( dest src -- ) HEX: d2 HEX: 66 2-operand-rm-sse ;
+: (PSRLQ-reg) ( dest src -- ) HEX: d3 HEX: 66 2-operand-rm-sse ;
+: (PSRAW-reg) ( dest src -- ) HEX: e1 HEX: 66 2-operand-rm-sse ;
+: (PSRAD-reg) ( dest src -- ) HEX: e2 HEX: 66 2-operand-rm-sse ;
+: (PSLLW-reg) ( dest src -- ) HEX: f1 HEX: 66 2-operand-rm-sse ;
+: (PSLLD-reg) ( dest src -- ) HEX: f2 HEX: 66 2-operand-rm-sse ;
+: (PSLLQ-reg) ( dest src -- ) HEX: f3 HEX: 66 2-operand-rm-sse ;
+
+: PSRLW ( dest src -- ) dup integer? [ (PSRLW-imm) ] [ (PSRLW-reg) ] if ;
+: PSRAW ( dest src -- ) dup integer? [ (PSRAW-imm) ] [ (PSRAW-reg) ] if ;
+: PSLLW ( dest src -- ) dup integer? [ (PSLLW-imm) ] [ (PSLLW-reg) ] if ;
+: PSRLD ( dest src -- ) dup integer? [ (PSRLD-imm) ] [ (PSRLD-reg) ] if ;
+: PSRAD ( dest src -- ) dup integer? [ (PSRAD-imm) ] [ (PSRAD-reg) ] if ;
+: PSLLD ( dest src -- ) dup integer? [ (PSLLD-imm) ] [ (PSLLD-reg) ] if ;
+: PSRLQ ( dest src -- ) dup integer? [ (PSRLQ-imm) ] [ (PSRLQ-reg) ] if ;
+: PSLLQ ( dest src -- ) dup integer? [ (PSLLQ-imm) ] [ (PSLLQ-reg) ] if ;
+
 : PSRLDQ     ( dest imm -- ) BIN: 011 HEX: 73 HEX: 66 2-operand-sse-shift ;
-: PSLLQ      ( dest imm -- ) BIN: 110 HEX: 73 HEX: 66 2-operand-sse-shift ;
 : PSLLDQ     ( dest imm -- ) BIN: 111 HEX: 73 HEX: 66 2-operand-sse-shift ;
 
 : PCMPEQB    ( dest src -- ) HEX: 74 HEX: 66 2-operand-rm-sse ;
@@ -709,11 +644,14 @@ ALIAS: PINSRQ PINSRD
 : HSUBPD     ( dest src -- ) HEX: 7d HEX: 66 2-operand-rm-sse ;
 : HSUBPS     ( dest src -- ) HEX: 7d HEX: f2 2-operand-rm-sse ;
 
+: FXSAVE     ( dest -- ) { BIN: 000 f { HEX: 0f HEX: ae } } 1-operand ;
+: FXRSTOR    ( src -- )  { BIN: 001 f { HEX: 0f HEX: ae } } 1-operand ;
 : LDMXCSR    ( src -- )  { BIN: 010 f { HEX: 0f HEX: ae } } 1-operand ;
 : STMXCSR    ( dest -- ) { BIN: 011 f { HEX: 0f HEX: ae } } 1-operand ;
 : LFENCE     ( -- ) HEX: 0f , HEX: ae , OCT: 350 , ;
 : MFENCE     ( -- ) HEX: 0f , HEX: ae , OCT: 360 , ;
 : SFENCE     ( -- ) HEX: 0f , HEX: ae , OCT: 370 , ;
+: CLFLUSH    ( dest -- ) { BIN: 111 f { HEX: 0f HEX: ae } } 1-operand ;
 
 : POPCNT     ( dest src -- ) HEX: b8 HEX: f3 2-operand-rm-sse ;
 
@@ -762,26 +700,46 @@ ALIAS: PINSRQ PINSRD
 : ADDSUBPD   ( dest src -- ) HEX: d0 HEX: 66 2-operand-rm-sse ;
 : ADDSUBPS   ( dest src -- ) HEX: d0 HEX: f2 2-operand-rm-sse ;
 : PADDQ      ( dest src -- ) HEX: d4 HEX: 66 2-operand-rm-sse ;
+: PMULLW     ( dest src -- ) HEX: d5 HEX: 66 2-operand-rm-sse ;
+: PMOVMSKB   ( dest src -- ) HEX: d7 HEX: 66 2-operand-rm-sse ;
+: PSUBUSB    ( dest src -- ) HEX: d8 HEX: 66 2-operand-rm-sse ;
+: PSUBUSW    ( dest src -- ) HEX: d9 HEX: 66 2-operand-rm-sse ;
 : PMINUB     ( dest src -- ) HEX: da HEX: 66 2-operand-rm-sse ;
+: PAND       ( dest src -- ) HEX: db HEX: 66 2-operand-rm-sse ;
+: PADDUSB    ( dest src -- ) HEX: dc HEX: 66 2-operand-rm-sse ;
+: PADDUSW    ( dest src -- ) HEX: dd HEX: 66 2-operand-rm-sse ;
 : PMAXUB     ( dest src -- ) HEX: de HEX: 66 2-operand-rm-sse ;
+: PANDN      ( dest src -- ) HEX: df HEX: 66 2-operand-rm-sse ;
 : PAVGB      ( dest src -- ) HEX: e0 HEX: 66 2-operand-rm-sse ;
 : PAVGW      ( dest src -- ) HEX: e3 HEX: 66 2-operand-rm-sse ;
 : PMULHUW    ( dest src -- ) HEX: e4 HEX: 66 2-operand-rm-sse ;
+: PMULHW     ( dest src -- ) HEX: e5 HEX: 66 2-operand-rm-sse ;
 : CVTTPD2DQ  ( dest src -- ) HEX: e6 HEX: 66 2-operand-rm-sse ;
 : CVTPD2DQ   ( dest src -- ) HEX: e6 HEX: f2 2-operand-rm-sse ;
 : CVTDQ2PD   ( dest src -- ) HEX: e6 HEX: f3 2-operand-rm-sse ;
 
 : MOVNTDQ    ( dest src -- ) HEX: e7 HEX: 66 2-operand-mr-sse ;
 
+: PSUBSB     ( dest src -- ) HEX: e8 HEX: 66 2-operand-rm-sse ;
+: PSUBSW     ( dest src -- ) HEX: e9 HEX: 66 2-operand-rm-sse ;
 : PMINSW     ( dest src -- ) HEX: ea HEX: 66 2-operand-rm-sse ;
+: POR        ( dest src -- ) HEX: eb HEX: 66 2-operand-rm-sse ;
+: PADDSB     ( dest src -- ) HEX: ec HEX: 66 2-operand-rm-sse ;
+: PADDSW     ( dest src -- ) HEX: ed HEX: 66 2-operand-rm-sse ;
 : PMAXSW     ( dest src -- ) HEX: ee HEX: 66 2-operand-rm-sse ;
+: PXOR       ( dest src -- ) HEX: ef HEX: 66 2-operand-rm-sse ;
 : LDDQU      ( dest src -- ) HEX: f0 HEX: f2 2-operand-rm-sse ;
 : PMULUDQ    ( dest src -- ) HEX: f4 HEX: 66 2-operand-rm-sse ;
+: PMADDWD    ( dest src -- ) HEX: f5 HEX: 66 2-operand-rm-sse ;
 : PSADBW     ( dest src -- ) HEX: f6 HEX: 66 2-operand-rm-sse ;
-
 : MASKMOVDQU ( dest src -- ) HEX: f7 HEX: 66 2-operand-rm-sse ;
-
+: PSUBB      ( dest src -- ) HEX: f8 HEX: 66 2-operand-rm-sse ;
+: PSUBW      ( dest src -- ) HEX: f9 HEX: 66 2-operand-rm-sse ;
+: PSUBD      ( dest src -- ) HEX: fa HEX: 66 2-operand-rm-sse ;
 : PSUBQ      ( dest src -- ) HEX: fb HEX: 66 2-operand-rm-sse ;
+: PADDB      ( dest src -- ) HEX: fc HEX: 66 2-operand-rm-sse ;
+: PADDW      ( dest src -- ) HEX: fd HEX: 66 2-operand-rm-sse ;
+: PADDD      ( dest src -- ) HEX: fe HEX: 66 2-operand-rm-sse ;
 
 ! x86-64 branch prediction hints
 
index 1901f27a24507e2512d93a1f956aaaa0d2f05714..580f882c8d78327fd1fc737a4da0624407fe0e7a 100755 (executable)
@@ -1 +1,2 @@
 Slava Pestov
+Joe Groff
diff --git a/basis/cpu/x86/assembler/operands/operands.factor b/basis/cpu/x86/assembler/operands/operands.factor
new file mode 100644 (file)
index 0000000..d3cb66f
--- /dev/null
@@ -0,0 +1,118 @@
+! Copyright (C) 2008, 2009 Slava Pestov, Joe Groff.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel words math accessors sequences namespaces
+assocs layouts cpu.x86.assembler.syntax ;
+IN: cpu.x86.assembler.operands
+
+! In 32-bit mode, { 1234 } is absolute indirect addressing.
+! In 64-bit mode, { 1234 } is RIP-relative.
+! Beware!
+
+REGISTERS: 8 AL CL DL BL SPL BPL SIL DIL R8B R9B R10B R11B R12B R13B R14B R15B ;
+
+ALIAS: AH SPL
+ALIAS: CH BPL
+ALIAS: DH SIL
+ALIAS: BH DIL
+
+REGISTERS: 16 AX CX DX BX SP BP SI DI R8W R9W R10W R11W R12W R13W R14W R15W ;
+
+REGISTERS: 32 EAX ECX EDX EBX ESP EBP ESI EDI R8D R9D R10D R11D R12D R13D R14D R15D ;
+
+REGISTERS: 64
+RAX RCX RDX RBX RSP RBP RSI RDI R8 R9 R10 R11 R12 R13 R14 R15 ;
+
+REGISTERS: 128
+XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7
+XMM8 XMM9 XMM10 XMM11 XMM12 XMM13 XMM14 XMM15 ;
+
+<PRIVATE
+
+GENERIC: extended? ( op -- ? )
+
+M: object extended? drop f ;
+
+PREDICATE: register < word
+    "register" word-prop ;
+
+PREDICATE: register-8 < register
+    "register-size" word-prop 8 = ;
+
+PREDICATE: register-16 < register
+    "register-size" word-prop 16 = ;
+
+PREDICATE: register-32 < register
+    "register-size" word-prop 32 = ;
+
+PREDICATE: register-64 < register
+    "register-size" word-prop 64 = ;
+
+PREDICATE: register-128 < register
+    "register-size" word-prop 128 = ;
+
+M: register extended? "register" word-prop 7 > ;
+
+! Addressing modes
+TUPLE: indirect base index scale displacement ;
+
+M: indirect extended? base>> extended? ;
+
+: canonicalize-EBP ( indirect -- indirect )
+    #! { EBP } ==> { EBP 0 }
+    dup [ base>> { EBP RBP R13 } member? ] [ displacement>> not ] bi and
+    [ 0 >>displacement ] when ;
+
+ERROR: bad-index indirect ;
+
+: check-ESP ( indirect -- indirect )
+    dup index>> { ESP RSP } memq? [ bad-index ] when ;
+
+: canonicalize ( indirect -- indirect )
+    #! Modify the indirect to work around certain addressing mode
+    #! quirks.
+    canonicalize-EBP check-ESP ;
+
+: <indirect> ( base index scale displacement -- indirect )
+    indirect boa canonicalize ;
+
+! Utilities
+UNION: operand register indirect ;
+
+GENERIC: operand-64? ( operand -- ? )
+
+M: indirect operand-64?
+    [ base>> ] [ index>> ] bi [ operand-64? ] either? ;
+
+M: register-64 operand-64? drop t ;
+
+M: object operand-64? drop f ;
+
+PRIVATE>
+
+: [] ( reg/displacement -- indirect )
+    dup integer? [ [ f f f ] dip ] [ f f f ] if <indirect> ;
+
+: [+] ( reg displacement -- indirect )
+    dup integer?
+    [ dup zero? [ drop f ] when [ f f ] dip ]
+    [ f f ] if
+    <indirect> ;
+
+TUPLE: byte value ;
+
+C: <byte> byte
+
+: extended-8-bit-register? ( register -- ? )
+    { SPL BPL SIL DIL } memq? ;
+
+: n-bit-version-of ( register n -- register' )
+    ! Certain 8-bit registers don't exist in 32-bit mode...
+    [ "register" word-prop ] dip registers get at nth
+    dup extended-8-bit-register? cell 4 = and
+    [ drop f ] when ;
+
+: 8-bit-version-of ( register -- register' ) 8 n-bit-version-of ;
+: 16-bit-version-of ( register -- register' ) 16 n-bit-version-of ;
+: 32-bit-version-of ( register -- register' ) 32 n-bit-version-of ;
+: 64-bit-version-of ( register -- register' ) 64 n-bit-version-of ;
+: native-version-of ( register -- register' ) cell-bits n-bit-version-of ;
\ No newline at end of file
index 631dcaa8f7d3536fae6f9d169f407a523a3c20bb..5b65c19155055aa3b9b9db9a0113fef44f168a18 100644 (file)
@@ -1,14 +1,23 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel words words.symbol sequences lexer parser fry ;
+USING: kernel words words.symbol sequences lexer parser fry
+namespaces combinators assocs ;
 IN: cpu.x86.assembler.syntax
 
-: define-register ( name num size -- )
-    [ "cpu.x86.assembler" create dup define-symbol ] 2dip
-    [ dupd "register" set-word-prop ] dip
-    "register-size" set-word-prop ;
+SYMBOL: registers
 
-: define-registers ( names size -- )
-    '[ _ define-register ] each-index ;
+registers [ H{ } clone ] initialize
 
-SYNTAX: REGISTERS: scan-word ";" parse-tokens swap define-registers ;
+: define-register ( name num size -- word )
+    [ "cpu.x86.assembler.operands" create ] 2dip {
+        [ 2drop ]
+        [ 2drop define-symbol ]
+        [ drop "register" set-word-prop ]
+        [ nip "register-size" set-word-prop ]
+    } 3cleave ;
+
+: define-registers ( size names -- )
+    [ swap '[ _ define-register ] map-index ] [ drop ] 2bi
+    registers get set-at ;
+
+SYNTAX: REGISTERS: scan-word ";" parse-tokens define-registers ;
index 474ce2ea468fc2f4e56b355c90461750f68cb7a2..6363f17e48053eebdd0973b00735a9eb0f8cacc7 100644 (file)
@@ -1,9 +1,9 @@
 ! Copyright (C) 2007, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: bootstrap.image.private kernel kernel.private namespaces
-system cpu.x86.assembler layouts compiler.units math
-math.private compiler.constants vocabs slots.private words
-locals.backend make sequences combinators arrays ;
+USING: bootstrap.image.private kernel kernel.private namespaces system
+layouts compiler.units math math.private compiler.constants vocabs
+slots.private words locals.backend make sequences combinators arrays
+ cpu.x86.assembler cpu.x86.assembler.operands ;
 IN: bootstrap.x86
 
 big-endian off
index 258f84259877d7579f5a4a20aee2dd147067528b..34b1b63581e2f5a979244010d0ec279178c71245 100644 (file)
@@ -1,9 +1,9 @@
 ! Copyright (C) 2005, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors assocs alien alien.c-types arrays strings
-cpu.x86.assembler cpu.x86.assembler.private cpu.architecture
-kernel kernel.private math memory namespaces make sequences
-words system layouts combinators math.order fry locals
+cpu.x86.assembler cpu.x86.assembler.private cpu.x86.assembler.operands
+cpu.architecture kernel kernel.private math memory namespaces make
+sequences words system layouts combinators math.order fry locals
 compiler.constants
 compiler.cfg.registers
 compiler.cfg.instructions
@@ -264,124 +264,54 @@ M:: x86 %box-alien ( dst src temp -- )
         "end" resolve-label
     ] with-scope ;
 
-: small-reg-8 ( reg -- reg' )
-    H{
-        { EAX RAX }
-        { ECX RCX }
-        { EDX RDX }
-        { EBX RBX }
-        { ESP RSP }
-        { EBP RBP }
-        { ESI RSP }
-        { EDI RDI }
-
-        { RAX RAX }
-        { RCX RCX }
-        { RDX RDX }
-        { RBX RBX }
-        { RSP RSP }
-        { RBP RBP }
-        { RSI RSP }
-        { RDI RDI }
-    } at ; inline
-
-: small-reg-4 ( reg -- reg' )
-    small-reg-8 H{
-        { RAX EAX }
-        { RCX ECX }
-        { RDX EDX }
-        { RBX EBX }
-        { RSP ESP }
-        { RBP EBP }
-        { RSI ESP }
-        { RDI EDI }
-    } at ; inline
-
-: small-reg-2 ( reg -- reg' )
-    small-reg-4 H{
-        { EAX AX }
-        { ECX CX }
-        { EDX DX }
-        { EBX BX }
-        { ESP SP }
-        { EBP BP }
-        { ESI SI }
-        { EDI DI }
-    } at ; inline
-
-: small-reg-1 ( reg -- reg' )
-    small-reg-4 {
-        { EAX AL }
-        { ECX CL }
-        { EDX DL }
-        { EBX BL }
-    } at ; inline
-
-: small-reg ( reg size -- reg' )
-    {
-        { 1 [ small-reg-1 ] }
-        { 2 [ small-reg-2 ] }
-        { 4 [ small-reg-4 ] }
-        { 8 [ small-reg-8 ] }
-    } case ;
+! The 'small-reg' mess is pretty crappy, but its only used on x86-32.
+! On x86-64, all registers have 8-bit versions. However, a similar
+! problem arises for shifts, where the shift count must be in CL, and
+! so one day I will fix this properly by adding precoloring to the
+! register allocator.
 
-HOOK: small-regs cpu ( -- regs )
+HOOK: has-small-reg? cpu ( reg size -- ? )
 
-M: x86.32 small-regs { EAX ECX EDX EBX } ;
-M: x86.64 small-regs { RAX RCX RDX RBX } ;
+CONSTANT: have-byte-regs { EAX ECX EDX EBX }
 
-HOOK: small-reg-native cpu ( reg -- reg' )
+M: x86.32 has-small-reg?
+    {
+        { 8 [ have-byte-regs memq? ] }
+        { 16 [ drop t ] }
+        { 32 [ drop t ] }
+    } case ;
 
-M: x86.32 small-reg-native small-reg-4 ;
-M: x86.64 small-reg-native small-reg-8 ;
+M: x86.64 has-small-reg? 2drop t ;
 
 : small-reg-that-isn't ( exclude -- reg' )
-    small-regs swap [ small-reg-native ] map '[ _ memq? not ] find nip ;
+    [ have-byte-regs ] dip
+    [ native-version-of ] map
+    '[ _ memq? not ] find nip ;
 
 : with-save/restore ( reg quot -- )
     [ drop PUSH ] [ call ] [ drop POP ] 2tri ; inline
 
-:: with-small-register ( dst exclude quot: ( new-dst -- ) -- )
-    #! If the destination register overlaps a small register, we
-    #! call the quot with that. Otherwise, we find a small
-    #! register that is not in exclude, and call quot, saving
-    #! and restoring the small register.
-    dst small-reg-native small-regs memq? [ dst quot call ] [
+:: with-small-register ( dst exclude size quot: ( new-dst -- ) -- )
+    ! If the destination register overlaps a small register with
+    ! 'size' bits, we call the quot with that. Otherwise, we find a
+    ! small register that is not in exclude, and call quot, saving and
+    ! restoring the small register.
+    dst size has-small-reg? [ dst quot call ] [
         exclude small-reg-that-isn't
         [ quot call ] with-save/restore
     ] if ; inline
 
-: shift-count? ( reg -- ? ) { ECX RCX } memq? ;
-
-:: emit-shift ( dst src1 src2 quot -- )
-    src2 shift-count? [
-        dst CL quot call
-    ] [
-        dst shift-count? [
-            dst src2 XCHG
-            src2 CL quot call
-            dst src2 XCHG
-        ] [
-            ECX small-reg-native [
-                CL src2 MOV
-                drop dst CL quot call
-            ] with-save/restore
-        ] if
-    ] if ; inline
-
-M: x86 %shl [ SHL ] emit-shift ;
-M: x86 %shr [ SHR ] emit-shift ;
-M: x86 %sar [ SAR ] emit-shift ;
-
 M:: x86 %string-nth ( dst src index temp -- )
+    ! We request a small-reg of size 8 since those of size 16 are
+    ! a superset.
     "end" define-label
-    dst { src index temp } [| new-dst |
+    dst { src index temp } [| new-dst |
         ! Load the least significant 7 bits into new-dst.
         ! 8th bit indicates whether we have to load from
         ! the aux vector or not.
         temp src index [+] LEA
-        new-dst 1 small-reg temp string-offset [+] MOV
-        new-dst new-dst 1 small-reg MOVZX
+        new-dst 8-bit-version-of temp string-offset [+] MOV
+        new-dst new-dst 8-bit-version-of MOVZX
         ! Do we have to look at the aux vector?
         new-dst HEX: 80 CMP
         "end" get JL
@@ -392,8 +322,8 @@ M:: x86 %string-nth ( dst src index temp -- )
         new-dst index ADD
         new-dst index ADD
         ! Load high 16 bits
-        new-dst 2 small-reg new-dst byte-array-offset [+] MOV
-        new-dst new-dst 2 small-reg MOVZX
+        new-dst 16-bit-version-of new-dst byte-array-offset [+] MOV
+        new-dst new-dst 16-bit-version-of MOVZX
         new-dst 7 SHL
         ! Compute code point
         new-dst temp XOR
@@ -402,15 +332,15 @@ M:: x86 %string-nth ( dst src index temp -- )
     ] with-small-register ;
 
 M:: x86 %set-string-nth-fast ( ch str index temp -- )
-    ch { index str temp } [| new-ch |
+    ch { index str temp } [| new-ch |
         new-ch ch ?MOV
         temp str index [+] LEA
-        temp string-offset [+] new-ch 1 small-reg MOV
+        temp string-offset [+] new-ch 8-bit-version-of MOV
     ] with-small-register ;
 
 :: %alien-integer-getter ( dst src size quot -- )
-    dst { src } [| new-dst |
-        new-dst dup size small-reg dup src [] MOV
+    dst { src } size [| new-dst |
+        new-dst dup size n-bit-version-of dup src [] MOV
         quot call
         dst new-dst ?MOV
     ] with-small-register ; inline
@@ -418,35 +348,56 @@ M:: x86 %set-string-nth-fast ( ch str index temp -- )
 : %alien-unsigned-getter ( dst src size -- )
     [ MOVZX ] %alien-integer-getter ; inline
 
-M: x86 %alien-unsigned-1 1 %alien-unsigned-getter ;
-M: x86 %alien-unsigned-2 2 %alien-unsigned-getter ;
+M: x86 %alien-unsigned-1 8 %alien-unsigned-getter ;
+M: x86 %alien-unsigned-2 16 %alien-unsigned-getter ;
+M: x86 %alien-unsigned-4 32 [ 2drop ] %alien-integer-getter ;
 
 : %alien-signed-getter ( dst src size -- )
     [ MOVSX ] %alien-integer-getter ; inline
 
-M: x86 %alien-signed-1 1 %alien-signed-getter ;
-M: x86 %alien-signed-2 2 %alien-signed-getter ;
-M: x86 %alien-signed-4 4 %alien-signed-getter ;
-
-M: x86 %alien-unsigned-4 4 [ 2drop ] %alien-integer-getter ;
+M: x86 %alien-signed-1 8 %alien-signed-getter ;
+M: x86 %alien-signed-2 16 %alien-signed-getter ;
+M: x86 %alien-signed-4 32 %alien-signed-getter ;
 
 M: x86 %alien-cell [] MOV ;
 M: x86 %alien-float dupd [] MOVSS dup CVTSS2SD ;
 M: x86 %alien-double [] MOVSD ;
 
 :: %alien-integer-setter ( ptr value size -- )
-    value { ptr } [| new-value |
+    value { ptr } size [| new-value |
         new-value value ?MOV
-        ptr [] new-value size small-reg MOV
+        ptr [] new-value size n-bit-version-of MOV
     ] with-small-register ; inline
 
-M: x86 %set-alien-integer-1 1 %alien-integer-setter ;
-M: x86 %set-alien-integer-2 2 %alien-integer-setter ;
-M: x86 %set-alien-integer-4 4 %alien-integer-setter ;
+M: x86 %set-alien-integer-1 8 %alien-integer-setter ;
+M: x86 %set-alien-integer-2 16 %alien-integer-setter ;
+M: x86 %set-alien-integer-4 32 %alien-integer-setter ;
 M: x86 %set-alien-cell [ [] ] dip MOV ;
 M: x86 %set-alien-float dup dup CVTSD2SS [ [] ] dip MOVSS ;
 M: x86 %set-alien-double [ [] ] dip MOVSD ;
 
+: shift-count? ( reg -- ? ) { ECX RCX } memq? ;
+
+:: emit-shift ( dst src1 src2 quot -- )
+    src2 shift-count? [
+        dst CL quot call
+    ] [
+        dst shift-count? [
+            dst src2 XCHG
+            src2 CL quot call
+            dst src2 XCHG
+        ] [
+            ECX native-version-of [
+                CL src2 MOV
+                drop dst CL quot call
+            ] with-save/restore
+        ] if
+    ] if ; inline
+
+M: x86 %shl [ SHL ] emit-shift ;
+M: x86 %shr [ SHR ] emit-shift ;
+M: x86 %sar [ SAR ] emit-shift ;
+
 : load-zone-ptr ( reg -- )
     #! Load pointer to start of zone array
     0 MOV "nursery" f rc-absolute-cell rel-dlsym ;
@@ -484,38 +435,19 @@ M:: x86 %write-barrier ( src card# table -- )
     table table [] MOV
     table card# [+] card-mark <byte> MOV ;
 
-:: check-nursery ( temp1 temp2 -- )
+M:: x86 %check-nursery ( label temp1 temp2 -- )
     temp1 load-zone-ptr
     temp2 temp1 cell [+] MOV
     temp2 1024 ADD
     temp1 temp1 3 cells [+] MOV
-    temp2 temp1 CMP ;
-
-GENERIC# save-gc-root 1 ( gc-root operand temp -- )
-
-M:: spill-slot save-gc-root ( gc-root spill-slot temp -- )
-    temp spill-slot n>> spill-integer@ MOV
-    gc-root gc-root@ temp MOV ;
+    temp2 temp1 CMP
+    label JLE ;
 
-M:: word save-gc-root ( gc-root register temp -- )
-    gc-root gc-root@ register MOV ;
+M: x86 %save-gc-root ( gc-root register -- ) [ gc-root@ ] dip MOV ;
 
-: save-gc-roots ( gc-roots temp -- )
-    '[ _ save-gc-root ] assoc-each ;
+M: x86 %load-gc-root ( gc-root register -- ) swap gc-root@ MOV ;
 
-GENERIC# load-gc-root 1 ( gc-root operand temp -- )
-
-M:: spill-slot load-gc-root ( gc-root spill-slot temp -- )
-    temp gc-root gc-root@ MOV
-    spill-slot n>> spill-integer@ temp MOV ;
-
-M:: word load-gc-root ( gc-root register temp -- )
-    register gc-root gc-root@ MOV ;
-
-: load-gc-roots ( gc-roots temp -- )
-    '[ _ load-gc-root ] assoc-each ;
-
-:: call-gc ( gc-root-count -- )
+M:: x86 %call-gc ( gc-root-count -- )
     ! Pass pointer to start of GC roots as first parameter
     param-reg-1 gc-root-base param@ LEA
     ! Pass number of roots as second parameter
@@ -524,15 +456,6 @@ M:: word load-gc-root ( gc-root register temp -- )
     %prepare-alien-invoke
     "inline_gc" f %alien-invoke ;
 
-M:: x86 %gc ( temp1 temp2 gc-roots gc-root-count -- )
-    "end" define-label
-    temp1 temp2 check-nursery
-    "end" get JLE
-    gc-roots temp1 save-gc-roots
-    gc-root-count call-gc
-    gc-roots temp1 load-gc-roots
-    "end" resolve-label ;
-
 M: x86 %alien-global
     [ 0 MOV ] 2dip rc-absolute-cell rel-dlsym ;
 
index b4761075628044451643170673cbabd6267c3d9b..c1985c516f995cdee7c614985f4e9330a4b7c36e 100644 (file)
@@ -52,7 +52,7 @@ IN: heaps.tests
 ] each
 
 : sort-entries ( entries -- entries' )
-    [ [ key>> ] compare ] sort ;
+    [ key>> ] sort-with ;
 
 : delete-test ( n -- obj1 obj2 )
     [
index 84f708a6870a4a39754061286c4b6355ad7f6a0b..e8cc7e04c544fc878e480593842b95c3053a7423 100644 (file)
@@ -73,7 +73,7 @@ M: topic url-of topic>filename ;
     dup topic>filename utf8 [ help>html write-xml ] with-file-writer ;
 
 : all-vocabs-really ( -- seq )
-    all-vocabs >hashtable f over delete-at no-roots remove-redundant-prefixes ;
+    all-vocabs-recursive >hashtable f over delete-at no-roots remove-redundant-prefixes ;
 
 : all-topics ( -- topics )
     [
@@ -115,7 +115,7 @@ TUPLE: result title href ;
     load-index swap >lower
     '[ [ drop _ ] dip >lower subseq? ] assoc-filter
     [ swap result boa ] { } assoc>map
-    [ [ title>> ] compare ] sort ;
+    [ title>> ] sort-with ;
 
 : article-apropos ( string -- results )
     "articles.idx" offline-apropos ;
index 22283deecb5971a7c0a9caa3c2ac89c076f7def0..b94266282cf057ee19d048bb79d14bf8adfe6bfd 100644 (file)
@@ -46,7 +46,7 @@ PRIVATE>
     array>> [ value ] map ;\r
 \r
 : <interval-map> ( specification -- map )\r
-    all-intervals [ [ first second ] compare ] sort\r
+    all-intervals [ first second ] sort-with\r
     >intervals ensure-disjoint interval-map boa ;\r
 \r
 : <interval-set> ( specification -- map )\r
index 088de527665d0667adbae979b806174237314f01..3dec6130de5a3e83b747cbeeff0a078e10d52294 100644 (file)
@@ -64,6 +64,6 @@ TUPLE: upward-slice < slice ;
             drop
             [ downward-slices ]
             [ stable-slices ]
-            [ upward-slices ] tri 3append [ [ from>> ] compare ] sort
+            [ upward-slices ] tri 3append [ from>> ] sort-with
         ]
     } case ;
index 159da59be5a1e0013be2ad79898c7552fd7eaa9a..70818262c5542143fc8def2109cf3d223baca3d1 100644 (file)
@@ -65,7 +65,7 @@ M: ---- <menu-item>
 : <operations-menu> ( target hook -- menu )
     over object-operations
     [ primary-operation? ] partition
-    [ reverse ] [ [ [ command-name ] compare ] sort ] bi*
+    [ reverse ] [ [ command-name ] sort-with ] bi*
     { ---- } glue <commands-menu> ;
 
 : show-operations-menu ( gadget target hook -- )
index 35fa5e3c172dccc983802f044cf7a4f5563499c7..b4a772dca56847465e4c78816caafd133b2a5449 100644 (file)
@@ -57,7 +57,7 @@ M: object make-slot-descriptions
     make-mirror [ <slot-description> ] { } assoc>map ;
 
 M: hashtable make-slot-descriptions
-    call-next-method [ [ key-string>> ] compare ] sort ;
+    call-next-method [ key-string>> ] sort-with ;
 
 : <inspector-table> ( model -- table )
     [ make-slot-descriptions ] <arrow> inspector-renderer <table>
index 0e150ef07a7d1e38949202bc5a60cf43ddb1fb81..66bc277ef7d3f1bc50e9e2fe2082e9080b17048f 100644 (file)
@@ -14,7 +14,7 @@ IN: vocabs.prettyprint
 <PRIVATE
 
 : sort-vocabs ( seq -- seq' )
-    [ [ vocab-name ] compare ] sort ;
+    [ vocab-name ] sort-with ;
 
 : pprint-using ( seq -- )
     [ "syntax" vocab = not ] filter
index 74ba931c7998aa871d13d9e151b847e1d397e5d9..e371c3aab5c6b0acdc62f250b657d3275cf60ee7 100644 (file)
@@ -73,3 +73,7 @@ SYMBOL: xml-file
 [ T{ xml-chunk f V{ "hello" } } ] [ "hello" string>xml-chunk ] unit-test
 [ "1.1" ] [ "<?xml version='1.1'?><x/>" string>xml prolog>> version>> ] unit-test
 [ "ß" ] [ "<x>ß</x>" <string-reader> read-xml children>string ] unit-test
+
+! <pull-xml> tests
+! this tests just checks that pull-event doesn't raise an exception
+[ ] [ "vocab:xml/tests/test.xml" binary [ <pull-xml> pull-event drop ] with-file-reader ] unit-test
\ No newline at end of file
index cca1b5e2e0cf4160f8538a39e59b73b983e4ceab..a1d734f291e5e356b91be503809c0ca003993127 100755 (executable)
@@ -110,6 +110,7 @@ PRIVATE>
 TUPLE: pull-xml scope ;
 : <pull-xml> ( -- pull-xml )
     [
+        init-parser
         input-stream [ ] change ! bring var in this scope
         init-xml text-now? on
     ] H{ } make-assoc
index 0dd808c7227faf0d88c066b014ff58431b896f9b..5fe46b532f40f9cbe5b54dd08996028a2c65c4af 100644 (file)
@@ -56,7 +56,7 @@ M: checksum checksum-lines
     [ B{ CHAR: \n } join ] dip checksum-bytes ;
 
 : checksum-file ( path checksum -- value )
-    #! normalize-path (file-reader) is equivalen to
+    #! normalize-path (file-reader) is equivalent to
     #! binary <file-reader>. We use the lower-level form
     #! so that we can move io.encodings.binary to basis/.
     [ normalize-path (file-reader) ] dip checksum-stream ;
index 6d221c138007c9d8f974d8d91143584f480444bc..6bfc94d79a8a390dcfcd5b9762742c91be0d6074 100755 (executable)
@@ -207,7 +207,7 @@ M: anonymous-complement (classes-intersect?)
     [ "Topological sort failed" throw ] unless* ;\r
 \r
 : sort-classes ( seq -- newseq )\r
-    [ [ name>> ] compare ] sort >vector\r
+    [ name>> ] sort-with >vector\r
     [ dup empty? not ]\r
     [ dup largest-class [ over delete-nth ] dip ]\r
     produce nip ;\r
index 109a3b8089d58038cdf889c5d1ab169899823006..32bf483f7218f307ea51dbaad7dbb46cad08a974 100644 (file)
@@ -35,6 +35,7 @@ $nl
 "You can ask a class for its superclass:"
 { $subsection superclass }
 { $subsection superclasses }
+{ $subsection subclass-of? }
 "Class predicates can be used to test instances directly:"
 { $subsection "class-predicates" }
 "There is a universal class which all objects are an instance of, and an empty class with no instances:"
@@ -102,7 +103,21 @@ HELP: superclasses
     }
 } ;
 
-{ superclass superclasses } related-words
+HELP: subclass-of?
+{ $values
+    { "class" class }
+    { "superclass" class }
+    { "?" boolean }
+}
+{ $description "Outputs a boolean value indicating whether " { $snippet "class" } " is at any level a subclass of " { $snippet "superclass" } "." }
+{ $examples 
+    { $example "USING: classes classes.tuple prettyprint words ;"
+               "tuple-class \\ class subclass-of? ."
+               "t"
+    }
+} ;
+
+{ superclass superclasses subclass-of? } related-words
 
 HELP: members
 { $values { "class" class } { "seq" "a sequence of union members, or " { $link f } } }
index dfaec95f76841430496194e14c83a3e369bcbc9d..f0093684201a1b8ea841348ac1d00d1467801559 100644 (file)
@@ -59,6 +59,9 @@ M: predicate reset-word
 : superclasses ( class -- supers )
     [ superclass ] follow reverse ;
 
+: subclass-of? ( class superclass -- ? )
+    swap superclasses member? ;
+
 : members ( class -- seq )
     #! Output f for non-classes to work with algebra code
     dup class? [ "members" word-prop ] [ drop f ] if ;
index 72602c25b90abcb5f383dc697d1e5280dbd6f58a..8893db392925f229d89de25d27032b6045097852 100755 (executable)
@@ -354,6 +354,22 @@ HELP: spread
 
 { bi* tri* spread } related-words
 
+HELP: to-fixed-point
+{ $values { "object" object } { "quot" { $quotation "( object(n) -- object(n+1) )" } } { "object(n)" object } }
+{ $description "Applies the quotation repeatedly with " { $snippet "object" } " as the initial input until the output of the quotation equals the input." }
+{ $examples
+    { $example
+        "USING: combinators kernel math prettyprint sequences ;"
+        "IN: scratchpad"
+        ": flatten ( sequence -- sequence' )"
+        "    \"flatten\" over index"
+        "    [ [ 1 + swap nth ] [ nip dup 2 + ] [ drop ] 2tri replace-slice ] when* ;"
+        ""
+        "{ \"flatten\" { 1 { 2 3 } \"flatten\" { 4 5 } { 6 } } } [ flatten ] to-fixed-point ."
+        "{ 1 { 2 3 } 4 5 { 6 } }"
+    }
+} ;
+
 HELP: alist>quot
 { $values { "default" "a quotation" } { "assoc" "a sequence of quotation pairs" } { "quot" "a new quotation" } }
 { $description "Constructs a quotation which calls the first quotation in each pair of " { $snippet "assoc" } " until one of them outputs a true value, and then calls the second quotation in the corresponding pair. Quotations are called in reverse order, and if no quotation outputs a true value then " { $snippet "default" } " is called." }
index f293030f25787dc696dcc80b65b752baf83f6ef2..2bef1a568a1b3dd99d6b350aa56cb56e11a56963 100755 (executable)
@@ -113,7 +113,7 @@ ERROR: no-case object ;
     ] if ;
 
 : <buckets> ( initial length -- array )
-    next-power-of-2 swap [ nip clone ] curry map ;
+    next-power-of-2 iota swap [ nip clone ] curry map ;
 
 : distribute-buckets ( alist initial quot -- buckets )
     swapd [ [ dup first ] dip call 2array ] curry map
@@ -180,3 +180,6 @@ M: hashtable hashcode*
         dup assoc-size 1 eq?
         [ assoc-hashcode ] [ nip assoc-size ] if
     ] recursive-hashcode ;
+
+: to-fixed-point ( object quot: ( object(n) -- object(n+1) ) -- object(n) )
+    [ keep over = ] keep [ to-fixed-point ] curry unless ; inline recursive
index 9a773f43a2b5c0f78fe38afb6896243cbd0ec365..88387abd5cfcc0daee887e41046dff8acb12d214 100644 (file)
@@ -145,7 +145,7 @@ GENERIC: compile-engine ( engine -- obj )
     default get <array> [ <enum> swap update ] keep ;
 
 : lo-tag-number ( class -- n )
-    "type" word-prop dup num-tags get member?
+    "type" word-prop dup num-tags get iota member?
     [ drop object tag-number ] unless ;
 
 M: tag-dispatch-engine compile-engine
index cf2781aac074c1022d45e99f79fb63f2d4760a14..f5467daea6bc1b053584319d1bdbd98ed88051bc 100644 (file)
@@ -10,7 +10,7 @@ IN: io.binary
 
 : nth-byte ( x n -- b ) -8 * shift mask-byte ; inline
 
-: >le ( x n -- byte-array ) [ nth-byte ] with B{ } map-as ;
+: >le ( x n -- byte-array ) iota [ nth-byte ] with B{ } map-as ;
 : >be ( x n -- byte-array ) >le dup reverse-here ;
 
 : d>w/w ( d -- w1 w2 )
index 733283d2982f791d40dda509a735ee71b0722687..63a905d57805595813671f8eb426cb134e0c3eea 100644 (file)
@@ -23,6 +23,24 @@ HELP: file-name
     { $example "USING: io.pathnames prettyprint ;" "\"/usr/libexec/awk/\" file-name ." "\"awk\"" }
 } ;
 
+HELP: file-extension
+{ $values { "path" "a pathname string" } { "extension" string } }
+{ $description "Outputs the extension of " { $snippet "path" } ", or " { $link f } " if the filename has no extension." }
+{ $examples
+    { $example "USING: io.pathnames prettyprint ;" "\"/usr/bin/gcc\" file-extension ." "f" }
+    { $example "USING: io.pathnames prettyprint ;" "\"/home/csi/gui.vbs\" file-extension ." "\"vbs\"" }
+} ;
+
+HELP: file-stem
+{ $values { "path" "a pathname string" } { "stem" string } }
+{ $description "Outputs the " { $link file-name } " of " { $snippet "filename" } " with the file extension removed, if any." }
+{ $examples
+    { $example "USING: io.pathnames prettyprint ;" "\"/usr/bin/gcc\" file-stem ." "\"gcc\"" }
+    { $example "USING: io.pathnames prettyprint ;" "\"/home/csi/gui.vbs\" file-stem ." "\"gui\"" }
+} ;
+
+{ file-name file-stem file-extension } related-words
+
 HELP: path-components
 { $values { "path" "a pathnames string" } { "seq" sequence } }
 { $description "Splits a pathname on the " { $link path-separator } " into its its component strings." } ;
@@ -86,6 +104,8 @@ ARTICLE: "io.pathnames" "Pathname manipulation"
 "Pathname manipulation:"
 { $subsection parent-directory }
 { $subsection file-name }
+{ $subsection file-stem }
+{ $subsection file-extension }
 { $subsection last-path-separator }
 { $subsection path-components }
 { $subsection prepend-path }
index 30e9e6c2065a8e6601b875f806c8921bd18652a7..6a49ed5797dd05aa0d0a98bec7a4850fc8312cf3 100644 (file)
@@ -118,7 +118,10 @@ PRIVATE>
         ] if
     ] unless ;
 
-: file-extension ( filename -- extension )
+: file-stem ( path -- stem )
+    file-name "." split1-last drop ;
+
+: file-extension ( path -- extension )
     file-name "." split1-last nip ;
 
 : path-components ( path -- seq )
index f8bdaa1dbbf7330de7b21248c9c46bc4c546b14e..8b6aa3a3d3b9e22ced3b5c6462ff99f6c40cf9e9 100644 (file)
@@ -8,7 +8,7 @@ SYMBOL: building
 : make ( quot exemplar -- seq )
     [
         [
-            1024 swap new-resizable [
+            100 swap new-resizable [
                 building set call
             ] keep
         ] keep like
index 17dbcf5c3cbb8b7a87e8df8d00cafe7de0801e07..92a3495ba8672ef3b5ad41cf08d9bc81d2753f91 100755 (executable)
@@ -701,7 +701,7 @@ PRIVATE>
     3tri ;
 
 : reverse-here ( seq -- )
-    [ length 2/ ] [ length ] [ ] tri
+    [ length 2/ iota ] [ length ] [ ] tri
     [ [ over - 1 - ] dip exchange-unsafe ] 2curry each ;
 
 : reverse ( seq -- newseq )
@@ -805,14 +805,14 @@ PRIVATE>
 <PRIVATE
 
 : (start) ( subseq seq n -- subseq seq ? )
-    pick length [
+    pick length iota [
         [ 3dup ] dip [ + swap nth-unsafe ] keep rot nth-unsafe =
     ] all? nip ; inline
 
 PRIVATE>
 
 : start* ( subseq seq n -- i )
-    pick length pick length swap - 1 +
+    pick length pick length swap - 1 + iota
     [ (start) ] find-from
     swap [ 3drop ] dip ;
 
index 304ded0adbb5e836fb05732c9d5f4a8290735604..9215857018e4e375c36e58773deab61f6a912777 100755 (executable)
@@ -26,8 +26,10 @@ PREDICATE: writer-method < method-body "writing" word-prop ;
     [ drop define ]
     3bi ;
 
-: reader-quot ( slot-spec -- quot )
-    [
+GENERIC# reader-quot 1 ( class slot-spec -- quot )
+
+M: object reader-quot 
+    nip [
         dup offset>> ,
         \ slot ,
         dup class>> object bootstrap-word eq?
@@ -51,8 +53,12 @@ PREDICATE: writer-method < method-body "writing" word-prop ;
 : define-reader ( class slot-spec -- )
     [ nip name>> define-reader-generic ]
     [
-        [ name>> reader-word ] [ reader-quot ] [ reader-props ] tri
-        define-typecheck
+        {
+            [ drop ]
+            [ nip name>> reader-word ]
+            [ reader-quot ]
+            [ nip reader-props ]
+        } 2cleave define-typecheck
     ] 2bi ;
 
 : writer-word ( name -- word )
@@ -83,8 +89,10 @@ ERROR: bad-slot-value value class ;
 : writer-quot/fixnum ( slot-spec -- )
     [ [ >fixnum ] dip ] % writer-quot/check ;
 
-: writer-quot ( slot-spec -- quot )
-    [
+GENERIC# writer-quot 1 ( class slot-spec -- quot )
+
+M: object writer-quot
+    nip [
         {
             { [ dup class>> object bootstrap-word eq? ] [ writer-quot/object ] }
             { [ dup class>> "coercer" word-prop ] [ writer-quot/coerce ] }
@@ -101,8 +109,12 @@ ERROR: bad-slot-value value class ;
 
 : define-writer ( class slot-spec -- )
     [ nip name>> define-writer-generic ] [
-        [ name>> writer-word ] [ writer-quot ] [ writer-props ] tri
-        define-typecheck
+        {
+            [ drop ]
+            [ nip name>> writer-word ]
+            [ writer-quot ]
+            [ nip writer-props ]
+        } 2cleave define-typecheck
     ] 2bi ;
 
 : setter-word ( name -- word )
index 290ca1470cc68f1a1f8bd38e75df59f68876f4e1..c30c06a989bd0c528f7c75bfa3e9c851929143bc 100644 (file)
@@ -12,6 +12,8 @@ $nl
 "Sorting a sequence with a custom comparator:"
 { $subsection sort }
 "Sorting a sequence with common comparators:"
+{ $subsection sort-with }
+{ $subsection inv-sort-with }
 { $subsection natural-sort }
 { $subsection sort-keys }
 { $subsection sort-values } ;
@@ -20,16 +22,24 @@ ABOUT: "sequences-sorting"
 
 HELP: sort
 { $values { "seq" "a sequence" } { "quot" { $quotation "( obj1 obj2 -- <=> )" } } { "sortedseq" "a new sorted sequence" } }
-{ $description "Sorts the elements into a new array using a stable sort." }
+{ $description "Sorts the elements of " { $snippet "seq" } " into a new array using a stable sort." }
 { $notes "The algorithm used is the merge sort." } ;
 
+HELP: sort-with
+{ $values { "seq" "a sequence" } { "quot" { $quotation "( object -- key )" } } { "sortedseq" "a new sorted sequence" } }
+{ $description "Sorts the elements of " { $snippet "seq" } " by applying " { $link compare } " with " { $snippet "quot" } " to each pair of elements in the sequence." } ;
+
+HELP: inv-sort-with
+{ $values { "seq" "a sequence" } { "quot" { $quotation "( object -- key )" } } { "sortedseq" "a new sorted sequence" } }
+{ $description "Sorts the elements of " { $snippet "seq" } " by applying " { $link compare } " with " { $snippet "quot" } " to each pair of elements in the sequence and inverting the results." } ;
+
 HELP: sort-keys
 { $values { "seq" "an alist" } { "sortedseq" "a new sorted sequence" } }
-{ $description "Sorts the elements comparing first elements of pairs using the " { $link <=> } " word." } ;
+{ $description "Sorts the elements of " { $snippet "seq" } " comparing first elements of pairs using the " { $link <=> } " word." } ;
 
 HELP: sort-values
 { $values { "seq" "an alist" } { "sortedseq" "a new sorted sequence" } }
-{ $description "Sorts the elements comparing second elements of pairs using the " { $link <=> } " word." } ;
+{ $description "Sorts the elements of " { $snippet "seq" } " comparing second elements of pairs using the " { $link <=> } " word." } ;
 
 HELP: natural-sort
 { $values { "seq" "a sequence of real numbers" } { "sortedseq" "a new sorted sequence" } }
@@ -43,4 +53,4 @@ HELP: midpoint@
 { $values { "seq" "a sequence" } { "n" integer } }
 { $description "Outputs the index of the midpoint of " { $snippet "seq" } "." } ;
 
-{ <=> compare natural-sort sort-keys sort-values } related-words
+{ <=> compare natural-sort sort-with inv-sort-with sort-keys sort-values } related-words
index 0c0951bbceb5d150ccd64fde3bad33762e3ab62e..b8258b239bfebd28e1d126d22541262de9374a2e 100644 (file)
@@ -155,8 +155,13 @@ PRIVATE>
 
 : natural-sort ( seq -- sortedseq ) [ <=> ] sort ;
 
-: sort-keys ( seq -- sortedseq ) [ [ first ] compare ] sort ;
+: sort-with ( seq quot -- sortedseq )
+    [ compare ] curry sort ; inline
+: inv-sort-with ( seq quot -- sortedseq )
+    [ compare invert-comparison ] curry sort ; inline
 
-: sort-values ( seq -- sortedseq ) [ [ second ] compare ] sort ;
+: sort-keys ( seq -- sortedseq ) [ first ] sort-with ;
+
+: sort-values ( seq -- sortedseq ) [ second ] sort-with ;
 
 : sort-pair ( a b -- c d ) 2dup after? [ swap ] when ;
index f6f4f4825aaf9b8da76ff17d9b01d402557f7267..86a8354071e5c54f90103324c3039847cb567c98 100644 (file)
@@ -7,7 +7,7 @@ IN: source-files.errors
 TUPLE: source-file-error error asset file line# ;
 
 : sort-errors ( errors -- alist )
-    [ [ [ line#>> ] compare ] sort ] { } assoc-map-as sort-keys ;
+    [ [ line#>> ] sort-with ] { } assoc-map-as sort-keys ;
 
 : group-by-source-file ( errors -- assoc )
     H{ } clone [ [ push-at ] curry [ dup file>> ] prepose each ] keep ;
index 401934e736af7c47f753d8b1a13ff9edff956a44..4d296cc40283037ae2b9733b3f3631b83cb0dc5a 100644 (file)
@@ -18,6 +18,7 @@ HELP: CM-FUNCTION:
     "C-LIBRARY: exlib"
     ""
     "C-INCLUDE: <stdio.h>"
+    "C-INCLUDE: <stdlib.h>"
     "CM-FUNCTION: char* sum_diff ( const-int a, const-int b, int* x, int* y )"
     "    *x = a + b;"
     "    *y = a - b;"
index d269ef3503b24ac8ead2036542f2352def61dc48..6b3fd41575fbc58ef6d70da405ccfbc895016f1c 100755 (executable)
@@ -6,7 +6,7 @@ IN: benchmark.beust2
 ! http://crazybob.org/BeustSequence.java.html
 
 :: (count-numbers) ( remaining first value used max listener: ( -- ) -- ? )
-    10 first - [| i |
+    10 first - iota [| i |
         [let* | digit [ i first + ]
                 mask [ digit 2^ ]
                 value' [ i value + ] |
@@ -29,7 +29,7 @@ IN: benchmark.beust2
     ] any? ; inline recursive
 
 :: count-numbers ( max listener -- )
-    10 [ 1+ 1 1 0 max listener (count-numbers) ] any? drop ;
+    10 iota [ 1+ 1 1 0 max listener (count-numbers) ] any? drop ;
     inline
 
 :: beust ( -- )
index 0f8a98e6f9dede654385dd0e5472d0702acf1546..d001d81a8ce6b839c50036893776da4b2706e957 100644 (file)
@@ -54,6 +54,6 @@ IN: benchmark.pidigits
     [ 1 { { 1 0 } { 0 1 } } ] dip 0 0 (pidigits) ;
 
 : pidigits-main ( -- )
-    10000 pidigits ;
+    2000 pidigits ;
 
 MAIN: pidigits-main
diff --git a/extra/c/lexer/authors.txt b/extra/c/lexer/authors.txt
new file mode 100644 (file)
index 0000000..b4bd0e7
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
\ No newline at end of file
diff --git a/extra/c/lexer/lexer-tests.factor b/extra/c/lexer/lexer-tests.factor
new file mode 100644 (file)
index 0000000..c972b88
--- /dev/null
@@ -0,0 +1,103 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors c.lexer kernel sequence-parser tools.test ;
+IN: c.lexer.tests
+
+[ 36 ]
+[
+    "    //jofiejoe\n    //eoieow\n/*asdf*/\n      "
+    <sequence-parser> skip-whitespace/comments n>>
+] unit-test
+
+[ f "33asdf" ]
+[ "33asdf" <sequence-parser> [ take-c-identifier ] [ take-rest ] bi ] unit-test
+
+[ "asdf" ]
+[ "asdf" <sequence-parser> take-c-identifier ] unit-test
+
+[ "_asdf" ]
+[ "_asdf" <sequence-parser> take-c-identifier ] unit-test
+
+[ "_asdf400" ]
+[ "_asdf400" <sequence-parser> take-c-identifier ] unit-test
+
+[ "asdfasdf" ] [
+    "/*asdfasdf*/" <sequence-parser> take-c-comment
+] unit-test
+
+[ "k" ] [
+    "/*asdfasdf*/k" <sequence-parser> [ take-c-comment drop ] [ take-rest ] bi
+] unit-test
+
+[ "omg" ] [
+    "//asdfasdf\nomg" <sequence-parser>
+    [ take-c++-comment drop ] [ take-rest ] bi
+] unit-test
+
+[ "omg" ] [
+    "omg" <sequence-parser>
+    [ take-c++-comment drop ] [ take-rest ] bi
+] unit-test
+
+[ "/*asdfasdf" ] [
+    "/*asdfasdf" <sequence-parser> [ take-c-comment drop ] [ take-rest ] bi
+] unit-test
+
+[ "asdf" "eoieoei" ] [
+    "//asdf\neoieoei" <sequence-parser>
+    [ take-c++-comment ] [ take-rest ] bi
+] unit-test
+
+[ f ]
+[
+    "\"abc\" asdf" <sequence-parser>
+    [ CHAR: \ CHAR: " take-quoted-string drop ] [ "asdf" take-sequence ] bi
+] unit-test
+
+[ "abc\\\"def" ]
+[
+    "\"abc\\\"def\" asdf" <sequence-parser>
+    CHAR: \ CHAR: " take-quoted-string
+] unit-test
+
+[ "asdf" ]
+[
+    "\"abc\" asdf" <sequence-parser>
+    [ CHAR: \ CHAR: " take-quoted-string drop ]
+    [ skip-whitespace "asdf" take-sequence ] bi
+] unit-test
+
+[ f ]
+[
+    "\"abc asdf" <sequence-parser>
+    CHAR: \ CHAR: " take-quoted-string
+] unit-test
+
+[ "\"abc" ]
+[
+    "\"abc asdf" <sequence-parser>
+    [ CHAR: \ CHAR: " take-quoted-string drop ]
+    [ "\"abc" take-sequence ] bi
+] unit-test
+
+[ "c" ]
+[ "c" <sequence-parser> take-token ] unit-test
+
+[ f ]
+[ "" <sequence-parser> take-token ] unit-test
+
+[ "abcd e \\\"f g" ]
+[ "\"abcd e \\\"f g\"" <sequence-parser> CHAR: \ CHAR: " take-token* ] unit-test
+
+[ "123" ]
+[ "123jjj" <sequence-parser> take-c-integer ] unit-test
+
+[ "123uLL" ]
+[ "123uLL" <sequence-parser> take-c-integer ] unit-test
+
+[ "123ull" ]
+[ "123ull" <sequence-parser> take-c-integer ] unit-test
+
+[ "123u" ]
+[ "123u" <sequence-parser> take-c-integer ] unit-test
+
diff --git a/extra/c/lexer/lexer.factor b/extra/c/lexer/lexer.factor
new file mode 100644 (file)
index 0000000..962407e
--- /dev/null
@@ -0,0 +1,123 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors combinators combinators.short-circuit
+generalizations kernel locals math.order math.ranges
+sequence-parser sequences sorting.functor sorting.slots
+unicode.categories ;
+IN: c.lexer
+
+: take-c-comment ( sequence-parser -- seq/f )
+    [
+        dup "/*" take-sequence [
+            "*/" take-until-sequence*
+        ] [
+            drop f
+        ] if
+    ] with-sequence-parser ;
+
+: take-c++-comment ( sequence-parser -- seq/f )
+    [
+        dup "//" take-sequence [
+            [
+                [
+                    { [ current CHAR: \n = ] [ sequence-parse-end? ] } 1||
+                ] take-until
+            ] [
+                advance drop
+            ] bi
+        ] [
+            drop f
+        ] if
+    ] with-sequence-parser ;
+
+: skip-whitespace/comments ( sequence-parser -- sequence-parser )
+    skip-whitespace-eol
+    {
+        { [ dup take-c-comment ] [ skip-whitespace/comments ] }
+        { [ dup take-c++-comment ] [ skip-whitespace/comments ] }
+        [ ]
+    } cond ;
+
+: take-define-identifier ( sequence-parser -- string )
+    skip-whitespace/comments
+    [ current { [ blank? ] [ CHAR: ( = ] } 1|| ] take-until ;
+
+:: take-quoted-string ( sequence-parser escape-char quote-char -- string )
+    sequence-parser n>> :> start-n
+    sequence-parser advance
+    [
+        {
+            [ { [ previous escape-char = ] [ current quote-char = ] } 1&& ]
+            [ current quote-char = not ]
+        } 1||
+    ] take-while :> string
+    sequence-parser current quote-char = [
+        sequence-parser advance* string
+    ] [
+        start-n sequence-parser (>>n) f
+    ] if ;
+
+: (take-token) ( sequence-parser -- string )
+    skip-whitespace [ current { [ blank? ] [ f = ] } 1|| ] take-until ;
+
+:: take-token* ( sequence-parser escape-char quote-char -- string/f )
+    sequence-parser skip-whitespace
+    dup current {
+        { quote-char [ escape-char quote-char take-quoted-string ] }
+        { f [ drop f ] }
+        [ drop (take-token) ]
+    } case ;
+
+: take-token ( sequence-parser -- string/f )
+    CHAR: \ CHAR: " take-token* ;
+
+: c-identifier-begin? ( ch -- ? )
+    CHAR: a CHAR: z [a,b]
+    CHAR: A CHAR: Z [a,b]
+    { CHAR: _ } 3append member? ;
+
+: c-identifier-ch? ( ch -- ? )
+    CHAR: a CHAR: z [a,b]
+    CHAR: A CHAR: Z [a,b]
+    CHAR: 0 CHAR: 9 [a,b]
+    { CHAR: _ } 4 nappend member? ;
+
+: (take-c-identifier) ( sequence-parser -- string/f )
+    dup current c-identifier-begin? [
+        [ current c-identifier-ch? ] take-while
+    ] [
+        drop f
+    ] if ;
+
+: take-c-identifier ( sequence-parser -- string/f )
+    [ (take-c-identifier) ] with-sequence-parser ;
+
+<< "length" [ length ] define-sorting >>
+
+: sort-tokens ( seq -- seq' )
+    { length>=< <=> } sort-by ;
+
+: take-c-integer ( sequence-parser -- string/f )
+    [
+        dup take-integer [
+            swap
+            { "ull" "uLL" "Ull" "ULL" "ll" "LL" "l" "L" "u" "U" }
+            take-longest [ append ] when*
+        ] [
+            drop f
+        ] if*
+    ] with-sequence-parser ;
+
+CONSTANT: c-punctuators
+    {
+        "[" "]" "(" ")" "{" "}" "." "->"
+        "++" "--" "&" "*" "+" "-" "~" "!"
+        "/" "%" "<<" ">>" "<" ">" "<=" ">=" "==" "!=" "^" "|" "&&" "||"
+        "?" ":" ";" "..."
+        "=" "*=" "/=" "%=" "+=" "-=" "<<=" ">>=" "&=" "^=" "|="
+        "," "#" "##"
+        "<:" ":>" "<%" "%>" "%:" "%:%:"
+    }
+
+: take-c-punctuator ( sequence-parser -- string/f )
+    c-punctuators take-longest ;
index f787befc3116a1a0234eae644b401daac18c001d..3018fa7a2469d400d9ffd5930bea8b5fa646778f 100644 (file)
@@ -4,7 +4,7 @@ USING: sequence-parser io io.encodings.utf8 io.files
 io.streams.string kernel combinators accessors io.pathnames
 fry sequences arrays locals namespaces io.directories
 assocs math splitting make unicode.categories
-combinators.short-circuit ;
+combinators.short-circuit c.lexer ;
 IN: c.preprocessor
 
 : initial-library-paths ( -- seq )
diff --git a/extra/classes/tuple/change-tracking/authors.txt b/extra/classes/tuple/change-tracking/authors.txt
new file mode 100644 (file)
index 0000000..f13c9c1
--- /dev/null
@@ -0,0 +1 @@
+Joe Groff
diff --git a/extra/classes/tuple/change-tracking/change-tracking-tests.factor b/extra/classes/tuple/change-tracking/change-tracking-tests.factor
new file mode 100644 (file)
index 0000000..633707b
--- /dev/null
@@ -0,0 +1,10 @@
+USING: classes.tuple.change-tracking tools.test strings accessors kernel continuations ;
+IN: classes.tuple.change-tracking.tests
+
+TUPLE: resource < change-tracking-tuple
+    { pathname string } ;
+
+: <resource> ( pathname -- resource ) f swap resource boa ;
+
+[ t ] [ "foo" <resource> "bar" >>pathname changed?>> ] unit-test
+[ f ] [ "foo" <resource> [ 123 >>pathname ] [ drop ] recover changed?>> ] unit-test
diff --git a/extra/classes/tuple/change-tracking/change-tracking.factor b/extra/classes/tuple/change-tracking/change-tracking.factor
new file mode 100644 (file)
index 0000000..3e21092
--- /dev/null
@@ -0,0 +1,23 @@
+! (c)2009 Joe Groff bsd license
+USING: accessors classes classes.tuple fry kernel sequences slots ;
+IN: classes.tuple.change-tracking
+
+TUPLE: change-tracking-tuple
+    { changed? boolean } ;
+
+PREDICATE: change-tracking-tuple-class < tuple-class
+    change-tracking-tuple subclass-of? ;
+
+: changed? ( tuple -- changed? ) changed?>> ; inline
+: clear-changed ( tuple -- tuple ) f >>changed? ; inline
+
+: filter-changed ( sequence -- sequence' ) [ changed? ] filter ; inline
+
+<PRIVATE
+
+M: change-tracking-tuple-class writer-quot ( class slot-spec -- )
+    [ call-next-method ]
+    [ name>> "changed?" = [ '[ _ [ t >>changed? drop ] bi ] ] unless ] bi ;
+
+PRIVATE>
+
diff --git a/extra/classes/tuple/change-tracking/summary.txt b/extra/classes/tuple/change-tracking/summary.txt
new file mode 100644 (file)
index 0000000..3545c4b
--- /dev/null
@@ -0,0 +1 @@
+Tuple classes that keep track of when they've been modified
index f47eb7010c6dbbf0b4c16862f628d87edafcb065..6934d3bbd916f3dceb7d1a18ed1b2c71747b4d35 100644 (file)
@@ -10,7 +10,7 @@ MACRO: 1if ( test then else -- ) '[ dup @ _ _ if ] ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: sort-largest-first ( seq -- seq ) [ [ length ] compare ] sort reverse ;
+: sort-largest-first ( seq -- seq ) [ length ] sort-with reverse ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
index 86aa215e2104227803381e5cb2d54c3a8426bc0a..cfd036e6258c4c812d65c21e5562a11bb403ddf0 100644 (file)
@@ -23,7 +23,7 @@ IN: fuel.xref
     dup dup >vocab-link where normalize-loc 4array ;
 
 : sort-xrefs ( seq -- seq' )
-    [ [ first ] dip first <=> ] sort ;
+    [ first ] sort-with ;
 
 : format-xrefs ( seq -- seq' )
     [ word? ] filter [ word>xref ] map ;
index f975b21245d5474206cca03600ee70728167a955..48f74df6cec0b401d28ea786189ebd8519301ad4 100755 (executable)
@@ -221,7 +221,7 @@ BEFORE: bunny-world begin-world
     bunny-uniforms boa ;
 
 : draw-bunny ( world -- )
-    T{ depth-state { comparison cmp-less } } set-gpu-state*
+    T{ depth-state { comparison cmp-less } } set-gpu-state
     
     [
         sobel>> framebuffer>> {
@@ -247,7 +247,7 @@ BEFORE: bunny-world begin-world
     sobel-uniforms boa ;
 
 : draw-sobel ( world -- )
-    T{ depth-state { comparison f } } set-gpu-state*
+    T{ depth-state { comparison f } } set-gpu-state
 
     sobel>> {
         { "primitive-mode" [ drop triangle-strip-mode ] }
@@ -260,7 +260,7 @@ BEFORE: bunny-world begin-world
     [ draw-bunny ] [ draw-sobel ] bi ;
 
 : draw-loading ( world -- )
-    T{ depth-state { comparison f } } set-gpu-state*
+    T{ depth-state { comparison f } } set-gpu-state
 
     loading>> {
         { "primitive-mode" [ drop triangle-strip-mode ] }
index 16d2e408f2955b271f1f2ab75db0b3ba11881443..7d21baf2d0f511864b7aec39cb2e2f0d97171058 100644 (file)
@@ -37,7 +37,7 @@ border_factor(vec2 texcoord)
 void
 main()
 {
-    gl_FragColor = /*vec4(border_factor(texcoord));*/ mix(
+    gl_FragColor = mix(
         texture2D(color_texture, texcoord),
         line_color,
         border_factor(texcoord)
index ce6e0e25fff40840a97f0601ce7740f62b5a72ca..2f920645ed5a2213a4b5092613138ede0077552c 100644 (file)
@@ -8,7 +8,7 @@ gpu.textures gpu.textures.private half-floats images kernel
 lexer locals math math.order math.parser namespaces opengl
 opengl.gl parser quotations sequences slots sorting
 specialized-arrays.alien specialized-arrays.float specialized-arrays.int
-specialized-arrays.uint strings tr ui.gadgets.worlds variants
+specialized-arrays.uint strings ui.gadgets.worlds variants
 vocabs.parser words ;
 IN: gpu.render
 
@@ -73,7 +73,7 @@ TUPLE: multi-index-range
 C: <multi-index-range> multi-index-range
 
 TUPLE: index-elements
-    { ptr gpu-data-ptr read-only }
+    { ptr read-only }
     { count integer read-only }
     { index-type index-type read-only } ;
 
@@ -338,8 +338,6 @@ DEFER: [bind-uniform-tuple]
     texture-unit' 
     value>>-quot { value-cleave 2cleave } append ;
 
-TR: hyphens>underscores "-" "_" ;
-
 :: [bind-uniform] ( texture-unit uniform prefix -- texture-unit' quot )
     prefix uniform name>> append hyphens>underscores :> name
     uniform uniform-type>> :> type
@@ -424,7 +422,7 @@ SYNTAX: UNIFORM-TUPLE:
     [ [ length ] [ >int-array ] bi glDrawBuffers ] if ;
 
 : bind-named-output-attachments ( program-instance framebuffer attachments -- )
-    rot '[ [ first _ swap output-index ] bi@ <=> ] sort [ second ] map
+    rot '[ first _ swap output-index ] sort-with [ second ] map
     bind-unnamed-output-attachments ;
 
 : bind-output-attachments ( program-instance framebuffer attachments -- )
index d2dd29595aaf938f3076b912601600960c52a284..58633d4a7171f95aa1270c88ce0334a10bcc5c8a 100755 (executable)
@@ -8,7 +8,7 @@ io.encodings.ascii io.files io.pathnames kernel lexer literals
 locals math math.parser memoize multiline namespaces opengl
 opengl.gl opengl.shaders parser quotations sequences
 specialized-arrays.alien specialized-arrays.int splitting
-strings ui.gadgets.worlds variants vectors vocabs vocabs.loader
+strings tr ui.gadgets.worlds variants vectors vocabs vocabs.loader
 vocabs.parser words words.constant ;
 IN: gpu.shaders
 
@@ -65,6 +65,8 @@ MEMO: output-index ( program-instance output-name -- index )
 
 <PRIVATE
 
+TR: hyphens>underscores "-" "_" ;
+
 : gl-vertex-type ( component-type -- gl-type )
     {
         { ubyte-components          [ GL_UNSIGNED_BYTE  ] }
@@ -125,12 +127,12 @@ MEMO: output-index ( program-instance output-name -- index )
     } 0&& [ vertex-attribute inaccurate-feedback-attribute-error ] unless ;
 
 :: [bind-vertex-attribute] ( stride offset vertex-attribute -- stride offset' quot )
-    vertex-attribute name>>                 :> name
-    vertex-attribute component-type>>       :> type
-    type gl-vertex-type                     :> gl-type
-    vertex-attribute dim>>                  :> dim
-    vertex-attribute normalize?>> >c-bool   :> normalize?
-    vertex-attribute vertex-attribute-size  :> size
+    vertex-attribute name>> hyphens>underscores :> name
+    vertex-attribute component-type>>           :> type
+    type gl-vertex-type                         :> gl-type
+    vertex-attribute dim>>                      :> dim
+    vertex-attribute normalize?>> >c-bool       :> normalize?
+    vertex-attribute vertex-attribute-size      :> size
 
     stride offset size +
     {
index 8f3bb361a5aaa0cacf114dd3b7f47e8887ff7384..6a14a5728baa518ddd1601b0877331eed2ea134d 100644 (file)
@@ -1,5 +1,5 @@
 ! (c)2009 Joe Groff bsd license
-USING: byte-arrays classes gpu.buffers help.markup help.syntax
+USING: alien byte-arrays classes gpu.buffers help.markup help.syntax
 images kernel math ;
 IN: gpu.textures
 
@@ -228,7 +228,11 @@ HELP: texture-cube-map
 { texture-cube-map <texture-cube-map> } related-words
 
 HELP: texture-data
-{ $class-description { $snippet "texture-data" } " tuples are used to feed image data to " { $link allocate-texture } " and " { $link update-texture } ". In addition to providing a " { $snippet "ptr" } " to CPU memory or a GPU " { $link buffer-ptr } ", the " { $link texture-data } " object also specifies the " { $link component-order } " and " { $link component-type } " of the referenced data." }
+{ $class-description { $snippet "texture-data" } " tuples are used to feed image data to " { $link allocate-texture } " and " { $link update-texture } "."
+{ $list
+{ "The " { $snippet "ptr" } " slot references either CPU memory (as a " { $link byte-array } " or " { $link alien } ") or a GPU " { $link buffer-ptr } " that contains the image data." }
+{ "The " { $snippet "component-order" } " and " { $snippet "component-type" } " slots determine the " { $link component-order } " and " { $link component-type } " of the referenced data." }
+} }
 { $notes "Using a " { $link buffer-ptr } " as the " { $snippet "ptr" } " of a " { $snippet "texture-data" } " object requires OpenGL 2.1 or later or the " { $snippet "GL_ARB_pixel_buffer_object" } " extension." } ;
 
 { texture-data <texture-data> } related-words
@@ -254,15 +258,15 @@ HELP: texture-filter
 { $class-description { $snippet "texture-filter" } " values are used in a " { $link texture-parameters } " tuple to determine how a texture should be sampled between pixels or between levels of detail. " { $link filter-linear } " selects linear filtering, while " { $link filter-nearest } " selects nearest-neighbor sampling." } ;
 
 HELP: texture-parameters
-{ $class-description "When a " { $link texture } " is created, the following " { $snippet "texture-parameter" } "s are set to control how the texture is sampled:"
+{ $class-description "A " { $snippet "texture-parameters" } " tuple is supplied when constructing a " { $link texture } " to control the wrapping, filtering, and level-of-detail handling of the texture. These tuples have the following slots:"
 { $list
 { "The " { $snippet "wrap" } " slot determines how texture coordinates outside the 0.0 to 1.0 range are mapped to the texture image. The slot either contains a single " { $link texture-wrap } " value, which will apply to all three axes, or a sequence of up to three values, which will apply to the S, T, and R axes, respectively." }
-{ "The " { $snippet "min-filter" } " and " { $snippet "min-mipmap-filter" } " determine how the texture image is filtered when sampled below its highest level of detail, the former controlling filtering between pixels within a level of detail and the latter filtering between levels of detail. A setting of " { $link filter-linear } " uses linear, bilinear, or trilinear filtering among sampled pixels, while a setting of " { $link filter-nearest } " uses nearest-neighbor sampling. The " { $snippet "min-mipmap-filter" } " slot may additionally be set to " { $link f } " to disable mipmapping and only sample the highest level of detail." }
+{ "The " { $snippet "min-filter" } " and " { $snippet "min-mipmap-filter" } " determine how the texture image is filtered when sampled below its highest level of detail, the former filtering between pixels within a level of detail and the latter filtering between levels of detail. A setting of " { $link filter-linear } " uses linear, bilinear, or trilinear filtering among the sampled pixels, while a setting of " { $link filter-nearest } " uses nearest-neighbor sampling. The " { $snippet "min-mipmap-filter" } " slot may additionally be set to " { $link f } " to disable mipmapping and only sample the highest level of detail." }
 { "The " { $snippet "mag-filter" } " analogously determines how the texture image is filtered when sampled above its highest level of detail." }
 { "The " { $snippet "min-lod" } " and " { $snippet "max-lod" } " slots contain integer values that will clamp the range of levels of detail that will be sampled from the texture." }
 { "The " { $snippet "lod-bias" } " slot contains an integer value that will offset the levels of detail that would normally be sampled from the texture." }
 { "The " { $snippet "base-level" } " slot contains an integer value that identifies the highest level of detail for the image, typically zero." }
-{ "The " { $snippet "max-level" } " slot contains an integer value that identifies the lowest level of detail for the image. This value will automatically be clamped to the maximum of the base-2 logarithm of the dimensions of the highest level of detail image." }
+{ "The " { $snippet "max-level" } " slot contains an integer value that identifies the lowest level of detail for the image. This value will automatically be clamped to the maximum of the base-2 logarithms of the dimensions of the highest level of detail image." }
 } } ;
 
 { texture-parameters set-texture-parameters } related-words
index c84f3a21238164dde206f86694bd7a6c90c20774..a2e6ffd44010854c6dc832c2f1f265fa16241403 100644 (file)
@@ -26,14 +26,14 @@ TUPLE: cube-map-face
     { axis cube-map-axis read-only } ;
 C: <cube-map-face> cube-map-face
 
-UNION: texture-data-target
-    texture-1d texture-2d texture-3d cube-map-face ;
 UNION: texture-1d-data-target
     texture-1d ;
 UNION: texture-2d-data-target
     texture-2d texture-rectangle texture-1d-array cube-map-face ;
 UNION: texture-3d-data-target
     texture-3d texture-2d-array ;
+UNION: texture-data-target
+    texture-1d-data-target texture-2d-data-target texture-3d-data-target ;
 
 M: texture dispose
     [ [ delete-texture ] when* f ] change-handle drop ;
index 1b4a4550dc5503547de2f9eed6434b483639e577..b065dfe2f0b22168193b7f6014c50b90e0805853 100644 (file)
@@ -75,8 +75,9 @@ M: to-many-chats message-forwards sender>> participant-chats ;
 GENERIC: process-message ( irc-message -- )
 M: object process-message drop ;
 M: ping   process-message trailing>> /PONG ;
-M: join   process-message [ sender>> ] [ chat> ] bi join-participant ;
-M: part   process-message [ sender>> ] [ chat> ] bi part-participant ;
+! FIXME: it shouldn't be checking for the presence of chat here...
+M: join   process-message [ sender>> ] [ chat> ] bi [ join-participant ] [ drop ] if* ;
+M: part   process-message [ sender>> ] [ chat> ] bi [ part-participant ] [ drop ] if* ;
 M: quit   process-message sender>> quit-participant ;
 M: nick   process-message [ trailing>> ] [ sender>> ] bi rename-participant* ;
 M: rpl-nickname-in-use process-message name>> "_" append /NICK ;
index ff8085a9a9c5dc99a1191916056c346c3c0cf8cb..976a3832f47fdbe0b210bafe651e1c345357f8e1 100644 (file)
@@ -21,15 +21,17 @@ SYMBOL: current-stream
 : timestamp-path ( timestamp -- path )
     timestamp>ymd ".log" append log-directory prepend-path ;
 
+: update-current-stream ( timestamp -- )
+    current-stream get [ dispose ] when*
+    [ day-of-year current-day set ]
+    [ timestamp-path latin1 <file-appender> ] bi
+    current-stream set ;
+
+: same-day? ( timestamp -- ? ) day-of-year current-day get = ;
+
 : timestamp>stream ( timestamp  -- stream )
-    dup day-of-year current-day get = [
-        drop
-    ] [
-        current-stream get [ dispose ] when*
-        [ day-of-year current-day set ]
-        [ timestamp-path latin1 <file-appender> ] bi
-        current-stream set
-    ] if current-stream get ;
+    dup same-day? [ drop ] [ update-current-stream ] if
+    current-stream get ;
 
 : log-message ( string timestamp -- )
     [ add-timestamp ] [ timestamp>stream ] bi
index d44d5bce78e6974bc94cbca66e3a6d18baab9143..131f9f5465107c2b597850589203143e1bed36cd 100644 (file)
@@ -21,7 +21,7 @@ ERROR: no-pair-method a b generic ;
 
 : sorted-pair-methods ( word -- alist )
     "pair-generic-methods" word-prop >alist
-    [ [ first method-sort-key ] bi@ >=< ] sort ;
+    [ first method-sort-key ] inv-sort-with ;
 
 : pair-generic-definition ( word -- def )
     [ sorted-pair-methods [ first2 pair-method-cond ] map ]
index 259fb9f259a10acd306774787839d7b793d315a1..af13e5b86e757c481693c419e827babeb9caf8ed 100644 (file)
@@ -77,47 +77,6 @@ IN: sequence-parser.tests
 [ "cd" ]
 [ "abcd" <sequence-parser> [ "ab" take-sequence drop ] [ "cd" take-sequence ] bi ] unit-test
 
-[ f ]
-[
-    "\"abc\" asdf" <sequence-parser>
-    [ CHAR: \ CHAR: " take-quoted-string drop ] [ "asdf" take-sequence ] bi
-] unit-test
-
-[ "abc\\\"def" ]
-[
-    "\"abc\\\"def\" asdf" <sequence-parser>
-    CHAR: \ CHAR: " take-quoted-string
-] unit-test
-
-[ "asdf" ]
-[
-    "\"abc\" asdf" <sequence-parser>
-    [ CHAR: \ CHAR: " take-quoted-string drop ]
-    [ skip-whitespace "asdf" take-sequence ] bi
-] unit-test
-
-[ f ]
-[
-    "\"abc asdf" <sequence-parser>
-    CHAR: \ CHAR: " take-quoted-string
-] unit-test
-
-[ "\"abc" ]
-[
-    "\"abc asdf" <sequence-parser>
-    [ CHAR: \ CHAR: " take-quoted-string drop ]
-    [ "\"abc" take-sequence ] bi
-] unit-test
-
-[ "c" ]
-[ "c" <sequence-parser> take-token ] unit-test
-
-[ f ]
-[ "" <sequence-parser> take-token ] unit-test
-
-[ "abcd e \\\"f g" ]
-[ "\"abcd e \\\"f g\"" <sequence-parser> CHAR: \ CHAR: " take-token* ] unit-test
-
 [ f ]
 [ "" <sequence-parser> take-rest ] unit-test
 
@@ -140,63 +99,6 @@ IN: sequence-parser.tests
 [ "abcd" ] [ "abcd" <sequence-parser> 4 take-n ] unit-test
 [ "abcd" "efg" ] [ "abcdefg" <sequence-parser> [ 4 take-n ] [ take-rest ] bi ] unit-test
 
-[ "asdfasdf" ] [
-    "/*asdfasdf*/" <sequence-parser> take-c-comment 
-] unit-test
-
-[ "k" ] [
-    "/*asdfasdf*/k" <sequence-parser> [ take-c-comment drop ] [ take-rest ] bi
-] unit-test
-
-[ "omg" ] [
-    "//asdfasdf\nomg" <sequence-parser>
-    [ take-c++-comment drop ] [ take-rest ] bi
-] unit-test
-
-[ "omg" ] [
-    "omg" <sequence-parser>
-    [ take-c++-comment drop ] [ take-rest ] bi
-] unit-test
-
-[ "/*asdfasdf" ] [
-    "/*asdfasdf" <sequence-parser> [ take-c-comment drop ] [ take-rest ] bi
-] unit-test
-
-[ "asdf" "eoieoei" ] [
-    "//asdf\neoieoei" <sequence-parser>
-    [ take-c++-comment ] [ take-rest ] bi
-] unit-test
-
-[ f "33asdf" ]
-[ "33asdf" <sequence-parser> [ take-c-identifier ] [ take-rest ] bi ] unit-test
-
-[ "asdf" ]
-[ "asdf" <sequence-parser> take-c-identifier ] unit-test
-
-[ "_asdf" ]
-[ "_asdf" <sequence-parser> take-c-identifier ] unit-test
-
-[ "_asdf400" ]
-[ "_asdf400" <sequence-parser> take-c-identifier ] unit-test
-
-[ "123" ]
-[ "123jjj" <sequence-parser> take-c-integer ] unit-test
-
-[ "123uLL" ]
-[ "123uLL" <sequence-parser> take-c-integer ] unit-test
-
-[ "123ull" ]
-[ "123ull" <sequence-parser> take-c-integer ] unit-test
-
-[ "123u" ]
-[ "123u" <sequence-parser> take-c-integer ] unit-test
-
-[ 36 ]
-[
-    "    //jofiejoe\n    //eoieow\n/*asdf*/\n      "
-    <sequence-parser> skip-whitespace/comments n>>
-] unit-test
-
 [ f ]
 [ "\n" <sequence-parser> take-integer ] unit-test
 
index e46abe809050a1ad73a3db05c3a81b22d351094e..0a6f3ef0db493b12fa646d01f4e58ca6a30c3e5e 100644 (file)
@@ -1,9 +1,8 @@
 ! Copyright (C) 2005, 2009 Daniel Ehrenberg, Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: namespaces math kernel sequences accessors fry circular
-unicode.case unicode.categories locals combinators.short-circuit
-make combinators io splitting math.parser math.ranges
-generalizations sorting.functor math.order sorting.slots ;
+USING: accessors circular combinators.short-circuit fry io
+kernel locals math math.order sequences sorting.functor
+sorting.slots unicode.categories ;
 IN: sequence-parser
 
 TUPLE: sequence-parser sequence n ;
@@ -109,42 +108,6 @@ TUPLE: sequence-parser sequence n ;
 : skip-whitespace-eol ( sequence-parser -- sequence-parser )
     [ [ current " \t\r" member? not ] take-until drop ] keep ;
 
-: take-c-comment ( sequence-parser -- seq/f )
-    [
-        dup "/*" take-sequence [
-            "*/" take-until-sequence*
-        ] [
-            drop f
-        ] if
-    ] with-sequence-parser ;
-
-: take-c++-comment ( sequence-parser -- seq/f )
-    [
-        dup "//" take-sequence [
-            [
-                [
-                    { [ current CHAR: \n = ] [ sequence-parse-end? ] } 1||
-                ] take-until
-            ] [
-                advance drop
-            ] bi
-        ] [
-            drop f
-        ] if
-    ] with-sequence-parser ;
-
-: skip-whitespace/comments ( sequence-parser -- sequence-parser )
-    skip-whitespace-eol
-    {
-        { [ dup take-c-comment ] [ skip-whitespace/comments ] }
-        { [ dup take-c++-comment ] [ skip-whitespace/comments ] }
-        [ ]
-    } cond ;
-
-: take-define-identifier ( sequence-parser -- string )
-    skip-whitespace/comments
-    [ current { [ blank? ] [ CHAR: ( = ] } 1|| ] take-until ;
-
 : take-rest-slice ( sequence-parser -- sequence/f )
     [ sequence>> ] [ n>> ] bi
     2dup [ length ] dip < [ 2drop f ] [ tail-slice ] if ; inline
@@ -158,35 +121,6 @@ TUPLE: sequence-parser sequence n ;
 : parse-sequence ( sequence quot -- )
     [ <sequence-parser> ] dip call ; inline
 
-:: take-quoted-string ( sequence-parser escape-char quote-char -- string )
-    sequence-parser n>> :> start-n
-    sequence-parser advance
-    [
-        {
-            [ { [ previous escape-char = ] [ current quote-char = ] } 1&& ]
-            [ current quote-char = not ]
-        } 1||
-    ] take-while :> string
-    sequence-parser current quote-char = [
-        sequence-parser advance* string
-    ] [
-        start-n sequence-parser (>>n) f
-    ] if ;
-
-: (take-token) ( sequence-parser -- string )
-    skip-whitespace [ current { [ blank? ] [ f = ] } 1|| ] take-until ;
-
-:: take-token* ( sequence-parser escape-char quote-char -- string/f )
-    sequence-parser skip-whitespace
-    dup current {
-        { quote-char [ escape-char quote-char take-quoted-string ] }
-        { f [ drop f ] }
-        [ drop (take-token) ]
-    } case ;
-
-: take-token ( sequence-parser -- string/f )
-    CHAR: \ CHAR: " take-token* ;
-
 : take-integer ( sequence-parser -- n/f )
     [ current digit? ] take-while ;
 
@@ -198,27 +132,6 @@ TUPLE: sequence-parser sequence n ;
         sequence-parser [ n + ] change-n drop
     ] if ;
 
-: c-identifier-begin? ( ch -- ? )
-    CHAR: a CHAR: z [a,b]
-    CHAR: A CHAR: Z [a,b]
-    { CHAR: _ } 3append member? ;
-
-: c-identifier-ch? ( ch -- ? )
-    CHAR: a CHAR: z [a,b]
-    CHAR: A CHAR: Z [a,b]
-    CHAR: 0 CHAR: 9 [a,b]
-    { CHAR: _ } 4 nappend member? ;
-
-: (take-c-identifier) ( sequence-parser -- string/f )
-    dup current c-identifier-begin? [
-        [ current c-identifier-ch? ] take-while
-    ] [
-        drop f
-    ] if ;
-
-: take-c-identifier ( sequence-parser -- string/f )
-    [ (take-c-identifier) ] with-sequence-parser ;
-
 << "length" [ length ] define-sorting >>
 
 : sort-tokens ( seq -- seq' )
@@ -228,34 +141,8 @@ TUPLE: sequence-parser sequence n ;
     swap
     '[ _ [ swap take-sequence ] with-sequence-parser ] find nip ;
 
-
 : take-longest ( sequence-parser seq -- seq )
     sort-tokens take-first-matching ;
 
-: take-c-integer ( sequence-parser -- string/f )
-    [
-        dup take-integer [
-            swap
-            { "ull" "uLL" "Ull" "ULL" "ll" "LL" "l" "L" "u" "U" }
-            take-longest [ append ] when*
-        ] [
-            drop f
-        ] if*
-    ] with-sequence-parser ;
-
-CONSTANT: c-punctuators
-    {
-        "[" "]" "(" ")" "{" "}" "." "->"
-        "++" "--" "&" "*" "+" "-" "~" "!"
-        "/" "%" "<<" ">>" "<" ">" "<=" ">=" "==" "!=" "^" "|" "&&" "||"
-        "?" ":" ";" "..."
-        "=" "*=" "/=" "%=" "+=" "-=" "<<=" ">>=" "&=" "^=" "|="
-        "," "#" "##"
-        "<:" ":>" "<%" "%>" "%:" "%:%:"
-    }
-
-: take-c-punctuator ( sequence-parser -- string/f )
-    c-punctuators take-longest ;
-
 : write-full ( sequence-parser -- ) sequence>> write ;
 : write-rest ( sequence-parser -- ) take-rest write ;
index c16450bb251e79083b3e46fbf2d70f7549e934ff..f098bb9f09d4c674aab312709c9612b82415cbe7 100644 (file)
@@ -83,7 +83,7 @@ M: comment entity-url
     >>comments ;
 
 : reverse-chronological-order ( seq -- sorted )
-    [ [ date>> ] compare invert-comparison ] sort ;
+    [ date>> ] inv-sort-with ;
 
 : validate-author ( -- )
     { { "author" [ v-username ] } } validate-params ;
index 6a52d02009df3b1b562b44d3dccfda232370f63e..2c51d41aa016de58e9e54480e7ab2b35d14698c9 100644 (file)
@@ -59,7 +59,7 @@ TUPLE: paste < entity annotations ;
 
 : pastes ( -- pastes )
     f <paste> select-tuples
-    [ [ date>> ] compare ] sort
+    [ date>> ] sort-with
     reverse ;
 
 TUPLE: annotation < entity parent ;
index 12b7ccda24827815952edcb45cdce948d377b9a8..eb51acbe1a698e3dcaf8ce9972f5b4a335437209 100755 (executable)
@@ -56,11 +56,11 @@ posting "POSTINGS"
 
 : blogroll ( -- seq )
     f <blog> select-tuples
-    [ [ name>> ] compare ] sort ;
+    [ name>> ] sort-with ;
 
 : postings ( -- seq )
     posting new select-tuples
-    [ [ date>> ] compare invert-comparison ] sort ;
+    [ date>> ] inv-sort-with ;
 
 : <edit-blogroll-action> ( -- action )
     <page-action>
@@ -99,7 +99,7 @@ posting "POSTINGS"
     [ '[ _ <posting> ] map ] 2map concat ;
 
 : sort-entries ( entries -- entries' )
-    [ [ date>> ] compare invert-comparison ] sort ;
+    [ date>> ] inv-sort-with ;
 
 : update-cached-postings ( -- )
     blogroll fetch-blogroll sort-entries 8 short head [
index 5689f23d4ea6cfd60f3e30e1ac2f5e8f574316c9..f3a3784465d254d80882184e872913fed901e8a3 100644 (file)
@@ -66,7 +66,7 @@ M: revision feed-entry-date date>> ;
 M: revision feed-entry-url id>> revision-url ;
 
 : reverse-chronological-order ( seq -- sorted )
-    [ [ date>> ] compare invert-comparison ] sort ;
+    [ date>> ] inv-sort-with ;
 
 : <revision> ( id -- revision )
     revision new swap >>id ;
@@ -307,7 +307,7 @@ M: revision feed-entry-url id>> revision-url ;
 
         [
             f <article> select-tuples
-            [ [ title>> ] compare ] sort
+            [ title>> ] sort-with
             "articles" set-value
         ] >>init
 
index a4559c5c5c3bfb504cdc09f26cbd6277f8500755..73d6781313909d150b3913b47046c56e199e5c15 100644 (file)
     ("\\_<\\(}\\)\\_>" (1 "){"))
     ;; Parenthesis:
     ("\\_<\\((\\)\\_>" (1 "()"))
-    ("\\_<call\\((\\)\\_>" (1 "()"))
+    ("\\_<\\w*\\((\\)\\_>" (1 "()"))
     ("\\_<\\()\\)\\_>" (1 ")("))
     ("\\_<(\\((\\)\\_>" (1 "()"))
     ("\\_<\\()\\))\\_>" (1 ")("))
index 22e92809a7b033d9287c714a53b24784059f6dc5..5f78afb9db0c20435c8bbe3b0eee4d2d5e992d74 100755 (executable)
@@ -173,10 +173,15 @@ void print_stack_frame(stack_frame *frame)
        print_string("\n");
        print_obj(frame_scan(frame));
        print_string("\n");
+       print_string("word/quot addr: ");
        print_cell_hex((cell)frame_executing(frame));
-       print_string(" ");
+       print_string("\n");
+       print_string("word/quot xt: ");
        print_cell_hex((cell)frame->xt);
        print_string("\n");
+       print_string("return address: ");
+       print_cell_hex((cell)FRAME_RETURN_ADDRESS(frame));
+       print_string("\n");
 }
 
 void print_callstack()
index f8aa07ded9e6e6c87c70b16bf72aa3c0a629f5b0..de9de1acf1cb23d6b599ba45317539b77c3067c2 100755 (executable)
@@ -53,10 +53,8 @@ cell code_relocation_base;
 
 static void load_code_heap(FILE *file, image_header *h, vm_parameters *p)
 {
-       cell good_size = h->code_size + (1 << 19);
-
-       if(good_size > p->code_size)
-               p->code_size = good_size;
+       if(h->code_size > p->code_size)
+               fatal_error("Code heap too small to fit image",h->code_size);
 
        init_code_heap(p->code_size);