]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge branch 'llvm' of git://github.com/yuuki/factor
authorSlava Pestov <slava@shill.local>
Thu, 9 Jul 2009 11:21:44 +0000 (06:21 -0500)
committerSlava Pestov <slava@shill.local>
Thu, 9 Jul 2009 11:21:44 +0000 (06:21 -0500)
123 files changed:
basis/alien/inline/authors.txt [new file with mode: 0644]
basis/alien/inline/compiler/authors.txt [new file with mode: 0644]
basis/alien/inline/compiler/compiler.factor [new file with mode: 0644]
basis/alien/inline/inline.factor [new file with mode: 0644]
basis/alien/inline/tests/tests.factor [new file with mode: 0644]
basis/alien/inline/types/authors.txt [new file with mode: 0644]
basis/alien/inline/types/types.factor [new file with mode: 0644]
basis/alien/structs/structs-docs.factor
basis/bit-sets/authors.txt [new file with mode: 0644]
basis/bit-sets/bit-sets-tests.factor [new file with mode: 0644]
basis/bit-sets/bit-sets.factor [new file with mode: 0644]
basis/bit-sets/summary.txt [new file with mode: 0644]
basis/compiler/cfg/branch-folding/branch-folding-tests.factor [new file with mode: 0644]
basis/compiler/cfg/branch-folding/branch-folding.factor [new file with mode: 0644]
basis/compiler/cfg/branch-splitting/branch-splitting.factor
basis/compiler/cfg/builder/builder-tests.factor
basis/compiler/cfg/builder/builder.factor
basis/compiler/cfg/cfg-tests.factor [new file with mode: 0644]
basis/compiler/cfg/cfg.factor
basis/compiler/cfg/checker/checker.factor
basis/compiler/cfg/dce/authors.txt
basis/compiler/cfg/dce/dce-tests.factor [new file with mode: 0644]
basis/compiler/cfg/dce/dce.factor
basis/compiler/cfg/dce/summary.txt [new file with mode: 0644]
basis/compiler/cfg/def-use/def-use.factor
basis/compiler/cfg/gc-checks/gc-checks.factor
basis/compiler/cfg/instructions/instructions.factor
basis/compiler/cfg/intrinsics/fixnum/fixnum.factor
basis/compiler/cfg/intrinsics/intrinsics.factor
basis/compiler/cfg/iterator/iterator.factor [deleted file]
basis/compiler/cfg/iterator/summary.txt [deleted file]
basis/compiler/cfg/linear-scan/allocation/allocation.factor
basis/compiler/cfg/linear-scan/allocation/coalescing/coalescing.factor
basis/compiler/cfg/linear-scan/allocation/spilling/spilling.factor
basis/compiler/cfg/linear-scan/allocation/splitting/splitting.factor
basis/compiler/cfg/linear-scan/allocation/state/state.factor
basis/compiler/cfg/linear-scan/assignment/assignment.factor
basis/compiler/cfg/linear-scan/debugger/debugger.factor
basis/compiler/cfg/linear-scan/linear-scan-tests.factor
basis/compiler/cfg/linear-scan/linear-scan.factor
basis/compiler/cfg/linear-scan/live-intervals/live-intervals.factor
basis/compiler/cfg/linear-scan/numbering/numbering.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 [new file with mode: 0644]
basis/compiler/cfg/liveness/liveness.factor
basis/compiler/cfg/optimizer/optimizer-tests.factor
basis/compiler/cfg/optimizer/optimizer.factor
basis/compiler/cfg/phi-elimination/phi-elimination-tests.factor [new file with mode: 0644]
basis/compiler/cfg/phi-elimination/phi-elimination.factor
basis/compiler/cfg/predecessors/predecessors.factor
basis/compiler/cfg/stack-analysis/merge/merge-tests.factor
basis/compiler/cfg/stack-analysis/merge/merge.factor
basis/compiler/cfg/stack-analysis/stack-analysis-tests.factor
basis/compiler/cfg/stack-analysis/stack-analysis.factor
basis/compiler/cfg/stack-frame/stack-frame.factor
basis/compiler/cfg/tco/tco.factor [new file with mode: 0644]
basis/compiler/cfg/useless-blocks/summary.txt [deleted file]
basis/compiler/cfg/useless-blocks/useless-blocks-tests.factor [deleted file]
basis/compiler/cfg/useless-blocks/useless-blocks.factor [deleted file]
basis/compiler/cfg/useless-conditionals/summary.txt [new file with mode: 0644]
basis/compiler/cfg/useless-conditionals/useless-conditionals.factor [new file with mode: 0644]
basis/compiler/cfg/utilities/utilities.factor
basis/compiler/cfg/value-numbering/graph/graph.factor
basis/compiler/cfg/value-numbering/rewrite/rewrite.factor [changed mode: 0644->0755]
basis/compiler/cfg/value-numbering/simplify/simplify.factor
basis/compiler/codegen/codegen.factor
basis/compiler/tests/codegen.factor
basis/compiler/tests/intrinsics.factor
basis/compiler/tree/cleanup/cleanup-tests.factor
basis/compiler/tree/dead-code/simple/simple.factor
basis/compiler/tree/optimizer/optimizer.factor
basis/cpu/x86/32/32.factor
basis/editors/editors.factor
basis/help/apropos/apropos.factor
basis/help/html/html.factor
basis/help/lint/lint.factor
basis/help/vocabs/vocabs.factor
basis/http/client/client.factor
basis/http/client/debugger/debugger.factor
basis/http/http-docs.factor
basis/http/http.factor
basis/images/images.factor
basis/math/matrices/matrices.factor
basis/math/vectors/vectors-tests.factor
basis/opengl/opengl.factor
basis/present/present-tests.factor
basis/specialized-arrays/alien/alien.factor
basis/stuff.factor [new file with mode: 0644]
basis/threads/threads.factor
basis/tools/annotations/annotations-tests.factor
basis/tools/annotations/annotations.factor
basis/tools/completion/completion.factor
basis/ui/backend/backend.factor
basis/ui/gadgets/panes/panes.factor
basis/ui/gadgets/tables/tables.factor
basis/ui/gadgets/worlds/worlds-docs.factor
basis/ui/gadgets/worlds/worlds.factor
basis/ui/tools/listener/completion/completion.factor
basis/ui/tools/listener/history/history-tests.factor
basis/ui/tools/listener/history/history.factor
basis/ui/tools/tools.factor
basis/ui/ui.factor
basis/unicode/breaks/breaks-docs.factor
basis/unicode/breaks/breaks-tests.factor
basis/unicode/breaks/breaks.factor
basis/vocabs/cache/cache.factor
basis/vocabs/hierarchy/hierarchy-docs.factor
basis/vocabs/hierarchy/hierarchy.factor
basis/wrap/strings/strings-tests.factor
basis/wrap/wrap-tests.factor [new file with mode: 0644]
basis/wrap/wrap.factor
extra/benchmark/benchmark.factor
extra/benchmark/hashtables/authors.txt [new file with mode: 0644]
extra/benchmark/hashtables/hashtables.factor [new file with mode: 0644]
extra/fuel/help/help.factor
extra/fuel/xref/xref.factor
extra/half-floats/half-floats-tests.factor
extra/ui/gadgets/worlds/null/null.factor
extra/variants/variants-docs.factor
extra/webkit-demo/webkit-demo.factor
misc/factor.vim.fgen

diff --git a/basis/alien/inline/authors.txt b/basis/alien/inline/authors.txt
new file mode 100644 (file)
index 0000000..845910d
--- /dev/null
@@ -0,0 +1 @@
+Jeremy Hughes
diff --git a/basis/alien/inline/compiler/authors.txt b/basis/alien/inline/compiler/authors.txt
new file mode 100644 (file)
index 0000000..845910d
--- /dev/null
@@ -0,0 +1 @@
+Jeremy Hughes
diff --git a/basis/alien/inline/compiler/compiler.factor b/basis/alien/inline/compiler/compiler.factor
new file mode 100644 (file)
index 0000000..b5a7861
--- /dev/null
@@ -0,0 +1,53 @@
+! Copyright (C) 2009 Jeremy Hughes.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors arrays combinators fry generalizations
+io.encodings.ascii io.files io.files.temp io.launcher kernel
+locals sequences system ;
+IN: alien.inline.compiler
+
+SYMBOL: C
+SYMBOL: C++
+
+: library-suffix ( -- str )
+    os {
+        { [ dup macosx? ]  [ drop ".dylib" ] }
+        { [ dup unix? ]    [ drop ".so" ] }
+        { [ dup windows? ] [ drop ".dll" ] }
+    } cond ;
+
+: src-suffix ( lang -- str )
+    {
+        { C [ ".c" ] }
+        { C++ [ ".cpp" ] }
+    } case ;
+
+: compiler ( lang -- str )
+    {
+        { C [ "gcc" ] }
+        { C++ [ "g++" ] }
+    } case ;
+
+: link-command ( in out lang -- descr )
+    compiler os {
+        { [ dup linux? ]
+          [ drop { "-shared" "-o" } ] }
+        { [ dup macosx? ]
+          [ drop { "-g" "-prebind" "-dynamiclib" "-o" } ] }
+        [ name>> "unimplemented for: " prepend throw ]
+    } cond swap prefix prepend prepend ;
+
+:: compile-to-object ( lang contents name -- )
+    name ".o" append temp-file
+    contents name lang src-suffix append temp-file
+    [ ascii set-file-contents ] keep 2array
+    { "-fPIC" "-c" "-o" } lang compiler prefix prepend
+    try-process ;
+
+:: link-object ( lang args name -- )
+    args name [ "lib" prepend library-suffix append ]
+    [ ".o" append ] bi [ temp-file ] bi@ 2array
+    lang link-command try-process ;
+
+:: compile-to-library ( lang args contents name -- )
+    lang contents name compile-to-object
+    lang args name link-object ;
diff --git a/basis/alien/inline/inline.factor b/basis/alien/inline/inline.factor
new file mode 100644 (file)
index 0000000..ae4a954
--- /dev/null
@@ -0,0 +1,107 @@
+! Copyright (C) 2009 Jeremy Hughes.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors alien.inline.compiler alien.inline.types
+alien.libraries alien.parser arrays assocs effects fry
+generalizations grouping io.files io.files.info io.files.temp
+kernel lexer math math.order math.ranges multiline namespaces
+sequences splitting strings system vocabs.loader
+vocabs.parser words ;
+IN: alien.inline
+
+<PRIVATE
+SYMBOL: c-library
+SYMBOL: library-is-c++
+SYMBOL: compiler-args
+SYMBOL: c-strings
+
+: function-types-effect ( -- function types effect )
+    scan scan swap ")" parse-tokens
+    [ "(" subseq? not ] filter swap parse-arglist ;
+
+: arg-list ( types -- params )
+    CHAR: a swap length CHAR: a + [a,b]
+    [ 1string ] map ;
+
+: factor-function ( function types effect -- word quot effect )
+    annotate-effect [ c-library get ] 3dip
+    [ [ factorize-type ] map ] dip
+    types-effect>params-return factorize-type -roll
+    concat make-function ;
+
+: prototype-string ( function types effect -- str )
+    [ [ cify-type ] map ] dip
+    types-effect>params-return cify-type -rot
+    [ " " join ] map ", " join
+    "(" prepend ")" append 3array " " join
+    library-is-c++ get [ "extern \"C\" " prepend ] when ;
+
+: prototype-string' ( function types return -- str )
+    [ dup arg-list ] <effect> prototype-string ;
+
+: append-function-body ( prototype-str -- str )
+    " {\n" append parse-here append "\n}\n" append ;
+
+
+: library-path ( -- str )
+    "lib" c-library get library-suffix
+    3array concat temp-file ;
+
+: compile-library? ( -- ? )
+    library-path dup exists? [
+        current-vocab vocab-source-path
+        [ file-info modified>> ] bi@ <=> +lt+ =
+    ] [ drop t ] if ;
+
+: compile-library ( -- )
+    library-is-c++ get [ C++ ] [ C ] if
+    compiler-args get
+    c-strings get "\n" join
+    c-library get compile-to-library ;
+PRIVATE>
+
+: define-c-library ( name -- )
+    c-library set
+    V{ } clone c-strings set
+    V{ } clone compiler-args set ;
+
+: compile-c-library ( -- )
+    compile-library? [ compile-library ] when
+    c-library get library-path "cdecl" add-library ;
+
+: define-c-function ( function types effect -- )
+    [ factor-function define-declared ] 3keep prototype-string
+    append-function-body c-strings get push ;
+
+: define-c-function' ( function effect -- )
+    [ in>> ] keep [ factor-function define-declared ] 3keep
+    out>> prototype-string'
+    append-function-body c-strings get push ;
+
+: define-c-link ( str -- )
+    "-l" prepend compiler-args get push ;
+
+: define-c-framework ( str -- )
+    "-framework" swap compiler-args get '[ _ push ] bi@ ;
+
+: define-c-link/framework ( str -- )
+    os macosx? [ define-c-framework ] [ define-c-link ] if ;
+
+: define-c-include ( str -- )
+    "#include " prepend c-strings get push ;
+
+SYNTAX: C-LIBRARY: scan define-c-library ;
+
+SYNTAX: COMPILE-AS-C++ t library-is-c++ set ;
+
+SYNTAX: C-LINK: scan define-c-link ;
+
+SYNTAX: C-FRAMEWORK: scan define-c-framework ;
+
+SYNTAX: C-LINK/FRAMEWORK: scan define-c-link/framework ;
+
+SYNTAX: C-INCLUDE: scan define-c-include ;
+
+SYNTAX: C-FUNCTION:
+    function-types-effect define-c-function ;
+
+SYNTAX: ;C-LIBRARY compile-c-library ;
diff --git a/basis/alien/inline/tests/tests.factor b/basis/alien/inline/tests/tests.factor
new file mode 100644 (file)
index 0000000..acd2d61
--- /dev/null
@@ -0,0 +1,48 @@
+! Copyright (C) 2009 Jeremy Hughes.
+! See http://factorcode.org/license.txt for BSD license.
+USING: tools.test alien.inline alien.inline.private io.files
+io.directories kernel ;
+IN: alien.inline.tests
+
+C-LIBRARY: const
+
+C-FUNCTION: const-int add ( int a, int b )
+    return a + b;
+;
+
+;C-LIBRARY
+
+{ 2 1 } [ add ] must-infer-as
+[ 5 ] [ 2 3 add ] unit-test
+
+<< library-path dup exists? [ delete-file ] [ drop ] if >>
+
+
+C-LIBRARY: cpplib
+
+COMPILE-AS-C++
+
+C-INCLUDE: <string>
+
+C-FUNCTION: const-char* hello ( )
+    std::string s("hello world");
+    return s.c_str();
+;
+
+;C-LIBRARY
+
+{ 0 1 } [ hello ] must-infer-as
+[ "hello world" ] [ hello ] unit-test
+
+<< library-path dup exists? [ delete-file ] [ drop ] if >>
+
+
+C-LIBRARY: compile-error
+
+C-FUNCTION: char* breakme ( )
+    return not a string;
+;
+
+<< [ compile-c-library ] must-fail >>
+
+<< library-path dup exists? [ delete-file ] [ drop ] if >>
diff --git a/basis/alien/inline/types/authors.txt b/basis/alien/inline/types/authors.txt
new file mode 100644 (file)
index 0000000..c45c6f3
--- /dev/null
@@ -0,0 +1 @@
+Jeremy Hughes
\ No newline at end of file
diff --git a/basis/alien/inline/types/types.factor b/basis/alien/inline/types/types.factor
new file mode 100644 (file)
index 0000000..acc62a8
--- /dev/null
@@ -0,0 +1,47 @@
+! Copyright (C) 2009 Jeremy Hughes.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors alien.c-types assocs combinators.short-circuit
+continuations effects fry kernel math memoize sequences
+splitting ;
+IN: alien.inline.types
+
+: factorize-type ( str -- str' )
+    "const-" ?head drop
+    "unsigned-" ?head [ "u" prepend ] when
+    "long-" ?head [ "long" prepend ] when ;
+
+: cify-type ( str -- str' )
+    { { CHAR: - CHAR: space } } substitute ;
+
+: const-type? ( str -- ? )
+    "const-" head? ;
+
+MEMO: resolved-primitives ( -- seq )
+    primitive-types [ resolve-typedef ] map ;
+
+: primitive-type? ( type -- ? )
+    [
+        factorize-type resolve-typedef [ resolved-primitives ] dip
+        '[ _ = ] any?
+    ] [ 2drop f ] recover ;
+
+: pointer? ( type -- ? )
+    [ "*" tail? ] [ "&" tail? ] bi or ;
+
+: type-sans-pointer ( type -- type' )
+    [ '[ _ = ] "*&" swap any? ] trim-tail ;
+
+: pointer-to-primitive? ( type -- ? )
+    { [ pointer? ] [ type-sans-pointer primitive-type? ] } 1&& ;
+
+: types-effect>params-return ( types effect -- params return )
+    [ in>> zip ]
+    [ nip out>> dup length 0 > [ first ] [ drop "void" ] if ]
+    2bi ;
+
+: annotate-effect ( types effect -- types effect' )
+    [ in>> ] [ out>> ] bi [
+        zip
+        [ over pointer-to-primitive? [ ">" prepend ] when ]
+        assoc-map unzip
+    ] dip <effect> ;
index 2f7a7eadc8a2917030e510fdba2349710a143be1..c74fe22dfdd63d234c498dbdba9c987fdac1a51a 100644 (file)
@@ -23,11 +23,11 @@ $nl
 }
 "C structure objects can be allocated by calling " { $link <c-object> } " or " { $link malloc-object } "."
 $nl
-"Arrays of C structures can be created by calling " { $link <c-array> } " or " { $link malloc-array } ". Elements can be read and written using words named " { $snippet { $emphasis "type" } "-nth" } " and " { $snippet "set-" { $emphasis "type" } "-nth" } "; these words are automatically generated by " { $link POSTPONE: C-STRUCT: } "." ;
+"Arrays of C structures can be created with the " { $vocab-link "struct-arrays" } " vocabulary." ;
 
 ARTICLE: "c-unions" "C unions"
 "A " { $snippet "union" } " in C defines a type large enough to hold its largest member. This is usually used to allocate a block of memory which can hold one of several types of values."
 { $subsection POSTPONE: C-UNION: }
 "C union objects can be allocated by calling " { $link <c-object> } " or " { $link malloc-object } "."
 $nl
-"Arrays of C unions can be created by calling " { $link <c-array> } " or " { $link malloc-array } ". Elements can be read and written using words named " { $snippet { $emphasis "type" } "-nth" } " and " { $snippet "set-" { $emphasis "type" } "-nth" } "; these words are automatically generated by " { $link POSTPONE: C-UNION: } "." ;
+"Arrays of C unions can be created with the " { $vocab-link "struct-arrays" } " vocabulary." ;
\ No newline at end of file
diff --git a/basis/bit-sets/authors.txt b/basis/bit-sets/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/basis/bit-sets/bit-sets-tests.factor b/basis/bit-sets/bit-sets-tests.factor
new file mode 100644 (file)
index 0000000..e77bb43
--- /dev/null
@@ -0,0 +1,17 @@
+IN: bit-sets.tests
+USING: bit-sets tools.test bit-arrays ;
+
+[ ?{ t f t f t f } ] [
+    ?{ t f f f t f }
+    ?{ f f t f t f } bit-set-union
+] unit-test
+
+[ ?{ f f f f t f } ] [
+    ?{ t f f f t f }
+    ?{ f f t f t f } bit-set-intersect
+] unit-test
+
+[ ?{ t f t f f f } ] [
+    ?{ t t t f f f }
+    ?{ f t f f t t } bit-set-diff
+] unit-test
diff --git a/basis/bit-sets/bit-sets.factor b/basis/bit-sets/bit-sets.factor
new file mode 100644 (file)
index 0000000..0e97968
--- /dev/null
@@ -0,0 +1,29 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel accessors sequences byte-arrays bit-arrays math hints ;
+IN: bit-sets
+
+<PRIVATE
+
+: bit-set-map ( seq1 seq2 quot -- seq )
+    [ 2drop length>> ]
+    [
+        [
+            [ [ length ] bi@ assert= ]
+            [ [ underlying>> ] bi@ ] 2bi
+        ] dip 2map
+    ] 3bi bit-array boa ; inline
+
+PRIVATE>
+
+: bit-set-union ( seq1 seq2 -- seq ) [ bitor ] bit-set-map ;
+
+HINTS: bit-set-union bit-array bit-array ;
+
+: bit-set-intersect ( seq1 seq2 -- seq ) [ bitand ] bit-set-map ;
+
+HINTS: bit-set-intersect bit-array bit-array ;
+
+: bit-set-diff ( seq1 seq2 -- seq ) [ bitnot bitand ] bit-set-map ;
+
+HINTS: bit-set-diff bit-array bit-array ;
\ No newline at end of file
diff --git a/basis/bit-sets/summary.txt b/basis/bit-sets/summary.txt
new file mode 100644 (file)
index 0000000..d27503b
--- /dev/null
@@ -0,0 +1 @@
+Efficient bitwise operations on bit arrays
diff --git a/basis/compiler/cfg/branch-folding/branch-folding-tests.factor b/basis/compiler/cfg/branch-folding/branch-folding-tests.factor
new file mode 100644 (file)
index 0000000..964620d
--- /dev/null
@@ -0,0 +1,85 @@
+IN: compiler.cfg.branch-folding.tests
+USING: compiler.cfg.branch-folding compiler.cfg.instructions
+compiler.cfg compiler.cfg.registers compiler.cfg.debugger
+arrays compiler.cfg.phi-elimination compiler.cfg.dce
+compiler.cfg.predecessors kernel accessors assocs
+sequences classes namespaces tools.test cpu.architecture ;
+
+V{ T{ ##branch } } 0 test-bb
+
+V{
+    T{ ##peek f V int-regs 0 D 0 }
+    T{ ##compare-branch f V int-regs 0 V int-regs 0 cc< }
+} 1 test-bb
+
+V{
+    T{ ##load-immediate f V int-regs 1 1 }
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##load-immediate f V int-regs 2 2 }
+    T{ ##branch }
+} 3 test-bb
+
+V{
+    T{ ##phi f V int-regs 3 { } }
+    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
+
+[ ] [ cfg new 0 get >>entry fold-branches compute-predecessors eliminate-phis drop ] unit-test
+
+[ 1 ] [ 1 get successors>> length ] unit-test
+[ t ] [ 1 get successors>> first 3 get eq? ] unit-test
+
+[ T{ ##copy f V int-regs 3 V int-regs 2 } ] [ 3 get instructions>> second ] unit-test
+[ 2 ] [ 4 get instructions>> length ] unit-test
+
+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{ ##compare-branch f V int-regs 1 V int-regs 1 cc< }
+} 1 test-bb
+
+V{
+    T{ ##copy f V int-regs 2 V int-regs 0 }
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##phi f V int-regs 3 V{ } }
+    T{ ##branch }
+} 3 test-bb
+
+V{
+    T{ ##replace f V int-regs 3 D 0 }
+    T{ ##return }
+} 4 test-bb
+
+1 get V int-regs 1 2array
+2 get V int-regs 0 2array 2array 3 get instructions>> first (>>inputs)
+
+test-diamond
+
+[ ] [
+    cfg new 0 get >>entry
+    compute-predecessors
+    fold-branches
+    compute-predecessors
+    eliminate-dead-code
+    drop
+] unit-test
+
+[ 1 ] [ 3 get instructions>> first inputs>> assoc-size ] unit-test
\ No newline at end of file
diff --git a/basis/compiler/cfg/branch-folding/branch-folding.factor b/basis/compiler/cfg/branch-folding/branch-folding.factor
new file mode 100644 (file)
index 0000000..627db63
--- /dev/null
@@ -0,0 +1,30 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors combinators.short-circuit kernel sequences vectors
+compiler.cfg.instructions compiler.cfg.rpo ;
+IN: compiler.cfg.branch-folding
+
+! Fold comparisons where both inputs are the same. Predecessors must be
+! recomputed after this
+
+: fold-branch? ( bb -- ? )
+    instructions>> last {
+        [ ##compare-branch? ]
+        [ [ src1>> ] [ src2>> ] bi = ]
+    } 1&& ;
+
+: chosen-successor ( bb -- succ )
+    [ instructions>> last cc>> { cc= cc<= cc>= } memq? 0 1 ? ]
+    [ successors>> ]
+    bi nth ;
+
+: fold-branch ( bb -- )
+    dup chosen-successor 1vector >>successors
+    instructions>> [ pop* ] [ [ \ ##branch new-insn ] dip push ] bi ;
+
+: fold-branches ( cfg -- cfg' )
+    dup [
+        dup fold-branch?
+        [ fold-branch ] [ drop ] if
+    ] each-basic-block
+    f >>post-order ;
\ No newline at end of file
index 2b3d88191c2cd0d0d7dcb7ebc1df05f3edf06d1d..f7e9ea9cbff91b5674845ba21144f1434f033563 100644 (file)
@@ -1,24 +1,31 @@
-! Copyright (C) 2009 Doug Coleman.
+! Copyright (C) 2009 Doug Coleman, Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors combinators.short-circuit compiler.cfg.def-use
-compiler.cfg.rpo kernel math sequences ;
+USING: accessors combinators.short-circuit kernel math sequences
+compiler.cfg.def-use compiler.cfg compiler.cfg.rpo ;
 IN: compiler.cfg.branch-splitting
 
-: split-branch ( branch -- )
+! Predecessors must be recomputed after this
+
+: split-branch-for ( bb predecessor -- )
     [
-        [ instructions>> ] [ predecessors>> ] bi [
-            instructions>> [ pop* ] [ push-all ] bi
-        ] with each
-    ] [
-        [ successors>> ] [ predecessors>> ] bi [
-            [ drop clone ] change-successors drop
-        ] with each
-    ] bi ;
+        [
+            <basic-block>
+                swap
+                [ instructions>> [ clone ] map >>instructions ]
+                [ successors>> clone >>successors ]
+                bi
+        ] keep
+    ] dip
+    [ [ 2dup eq? [ 2drop ] [ 2nip ] if ] with with map ] change-successors
+    drop ;
+
+: split-branch ( bb -- )
+    dup predecessors>> [ split-branch-for ] with each ;
 
 : split-branches? ( bb -- ? )
     {
-        [ predecessors>> length 1 >= ]
-        [ successors>> length 1 <= ]
+        [ successors>> empty? ]
+        [ predecessors>> length 1 > ]
         [ instructions>> [ defs-vregs ] any? not ]
         [ instructions>> [ temp-vregs ] any? not ]
     } 1&& ;
@@ -26,4 +33,5 @@ IN: compiler.cfg.branch-splitting
 : split-branches ( cfg -- cfg' )
     dup [
         dup split-branches? [ split-branch ] [ drop ] if
-    ] each-basic-block f >>post-order ;
+    ] each-basic-block
+    f >>post-order ;
index 58eae8181b84e7c05e12ee57b6871096a95efa8a..4a481a09d81385ab390a39d6823b4ddc91b3e5f3 100644 (file)
@@ -18,10 +18,14 @@ kernel.private math ;
     [ 3 fixnum+fast ]
     [ fixnum*fast ]
     [ 3 fixnum*fast ]
+    [ 3 swap fixnum*fast ]
     [ fixnum-shift-fast ]
     [ 10 fixnum-shift-fast ]
     [ -10 fixnum-shift-fast ]
     [ 0 fixnum-shift-fast ]
+    [ 10 swap fixnum-shift-fast ]
+    [ -10 swap fixnum-shift-fast ]
+    [ 0 swap fixnum-shift-fast ]
     [ fixnum-bitnot ]
     [ eq? ]
     [ "hi" eq? ]
index d323263fc7342496c51667e26c3c1de56503408b..8cf141f3f4fd03942423d9b3f4494b4278822704 100755 (executable)
@@ -1,4 +1,4 @@
-! Copyright (C) 2004, 2008 Slava Pestov.
+! Copyright (C) 2004, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays assocs combinators hashtables kernel
 math fry namespaces make sequences words byte-arrays
@@ -11,7 +11,6 @@ compiler.tree.propagation.info
 compiler.cfg
 compiler.cfg.hats
 compiler.cfg.stacks
-compiler.cfg.iterator
 compiler.cfg.utilities
 compiler.cfg.registers
 compiler.cfg.intrinsics
@@ -26,10 +25,6 @@ SYMBOL: procedures
 SYMBOL: current-word
 SYMBOL: current-label
 SYMBOL: loops
-SYMBOL: first-basic-block
-
-! Basic block after prologue, makes recursion faster
-SYMBOL: current-label-start
 
 : add-procedure ( -- )
     basic-block get current-word get current-label get
@@ -46,27 +41,22 @@ SYMBOL: current-label-start
 : with-cfg-builder ( nodes word label quot -- )
     '[ begin-procedure @ ] with-scope ; inline
 
-GENERIC: emit-node ( node -- next )
+GENERIC: emit-node ( node -- )
 
 : check-basic-block ( node -- node' )
     basic-block get [ drop f ] unless ; inline
 
 : emit-nodes ( nodes -- )
-    [ current-node emit-node check-basic-block ] iterate-nodes ;
+    [ basic-block get [ emit-node ] [ drop ] if ] each ;
 
 : begin-word ( -- )
-    #! We store the basic block after the prologue as a loop
-    #! labeled by the current word, so that self-recursive
-    #! calls can skip an epilogue/prologue.
     ##prologue
     ##branch
-    begin-basic-block
-    basic-block get first-basic-block set ;
+    begin-basic-block ;
 
 : (build-cfg) ( nodes word label -- )
     [
         begin-word
-        V{ } clone node-stack set
         emit-nodes
     ] with-cfg-builder ;
 
@@ -77,37 +67,30 @@ GENERIC: emit-node ( node -- next )
         ] with-variable
     ] keep ;
 
-: local-recursive-call ( basic-block -- next )
+: emit-loop-call ( basic-block -- )
     ##branch
     basic-block get successors>> push
-    stop-iterating ;
+    basic-block off ;
 
-: emit-call ( word height -- next )
-    {
-        { [ over loops get key? ] [ drop loops get at local-recursive-call ] }
-        { [ terminate-call? ] [ ##call stop-iterating ] }
-        { [ tail-call? not ] [ ##call ##branch begin-basic-block iterate-next ] }
-        { [ dup current-label get eq? ] [ 2drop first-basic-block get local-recursive-call ] }
-        [ drop ##epilogue ##jump stop-iterating ]
-    } cond ;
+: emit-call ( word -- )
+    dup loops get key?
+    [ loops get at emit-loop-call ]
+    [ ##call ##branch begin-basic-block ]
+    if ;
 
 ! #recursive
-: recursive-height ( #recursive -- n )
-    [ label>> return>> in-d>> length ] [ in-d>> length ] bi - ;
-
-: emit-recursive ( #recursive -- next )
-    [ [ label>> id>> ] [ recursive-height ] bi emit-call ]
+: emit-recursive ( #recursive -- )
+    [ label>> id>> emit-call ]
     [ [ child>> ] [ label>> word>> ] [ label>> id>> ] tri (build-cfg) ] bi ;
 
 : remember-loop ( label -- )
     basic-block get swap loops get set-at ;
 
-: emit-loop ( node -- next )
+: emit-loop ( node -- )
     ##loop-entry
     ##branch
     begin-basic-block
-    [ label>> id>> remember-loop ] [ child>> emit-nodes ] bi
-    iterate-next ;
+    [ label>> id>> remember-loop ] [ child>> emit-nodes ] bi ;
 
 M: #recursive emit-node
     dup label>> loop?>> [ emit-loop ] [ emit-recursive ] if ;
@@ -121,7 +104,7 @@ M: #recursive emit-node
     ] with-scope ;
 
 : emit-if ( node -- )
-    children>>  [ emit-branch ] map
+    children>> [ emit-branch ] map
     end-basic-block
     begin-basic-block
     basic-block get '[ [ _ swap successors>> push ] when* ] each ;
@@ -157,23 +140,23 @@ M: #if emit-node
         { [ dup trivial-if? ] [ drop emit-trivial-if ] }
         { [ dup trivial-not-if? ] [ drop emit-trivial-not-if ] }
         [ ds-pop ##branch-t emit-if ]
-    } cond iterate-next ;
+    } cond ;
 
 ! #dispatch
 M: #dispatch emit-node
-    ds-pop ^^offset>slot i ##dispatch emit-if iterate-next ;
+    ds-pop ^^offset>slot i ##dispatch emit-if ;
 
 ! #call
 M: #call emit-node
     dup word>> dup "intrinsic" word-prop
-    [ emit-intrinsic ] [ swap call-height emit-call ] if ;
+    [ emit-intrinsic ] [ nip emit-call ] if ;
 
 ! #call-recursive
-M: #call-recursive emit-node [ label>> id>> ] [ call-height ] bi emit-call ;
+M: #call-recursive emit-node label>> id>> emit-call ;
 
 ! #push
 M: #push emit-node
-    literal>> ^^load-literal ds-push iterate-next ;
+    literal>> ^^load-literal ds-push ;
 
 ! #shuffle
 M: #shuffle emit-node
@@ -183,19 +166,18 @@ M: #shuffle emit-node
     [ [ 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
-    iterate-next ;
+    [ [ [ out-r>> ] [ mapping>> ] bi ] dip '[ _ at _ at ] map rs-store ] 2bi ;
 
 ! #return
 M: #return emit-node
-    drop ##epilogue ##return stop-iterating ;
+    drop ##epilogue ##return ;
 
 M: #return-recursive emit-node
     label>> id>> loops get key?
-    [ iterate-next ] [ ##epilogue ##return stop-iterating ] if ;
+    [ ##epilogue ##return ] unless ;
 
 ! #terminate
-M: #terminate emit-node drop stop-iterating ;
+M: #terminate emit-node drop ##no-tco basic-block off ;
 
 ! FFI
 : return-size ( ctype -- n )
@@ -215,9 +197,9 @@ M: #terminate emit-node drop stop-iterating ;
 : alien-stack-frame ( params -- )
     <alien-stack-frame> ##stack-frame ;
 
-: emit-alien-node ( node quot -- next )
+: emit-alien-node ( node quot -- )
     [ params>> ] dip [ drop alien-stack-frame ] [ call ] 2bi
-    ##branch begin-basic-block iterate-next ; inline
+    ##branch begin-basic-block ; inline
 
 M: #alien-invoke emit-node
     [ ##alien-invoke ] emit-alien-node ;
@@ -229,17 +211,16 @@ M: #alien-callback emit-node
     dup params>> xt>> dup
     [
         ##prologue
-        dup [ ##alien-callback ] emit-alien-node drop
+        dup [ ##alien-callback ] emit-alien-node
         ##epilogue
         params>> ##callback-return
-    ] with-cfg-builder
-    iterate-next ;
+    ] with-cfg-builder ;
 
 ! No-op nodes
-M: #introduce emit-node drop iterate-next ;
+M: #introduce emit-node drop ;
 
-M: #copy emit-node drop iterate-next ;
+M: #copy emit-node drop ;
 
-M: #enter-recursive emit-node drop iterate-next ;
+M: #enter-recursive emit-node drop ;
 
-M: #phi emit-node drop iterate-next ;
+M: #phi emit-node drop ;
diff --git a/basis/compiler/cfg/cfg-tests.factor b/basis/compiler/cfg/cfg-tests.factor
new file mode 100644 (file)
index 0000000..e69de29
index dabc7338d28377ffa2ac667bb7114bf515497023..68d7e15a5de2610300bf23f263228c561c8e0f05 100644 (file)
@@ -1,7 +1,9 @@
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel arrays vectors accessors
-namespaces math make fry sequences ;
+USING: kernel arrays vectors accessors assocs sets
+namespaces math make fry sequences
+combinators.short-circuit
+compiler.cfg.instructions ;
 IN: compiler.cfg
 
 TUPLE: basic-block < identity-tuple
@@ -20,6 +22,25 @@ M: basic-block hashcode* nip id>> ;
         V{ } clone >>predecessors
         \ basic-block counter >>id ;
 
+: empty-block? ( bb -- ? )
+    instructions>> {
+        [ length 1 = ]
+        [ first ##branch? ]
+    } 1&& ;
+
+SYMBOL: visited
+
+: (skip-empty-blocks) ( bb -- bb' )
+    dup visited get key? [
+        dup empty-block? [
+            dup visited get conjoin
+            successors>> first (skip-empty-blocks)
+        ] when
+    ] unless ;
+
+: skip-empty-blocks ( bb -- bb' )
+    H{ } clone visited [ (skip-empty-blocks) ] with-variable ;
+
 : add-instructions ( bb quot -- )
     [ instructions>> building ] dip '[
         building get pop
index 4f215f1dc8081417703fd47ae558e6d5726a0bed..e7d9dbdd9c9e11f3f22f7e4c24229e4ae0fc2cfc 100644 (file)
@@ -19,7 +19,7 @@ ERROR: last-insn-not-a-jump insn ;
         [ ##fixnum-add-tail? ]
         [ ##fixnum-sub-tail? ]
         [ ##fixnum-mul-tail? ]
-        [ ##call? ]
+        [ ##no-tco? ]
     } 1|| [ drop ] [ last-insn-not-a-jump ] if ;
 
 ERROR: bad-loop-entry ;
index d4f5d6b3aeb70f66356d80c70755fbb63ef584df..a44f8d7f8d462129605979ca2bec95cc98dc3a48 100644 (file)
@@ -1 +1,2 @@
-Slava Pestov
\ No newline at end of file
+Slava Pestov
+Daniel Ehrenberg
diff --git a/basis/compiler/cfg/dce/dce-tests.factor b/basis/compiler/cfg/dce/dce-tests.factor
new file mode 100644 (file)
index 0000000..de2ed78
--- /dev/null
@@ -0,0 +1,72 @@
+! Copyright (C) 2009 Daniel Ehrenberg.
+! See http://factorcode.org/license.txt for BSD license.
+USING: tools.test compiler.cfg kernel accessors compiler.cfg.dce
+compiler.cfg.instructions compiler.cfg.registers cpu.architecture ;
+IN: compiler.cfg.dce.tests
+
+: test-dce ( insns -- insns' )
+    <basic-block> swap >>instructions
+    cfg new swap >>entry
+    eliminate-dead-code
+    entry>> instructions>> ; 
+
+[ V{
+    T{ ##load-immediate { dst V int-regs 1 } { val 8 } }
+    T{ ##load-immediate { dst V int-regs 2 } { val 16 } }
+    T{ ##add { dst V int-regs 3 } { src1 V int-regs 1 } { src2 V int-regs 2 } }
+    T{ ##replace { src V int-regs 3 } { loc D 0 } }
+} ] [ V{
+    T{ ##load-immediate { dst V int-regs 1 } { val 8 } }
+    T{ ##load-immediate { dst V int-regs 2 } { val 16 } }
+    T{ ##add { dst V int-regs 3 } { src1 V int-regs 1 } { src2 V int-regs 2 } }
+    T{ ##replace { src V int-regs 3 } { loc D 0 } }
+} test-dce ] unit-test
+
+[ V{ } ] [ V{
+    T{ ##load-immediate { dst V int-regs 1 } { val 8 } }
+    T{ ##load-immediate { dst V int-regs 2 } { val 16 } }
+    T{ ##add { dst V int-regs 3 } { src1 V int-regs 1 } { src2 V int-regs 2 } }
+} test-dce ] unit-test
+
+[ V{ } ] [ V{
+    T{ ##load-immediate { dst V int-regs 3 } { val 8 } }
+    T{ ##allot { dst V int-regs 1 } { temp V int-regs 2 } }
+} test-dce ] unit-test
+
+[ V{ } ] [ V{
+    T{ ##load-immediate { dst V int-regs 3 } { val 8 } }
+    T{ ##allot { dst V int-regs 1 } { temp V int-regs 2 } }
+    T{ ##set-slot-imm { obj V int-regs 1 } { src V int-regs 3 } }
+} test-dce ] unit-test
+
+[ V{
+    T{ ##load-immediate { dst V int-regs 3 } { val 8 } }
+    T{ ##allot { dst V int-regs 1 } { temp V int-regs 2 } }
+    T{ ##set-slot-imm { obj V int-regs 1 } { src V int-regs 3 } }
+    T{ ##replace { src V int-regs 1 } { loc D 0 } }
+} ] [ V{
+    T{ ##load-immediate { dst V int-regs 3 } { val 8 } }
+    T{ ##allot { dst V int-regs 1 } { temp V int-regs 2 } }
+    T{ ##set-slot-imm { obj V int-regs 1 } { src V int-regs 3 } }
+    T{ ##replace { src V int-regs 1 } { loc D 0 } }
+} test-dce ] unit-test
+
+[ V{
+    T{ ##allot { dst V int-regs 1 } { temp V int-regs 2 } }
+    T{ ##replace { src V int-regs 1 } { loc D 0 } }
+} ] [ V{
+    T{ ##allot { dst V int-regs 1 } { temp V int-regs 2 } }
+    T{ ##replace { src V int-regs 1 } { loc D 0 } }
+} test-dce ] unit-test
+
+[ V{
+    T{ ##allot { dst V int-regs 1 } { temp V int-regs 2 } }
+    T{ ##replace { src V int-regs 1 } { loc D 0 } }
+    T{ ##load-immediate { dst V int-regs 3 } { val 8 } }
+    T{ ##set-slot-imm { obj V int-regs 1 } { src V int-regs 3 } }
+} ] [ V{
+    T{ ##allot { dst V int-regs 1 } { temp V int-regs 2 } }
+    T{ ##replace { src V int-regs 1 } { loc D 0 } }
+    T{ ##load-immediate { dst V int-regs 3 } { val 8 } }
+    T{ ##set-slot-imm { obj V int-regs 1 } { src V int-regs 3 } }
+} test-dce ] unit-test
index 68c89be455efad91a4f187ad5312a9bc6b098b70..fdc6601de41c1d0009334ed42f87a0e234f31ed5 100644 (file)
@@ -1,4 +1,4 @@
-! 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 assocs sets kernel namespaces sequences
 compiler.cfg.instructions compiler.cfg.def-use
@@ -11,35 +11,93 @@ SYMBOL: liveness-graph
 ! vregs which participate in side effects and thus are always live
 SYMBOL: live-vregs
 
+: live-vreg? ( vreg -- ? )
+    live-vregs get key? ;
+
+! vregs which are the result of an allocation
+SYMBOL: allocations
+
+: allocation? ( vreg -- ? )
+    allocations get key? ;
+
 : init-dead-code ( -- )
     H{ } clone liveness-graph set
-    H{ } clone live-vregs set ;
+    H{ } clone live-vregs set
+    H{ } clone allocations set ;
+
+GENERIC: build-liveness-graph ( insn -- )
+
+: add-edges ( insn register -- )
+    [ uses-vregs ] dip liveness-graph get [ union ] change-at ;
+
+: setter-liveness-graph ( insn vreg -- )
+    dup allocation? [ add-edges ] [ 2drop ] if ;
+
+M: ##set-slot build-liveness-graph
+    dup obj>> setter-liveness-graph ;
+
+M: ##set-slot-imm build-liveness-graph
+    dup obj>> setter-liveness-graph ;
+
+M: ##write-barrier build-liveness-graph
+    dup src>> setter-liveness-graph ;
+
+M: ##flushable build-liveness-graph
+    dup dst>> add-edges ;
 
-GENERIC: update-liveness-graph ( insn -- )
+M: ##allot build-liveness-graph
+    [ dst>> allocations get conjoin ]
+    [ call-next-method ] bi ;
 
-M: ##flushable update-liveness-graph
-    [ uses-vregs ] [ dst>> ] bi liveness-graph get set-at ;
+M: insn build-liveness-graph drop ;
 
-: record-live ( vregs -- )
+GENERIC: compute-live-vregs ( insn -- )
+
+: (record-live) ( vregs -- )
     [
         dup live-vregs get key? [ drop ] [
             [ live-vregs get conjoin ]
-            [ liveness-graph get at record-live ]
+            [ liveness-graph get at (record-live) ]
             bi
         ] if
     ] each ;
 
-M: insn update-liveness-graph uses-vregs record-live ;
+: record-live ( insn -- )
+    uses-vregs (record-live) ;
+
+: setter-live-vregs ( insn vreg -- )
+    allocation? [ drop ] [ record-live ] if ;
+
+M: ##set-slot compute-live-vregs
+    dup obj>> setter-live-vregs ;
+
+M: ##set-slot-imm compute-live-vregs
+    dup obj>> setter-live-vregs ;
+
+M: ##write-barrier compute-live-vregs
+    dup src>> setter-live-vregs ;
+
+M: ##flushable compute-live-vregs drop ;
+
+M: insn compute-live-vregs
+    record-live ;
 
 GENERIC: live-insn? ( insn -- ? )
 
-M: ##flushable live-insn? dst>> live-vregs get key? ;
+M: ##flushable live-insn? dst>> live-vreg? ;
+
+M: ##set-slot live-insn? obj>> live-vreg? ;
+
+M: ##set-slot-imm live-insn? obj>> live-vreg? ;
+
+M: ##write-barrier live-insn? src>> live-vreg? ;
 
 M: insn live-insn? drop t ;
 
 : eliminate-dead-code ( cfg -- cfg' )
     init-dead-code
-    [ [ instructions>> [ update-liveness-graph ] each ] each-basic-block ]
-    [ [ [ [ live-insn? ] filter ] change-instructions drop ] each-basic-block ]
-    [ ]
-    tri ;
\ No newline at end of file
+    dup
+    [ [ instructions>> [ build-liveness-graph ] each ] each-basic-block ]
+    [ [ instructions>> [ compute-live-vregs ] each ] each-basic-block ]
+    [ [ instructions>> [ live-insn? ] filter-here ] each-basic-block ]
+    tri ;
diff --git a/basis/compiler/cfg/dce/summary.txt b/basis/compiler/cfg/dce/summary.txt
new file mode 100644 (file)
index 0000000..82b391c
--- /dev/null
@@ -0,0 +1 @@
+Dead code elimination
index 4ff9814e6d0a03bb8c7ab417223b75b90dc13bbf..43ea89f28401b668e6fafb446f0b2ffd353328a5 100644 (file)
@@ -1,6 +1,6 @@
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors arrays kernel compiler.cfg.instructions ;
+USING: accessors arrays kernel assocs compiler.cfg.instructions ;
 IN: compiler.cfg.def-use
 
 GENERIC: defs-vregs ( insn -- seq )
@@ -43,7 +43,7 @@ M: ##dispatch uses-vregs src>> 1array ;
 M: ##alien-getter uses-vregs src>> 1array ;
 M: ##alien-setter uses-vregs [ src>> ] [ value>> ] bi 2array ;
 M: ##fixnum-overflow uses-vregs [ src1>> ] [ src2>> ] bi 2array ;
-M: ##phi uses-vregs inputs>> ;
+M: ##phi uses-vregs inputs>> values ;
 M: _conditional-branch uses-vregs [ src1>> ] [ src2>> ] bi 2array ;
 M: _compare-imm-branch uses-vregs src1>> 1array ;
 M: _dispatch uses-vregs src>> 1array ;
index 417691412624c0124121b035b4d64520923ca002..8435a231e6d3c02db325c0569f124daba42675b5 100644 (file)
@@ -1,20 +1,16 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors kernel sequences assocs
-cpu.architecture compiler.cfg.rpo
-compiler.cfg.liveness compiler.cfg.instructions
+compiler.cfg.rpo compiler.cfg.instructions
 compiler.cfg.hats ;
 IN: compiler.cfg.gc-checks
 
 : gc? ( bb -- ? )
     instructions>> [ ##allocation? ] any? ;
 
-: object-pointer-regs ( basic-block -- vregs )
-    live-in keys [ reg-class>> int-regs eq? ] filter ;
-
 : insert-gc-check ( basic-block -- )
     dup gc? [
-        [ i i f \ ##gc new-insn prefix ] change-instructions drop
+        [ i i f \ ##gc new-insn prefix ] change-instructions drop
     ] [ drop ] if ;
 
 : insert-gc-checks ( cfg -- cfg' )
index 4ce9c59e7e0ef4ec12fe23b3dbbc414c43c591ee..abbb86cb16d6f64497160668bcbc358c2fe77cf2 100644 (file)
@@ -53,10 +53,13 @@ INSN: ##inc-r { n integer } ;
 
 ! Subroutine calls
 INSN: ##stack-frame stack-frame ;
-INSN: ##call word { height integer } ;
+INSN: ##call word ;
 INSN: ##jump word ;
 INSN: ##return ;
 
+! Dummy instruction that simply inhibits TCO
+INSN: ##no-tco ;
+
 ! Jump tables
 INSN: ##dispatch src temp ;
 
@@ -196,6 +199,16 @@ SYMBOL: cc/=
         { cc/= cc= }
     } at ;
 
+: swap-cc ( cc -- cc' )
+    H{
+        { cc< cc> }
+        { cc<= cc>= }
+        { cc> cc< }
+        { cc>= cc<= }
+        { cc= cc= }
+        { cc/= cc/= }
+    } at ;
+
 : evaluate-cc ( result cc -- ? )
     H{
         { cc<  { +lt+           } }
@@ -217,7 +230,7 @@ INSN: ##compare-imm < ##binary-imm cc temp ;
 INSN: ##compare-float-branch < ##conditional-branch ;
 INSN: ##compare-float < ##binary cc temp ;
 
-INSN: ##gc { temp1 vreg } { temp2 vreg } live-registers live-spill-slots ;
+INSN: ##gc { temp1 vreg } { temp2 vreg } live-values ;
 
 ! Instructions used by machine IR only.
 INSN: _prologue stack-frame ;
@@ -248,4 +261,3 @@ INSN: _reload dst class n ;
 INSN: _copy dst src class ;
 INSN: _spill-counts counts ;
 
-SYMBOL: spill-temp
index a93fa5d90206972de3f81bd38354740048c064cb..9efac9e81a549ca0f4f8d5c67b079e6efc7e0d10 100644 (file)
@@ -1,11 +1,10 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2009 Slava Pestov, Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: sequences accessors layouts kernel math namespaces
 combinators fry locals
 compiler.tree.propagation.info
 compiler.cfg.hats
 compiler.cfg.stacks
-compiler.cfg.iterator
 compiler.cfg.instructions
 compiler.cfg.utilities
 compiler.cfg.registers ;
@@ -40,15 +39,11 @@ IN: compiler.cfg.intrinsics.fixnum
 
 :: emit-commutative-fixnum-op ( node insn imm-insn -- )
     [let | infos [ node node-input-infos ] |
-        infos first value-info-small-tagged?
-        [ infos imm-insn emit-fixnum-imm-op1 ]
-        [
-            infos second value-info-small-tagged? [
-                infos imm-insn emit-fixnum-imm-op2
-            ] [
-                insn (emit-fixnum-op)
-            ] if
-        ] if
+        {
+            { [ infos first value-info-small-tagged? ] [ infos imm-insn emit-fixnum-imm-op1 ] }
+            { [ infos second value-info-small-tagged? ] [ infos imm-insn emit-fixnum-imm-op2 ] }
+            [ insn (emit-fixnum-op) ]
+        } cond
         ds-push
     ] ; inline
 
@@ -63,7 +58,7 @@ IN: compiler.cfg.intrinsics.fixnum
         } case
         ds-push
     ] [ drop emit-primitive ] if ;
-
+    
 : emit-fixnum-bitnot ( -- )
     ds-pop ^^not tag-mask get ^^xor-imm ds-push ;
 
@@ -73,21 +68,28 @@ IN: compiler.cfg.intrinsics.fixnum
 : (emit-fixnum*fast) ( -- dst )
     2inputs ^^untag-fixnum ^^mul ;
 
-: (emit-fixnum*fast-imm) ( infos -- dst )
-    ds-drop
-    [ ds-pop ] [ second literal>> ] bi* ^^mul-imm ;
+: (emit-fixnum*fast-imm1) ( infos -- dst )
+    [ ds-pop ds-drop ] [ first literal>> ] bi* ^^mul-imm ;
+
+: (emit-fixnum*fast-imm2) ( infos -- dst )
+    [ ds-drop ds-pop ] [ second literal>> ] bi* ^^mul-imm ;
 
 : emit-fixnum*fast ( node -- )
     node-input-infos
-    dup second value-info-small-fixnum?
-    [ (emit-fixnum*fast-imm) ] [ drop (emit-fixnum*fast) ] if
+    dup first value-info-small-fixnum? drop f
+    [
+        (emit-fixnum*fast-imm1)
+    ] [
+        dup second value-info-small-fixnum?
+        [ (emit-fixnum*fast-imm2) ] [ drop (emit-fixnum*fast) ] if
+    ] if
     ds-push ;
 
 : (emit-fixnum-comparison) ( cc -- quot1 quot2 )
     [ ^^compare ] [ ^^compare-imm ] bi-curry ; inline
 
-: emit-eq ( node cc -- )
-    (emit-fixnum-comparison) emit-commutative-fixnum-op ;
+: emit-eq ( node -- )
+    cc= (emit-fixnum-comparison) emit-commutative-fixnum-op ;
 
 : emit-fixnum-comparison ( node cc -- )
     (emit-fixnum-comparison) emit-fixnum-op ;
@@ -98,15 +100,6 @@ IN: compiler.cfg.intrinsics.fixnum
 : emit-fixnum>bignum ( -- )
     ds-pop ^^untag-fixnum ^^integer>bignum ds-push ;
 
-: emit-fixnum-overflow-op ( quot quot-tail -- next )
-    [ 2inputs 1 ##inc-d ] 2dip
-    tail-call? [
-        ##epilogue
-        nip call
-        stop-iterating
-    ] [
-        drop call
-        ##branch
-        begin-basic-block
-        iterate-next
-    ] if ; inline
+: emit-fixnum-overflow-op ( quot -- next )
+    [ 2inputs 1 ##inc-d ] dip call ##branch
+    begin-basic-block ; inline
index 15c9c0cef3432b63d0e3244366b20a6845028ce1..df01bba89ba18c706f4bae91bda5c3a524039d78 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2009 Slava Pestov, Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: words sequences kernel combinators cpu.architecture
 compiler.cfg.hats
@@ -8,8 +8,7 @@ compiler.cfg.intrinsics.allot
 compiler.cfg.intrinsics.fixnum
 compiler.cfg.intrinsics.float
 compiler.cfg.intrinsics.slots
-compiler.cfg.intrinsics.misc
-compiler.cfg.iterator ;
+compiler.cfg.intrinsics.misc ;
 QUALIFIED: kernel
 QUALIFIED: arrays
 QUALIFIED: byte-arrays
@@ -95,66 +94,66 @@ IN: compiler.cfg.intrinsics
 : enable-fixnum-log2 ( -- )
     \ math.integers.private:fixnum-log2 t "intrinsic" set-word-prop ;
 
-: emit-intrinsic ( node word -- node/f )
+: emit-intrinsic ( node word -- )
     {
-        { \ kernel.private:tag [ drop emit-tag iterate-next ] }
-        { \ kernel.private:getenv [ emit-getenv iterate-next ] }
-        { \ math.private:both-fixnums? [ drop emit-both-fixnums? iterate-next ] }
-        { \ math.private:fixnum+ [ drop [ ##fixnum-add ] [ ##fixnum-add-tail ] emit-fixnum-overflow-op ] }
-        { \ math.private:fixnum- [ drop [ ##fixnum-sub ] [ ##fixnum-sub-tail ] emit-fixnum-overflow-op ] }
-        { \ math.private:fixnum* [ drop [ i i ##fixnum-mul ] [ i i ##fixnum-mul-tail ] emit-fixnum-overflow-op ] }
-        { \ math.private:fixnum+fast [ [ ^^add ] [ ^^add-imm ] emit-commutative-fixnum-op iterate-next ] }
-        { \ math.private:fixnum-fast [ [ ^^sub ] [ ^^sub-imm ] emit-fixnum-op iterate-next ] }
-        { \ math.private:fixnum-bitand [ [ ^^and ] [ ^^and-imm ] emit-commutative-fixnum-op iterate-next ] }
-        { \ math.private:fixnum-bitor [ [ ^^or ] [ ^^or-imm ] emit-commutative-fixnum-op iterate-next ] }
-        { \ math.private:fixnum-bitxor [ [ ^^xor ] [ ^^xor-imm ] emit-commutative-fixnum-op iterate-next ] }
-        { \ math.private:fixnum-shift-fast [ emit-fixnum-shift-fast iterate-next ] }
-        { \ math.private:fixnum-bitnot [ drop emit-fixnum-bitnot iterate-next ] }
-        { \ math.integers.private:fixnum-log2 [ drop emit-fixnum-log2 iterate-next ] }
-        { \ math.private:fixnum*fast [ emit-fixnum*fast iterate-next ] }
-        { \ math.private:fixnum< [ cc< emit-fixnum-comparison iterate-next ] }
-        { \ math.private:fixnum<= [ cc<= emit-fixnum-comparison iterate-next ] }
-        { \ math.private:fixnum>= [ cc>= emit-fixnum-comparison iterate-next ] }
-        { \ math.private:fixnum> [ cc> emit-fixnum-comparison iterate-next ] }
-        { \ kernel:eq? [ cc= emit-eq iterate-next ] }
-        { \ math.private:bignum>fixnum [ drop emit-bignum>fixnum iterate-next ] }
-        { \ math.private:fixnum>bignum [ drop emit-fixnum>bignum iterate-next ] }
-        { \ math.private:float+ [ drop [ ^^add-float ] emit-float-op iterate-next ] }
-        { \ math.private:float- [ drop [ ^^sub-float ] emit-float-op iterate-next ] }
-        { \ math.private:float* [ drop [ ^^mul-float ] emit-float-op iterate-next ] }
-        { \ math.private:float/f [ drop [ ^^div-float ] emit-float-op iterate-next ] }
-        { \ math.private:float< [ drop cc< emit-float-comparison iterate-next ] }
-        { \ math.private:float<= [ drop cc<= emit-float-comparison iterate-next ] }
-        { \ math.private:float>= [ drop cc>= emit-float-comparison iterate-next ] }
-        { \ math.private:float> [ drop cc> emit-float-comparison iterate-next ] }
-        { \ math.private:float= [ drop cc= emit-float-comparison iterate-next ] }
-        { \ math.private:float>fixnum [ drop emit-float>fixnum iterate-next ] }
-        { \ math.private:fixnum>float [ drop emit-fixnum>float iterate-next ] }
-        { \ slots.private:slot [ emit-slot iterate-next ] }
-        { \ slots.private:set-slot [ emit-set-slot iterate-next ] }
-        { \ strings.private:string-nth [ drop emit-string-nth iterate-next ] }
-        { \ strings.private:set-string-nth-fast [ drop emit-set-string-nth-fast iterate-next ] }
-        { \ classes.tuple.private:<tuple-boa> [ emit-<tuple-boa> iterate-next ] }
-        { \ arrays:<array> [ emit-<array> iterate-next ] }
-        { \ byte-arrays:<byte-array> [ emit-<byte-array> iterate-next ] }
-        { \ byte-arrays:(byte-array) [ emit-(byte-array) iterate-next ] }
-        { \ kernel:<wrapper> [ emit-simple-allot iterate-next ] }
-        { \ alien.accessors:alien-unsigned-1 [ 1 emit-alien-unsigned-getter iterate-next ] }
-        { \ alien.accessors:set-alien-unsigned-1 [ 1 emit-alien-integer-setter iterate-next ] }
-        { \ alien.accessors:alien-signed-1 [ 1 emit-alien-signed-getter iterate-next ] }
-        { \ alien.accessors:set-alien-signed-1 [ 1 emit-alien-integer-setter iterate-next ] }
-        { \ alien.accessors:alien-unsigned-2 [ 2 emit-alien-unsigned-getter iterate-next ] }
-        { \ alien.accessors:set-alien-unsigned-2 [ 2 emit-alien-integer-setter iterate-next ] }
-        { \ alien.accessors:alien-signed-2 [ 2 emit-alien-signed-getter iterate-next ] }
-        { \ alien.accessors:set-alien-signed-2 [ 2 emit-alien-integer-setter iterate-next ] }
-        { \ alien.accessors:alien-unsigned-4 [ 4 emit-alien-unsigned-getter iterate-next ] }
-        { \ alien.accessors:set-alien-unsigned-4 [ 4 emit-alien-integer-setter iterate-next ] }
-        { \ alien.accessors:alien-signed-4 [ 4 emit-alien-signed-getter iterate-next ] }
-        { \ alien.accessors:set-alien-signed-4 [ 4 emit-alien-integer-setter iterate-next ] }
-        { \ alien.accessors:alien-cell [ emit-alien-cell-getter iterate-next ] }
-        { \ alien.accessors:set-alien-cell [ emit-alien-cell-setter iterate-next ] }
-        { \ alien.accessors:alien-float [ single-float-regs emit-alien-float-getter iterate-next ] }
-        { \ alien.accessors:set-alien-float [ single-float-regs emit-alien-float-setter iterate-next ] }
-        { \ alien.accessors:alien-double [ double-float-regs emit-alien-float-getter iterate-next ] }
-        { \ alien.accessors:set-alien-double [ double-float-regs emit-alien-float-setter iterate-next ] }
+        { \ kernel.private:tag [ drop emit-tag ] }
+        { \ kernel.private:getenv [ emit-getenv ] }
+        { \ math.private:both-fixnums? [ drop emit-both-fixnums? ] }
+        { \ math.private:fixnum+ [ drop [ ##fixnum-add ] emit-fixnum-overflow-op ] }
+        { \ math.private:fixnum- [ drop [ ##fixnum-sub ] emit-fixnum-overflow-op ] }
+        { \ math.private:fixnum* [ drop [ i i ##fixnum-mul ] emit-fixnum-overflow-op ] }
+        { \ math.private:fixnum+fast [ [ ^^add ] [ ^^add-imm ] emit-commutative-fixnum-op ] }
+        { \ math.private:fixnum-fast [ [ ^^sub ] [ ^^sub-imm ] emit-fixnum-op ] }
+        { \ math.private:fixnum-bitand [ [ ^^and ] [ ^^and-imm ] emit-commutative-fixnum-op ] }
+        { \ math.private:fixnum-bitor [ [ ^^or ] [ ^^or-imm ] emit-commutative-fixnum-op ] }
+        { \ math.private:fixnum-bitxor [ [ ^^xor ] [ ^^xor-imm ] emit-commutative-fixnum-op ] }
+        { \ math.private:fixnum-shift-fast [ emit-fixnum-shift-fast ] }
+        { \ math.private:fixnum-bitnot [ drop emit-fixnum-bitnot ] }
+        { \ math.integers.private:fixnum-log2 [ drop emit-fixnum-log2 ] }
+        { \ math.private:fixnum*fast [ emit-fixnum*fast ] }
+        { \ math.private:fixnum< [ cc< emit-fixnum-comparison ] }
+        { \ math.private:fixnum<= [ cc<= emit-fixnum-comparison ] }
+        { \ math.private:fixnum>= [ cc>= emit-fixnum-comparison ] }
+        { \ math.private:fixnum> [ cc> emit-fixnum-comparison ] }
+        { \ kernel:eq? [ emit-eq ] }
+        { \ math.private:bignum>fixnum [ drop emit-bignum>fixnum ] }
+        { \ math.private:fixnum>bignum [ drop emit-fixnum>bignum ] }
+        { \ math.private:float+ [ drop [ ^^add-float ] emit-float-op ] }
+        { \ math.private:float- [ drop [ ^^sub-float ] emit-float-op ] }
+        { \ math.private:float* [ drop [ ^^mul-float ] emit-float-op ] }
+        { \ math.private:float/f [ drop [ ^^div-float ] emit-float-op ] }
+        { \ math.private:float< [ drop cc< emit-float-comparison ] }
+        { \ math.private:float<= [ drop cc<= emit-float-comparison ] }
+        { \ math.private:float>= [ drop cc>= emit-float-comparison ] }
+        { \ math.private:float> [ drop cc> emit-float-comparison ] }
+        { \ math.private:float= [ drop cc= emit-float-comparison ] }
+        { \ math.private:float>fixnum [ drop emit-float>fixnum ] }
+        { \ math.private:fixnum>float [ drop emit-fixnum>float ] }
+        { \ slots.private:slot [ emit-slot ] }
+        { \ slots.private:set-slot [ emit-set-slot ] }
+        { \ strings.private:string-nth [ drop emit-string-nth ] }
+        { \ strings.private:set-string-nth-fast [ drop emit-set-string-nth-fast ] }
+        { \ classes.tuple.private:<tuple-boa> [ emit-<tuple-boa> ] }
+        { \ arrays:<array> [ emit-<array> ] }
+        { \ byte-arrays:<byte-array> [ emit-<byte-array> ] }
+        { \ byte-arrays:(byte-array) [ emit-(byte-array) ] }
+        { \ kernel:<wrapper> [ emit-simple-allot ] }
+        { \ alien.accessors:alien-unsigned-1 [ 1 emit-alien-unsigned-getter ] }
+        { \ alien.accessors:set-alien-unsigned-1 [ 1 emit-alien-integer-setter ] }
+        { \ alien.accessors:alien-signed-1 [ 1 emit-alien-signed-getter ] }
+        { \ alien.accessors:set-alien-signed-1 [ 1 emit-alien-integer-setter ] }
+        { \ alien.accessors:alien-unsigned-2 [ 2 emit-alien-unsigned-getter ] }
+        { \ alien.accessors:set-alien-unsigned-2 [ 2 emit-alien-integer-setter ] }
+        { \ alien.accessors:alien-signed-2 [ 2 emit-alien-signed-getter ] }
+        { \ alien.accessors:set-alien-signed-2 [ 2 emit-alien-integer-setter ] }
+        { \ alien.accessors:alien-unsigned-4 [ 4 emit-alien-unsigned-getter ] }
+        { \ alien.accessors:set-alien-unsigned-4 [ 4 emit-alien-integer-setter ] }
+        { \ alien.accessors:alien-signed-4 [ 4 emit-alien-signed-getter ] }
+        { \ alien.accessors:set-alien-signed-4 [ 4 emit-alien-integer-setter ] }
+        { \ alien.accessors:alien-cell [ emit-alien-cell-getter ] }
+        { \ alien.accessors:set-alien-cell [ emit-alien-cell-setter ] }
+        { \ alien.accessors:alien-float [ single-float-regs emit-alien-float-getter ] }
+        { \ alien.accessors:set-alien-float [ single-float-regs emit-alien-float-setter ] }
+        { \ alien.accessors:alien-double [ double-float-regs emit-alien-float-getter ] }
+        { \ alien.accessors:set-alien-double [ double-float-regs emit-alien-float-setter ] }
     } case ;
diff --git a/basis/compiler/cfg/iterator/iterator.factor b/basis/compiler/cfg/iterator/iterator.factor
deleted file mode 100644 (file)
index eb7f71a..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-! Copyright (C) 2008 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: namespaces sequences kernel compiler.tree ;
-IN: compiler.cfg.iterator
-
-SYMBOL: node-stack
-
-: >node ( cursor -- ) node-stack get push ;
-: node> ( -- cursor ) node-stack get pop ;
-: node@ ( -- cursor ) node-stack get last ;
-: current-node ( -- node ) node@ first ;
-: iterate-next ( -- cursor ) node@ rest-slice ;
-: skip-next ( -- next ) node> rest-slice [ first ] [ >node ] bi ;
-
-: iterate-nodes ( cursor quot: ( -- ) -- )
-    over empty? [
-        2drop
-    ] [
-        [ swap >node call node> drop ] keep iterate-nodes
-    ] if ; inline recursive
-
-DEFER: (tail-call?)
-
-: tail-phi? ( cursor -- ? )
-    [ first #phi? ] [ rest-slice (tail-call?) ] bi and ;
-
-: (tail-call?) ( cursor -- ? )
-    [ t ] [
-        [
-            first
-            [ #return? ]
-            [ #return-recursive? ]
-            [ #terminate? ] tri or or
-        ] [ tail-phi? ] bi or
-    ] if-empty ;
-
-: tail-call? ( -- ? )
-    node-stack get [
-        rest-slice
-        [ t ] [ (tail-call?) ] if-empty
-    ] all? ;
-
-: terminate-call? ( -- ? )
-    node-stack get last
-    rest-slice [ f ] [ first #terminate? ] if-empty ;
diff --git a/basis/compiler/cfg/iterator/summary.txt b/basis/compiler/cfg/iterator/summary.txt
deleted file mode 100644 (file)
index b5afb47..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Utility for iterating for high-level IR
index d948fe37ff636c7cb2682a2145b5eafa347ba494..7dd39776050c459ee08ff5e3231a8a0fb6f0f0a6 100644 (file)
@@ -9,11 +9,6 @@ compiler.cfg.linear-scan.allocation.splitting
 compiler.cfg.linear-scan.allocation.state ;
 IN: compiler.cfg.linear-scan.allocation
 
-: free-positions ( new -- assoc )
-    vreg>> reg-class>> registers get at [ 1/0. ] H{ } map>assoc ;
-
-: add-use-position ( n reg assoc -- ) [ [ min ] when* ] change-at ;
-
 : active-positions ( new assoc -- )
     [ vreg>> active-intervals-for ] dip
     '[ [ 0 ] dip reg>> _ add-use-position ] each ;
@@ -21,11 +16,11 @@ IN: compiler.cfg.linear-scan.allocation
 : inactive-positions ( new assoc -- )
     [ [ vreg>> inactive-intervals-for ] keep ] dip
     '[
-        [ _ relevant-ranges intersect-live-ranges ] [ reg>> ] bi
+        [ _ relevant-ranges intersect-live-ranges 1/0. or ] [ reg>> ] bi
         _ add-use-position
     ] each ;
 
-: compute-free-pos ( new -- free-pos )
+: register-status ( new -- free-pos )
     dup free-positions
     [ inactive-positions ] [ active-positions ] [ nip ] 2tri
     >alist alist-max ;
@@ -33,19 +28,13 @@ IN: compiler.cfg.linear-scan.allocation
 : no-free-registers? ( result -- ? )
     second 0 = ; inline
 
-: register-available? ( new result -- ? )
-    [ end>> ] [ second ] bi* < ; inline
-
-: register-available ( new result -- )
-    first >>reg add-active ;
-
 : register-partially-available ( new result -- )
     [ second split-before-use ] keep
     '[ _ register-available ] [ add-unhandled ] bi* ;
 
 : assign-register ( new -- )
     dup coalesce? [ coalesce ] [
-        dup compute-free-pos {
+        dup register-status {
             { [ dup no-free-registers? ] [ drop assign-blocked-register ] }
             { [ 2dup register-available? ] [ register-available ] }
             [ register-partially-available ]
index b2b9202204099d9672282eb253856483c41330d3..e99c2ba710cbcc658c900b315fda731d04bc177a 100644 (file)
@@ -9,15 +9,15 @@ IN: compiler.cfg.linear-scan.allocation.coalescing
 : active-interval ( vreg -- live-interval )
     dup [ dup active-intervals-for [ vreg>> = ] with find nip ] when ;
 
-: intersects-inactive-intervals? ( live-interval -- ? )
+: avoids-inactive-intervals? ( live-interval -- ? )
     dup vreg>> inactive-intervals-for
-    [ relevant-ranges intersect-live-ranges 1/0. = ] with all? ;
+    [ intervals-intersect? not ] with all? ;
 
 : coalesce? ( live-interval -- ? )
     {
         [ copy-from>> active-interval ]
         [ [ start>> ] [ copy-from>> active-interval end>> ] bi = ]
-        [ intersects-inactive-intervals? ]
+        [ avoids-inactive-intervals? ]
     } 1&& ;
 
 : coalesce ( live-interval -- )
index 2f4130e9adc5d1b5dded08cbe02b9b173cc1cee5..9949832294e4c63410b07ef8fd3d97cbb1f43e37 100644 (file)
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays assocs combinators fry hints kernel locals
-math sequences sets sorting splitting compiler.utilities
+math sequences sets sorting splitting namespaces
+combinators.short-circuit compiler.utilities
 compiler.cfg.linear-scan.allocation.state
 compiler.cfg.linear-scan.allocation.splitting
 compiler.cfg.linear-scan.live-intervals ;
 IN: compiler.cfg.linear-scan.allocation.spilling
 
-: find-use ( live-interval n quot -- elt )
-    [ uses>> ] 2dip curry find nip ; inline
+ERROR: bad-live-ranges interval ;
 
-: spill-existing? ( new existing -- ? )
-    #! Test if 'new' will be used before 'existing'.
-    over start>> '[ _ [ > ] find-use -1 or ] bi@ < ;
+: check-ranges ( live-interval -- )
+    check-allocation? get [
+        dup ranges>> [ [ from>> ] [ to>> ] bi <= ] all?
+        [ drop ] [ bad-live-ranges ] if
+    ] [ drop ] if ;
 
-: interval-to-spill ( active-intervals current -- live-interval )
-    #! We spill the interval with the most distant use location.
-    start>> '[ dup _ [ >= ] find-use ] { } map>assoc
-    alist-max first ;
+: trim-before-ranges ( live-interval -- )
+    [ ranges>> ] [ uses>> last ] bi
+    [ '[ from>> _ <= ] filter-here ]
+    [ swap last (>>to) ]
+    2bi ;
+
+: trim-after-ranges ( live-interval -- )
+    [ ranges>> ] [ uses>> first ] bi
+    [ '[ to>> _ >= ] filter-here ]
+    [ 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 drop ;
+
+: 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* ;
+
+: find-use-position ( live-interval new -- n )
+    [ uses>> ] [ start>> '[ _ >= ] ] bi* find nip 1/0. or ;
+
+: find-use-positions ( live-intervals new assoc -- )
+    '[ [ _ find-use-position ] [ reg>> ] bi _ add-use-position ] each ;
+
+: active-positions ( new assoc -- )
+    [ [ vreg>> active-intervals-for ] keep ] dip
+    find-use-positions ;
+
+: inactive-positions ( new assoc -- )
     [
-        [ [ ranges>> last ] [ uses>> last ] bi >>to drop ]
-        [ [ ranges>> first ] [ uses>> first ] bi >>from drop ] bi*
-    ]
-    [ [ compute-start/end ] bi@ ]
-    [ ]
-    2tri ;
-
-: assign-spill ( before after -- before after )
-    #! If it has been spilled already, reuse spill location.
-    over reload-from>>
-    [ over vreg>> reg-class>> next-spill-location ] unless*
-    [ >>spill-to ] [ >>reload-from ] bi-curry bi* ;
-
-: split-and-spill ( new existing -- before after )
-    swap start>> split-for-spill assign-spill ;
-
-: spill-existing ( new existing -- )
-    #! Our new interval will be used before the active interval
-    #! with the most distant use location. Spill the existing
-    #! interval, then process the new interval and the tail end
-    #! of the existing interval again.
-    [ nip delete-active ]
-    [ reg>> >>reg add-active ]
-    [ split-and-spill [ add-handled ] [ add-unhandled ] bi* ] 2tri ;
-
-: spill-new ( new existing -- )
-    #! Our new interval will be used after the active interval
-    #! with the most distant use location. Split the new
-    #! interval, then process both parts of the new interval
-    #! again.
-    [ dup split-and-spill add-unhandled ] dip spill-existing ;
+        [ vreg>> inactive-intervals-for ] keep
+        [ '[ _ intervals-intersect? ] filter ] keep
+    ] dip
+    find-use-positions ;
 
-: assign-blocked-register ( new -- )
-    [ dup vreg>> active-intervals-for ] keep interval-to-spill
-    2dup spill-existing? [ spill-existing ] [ spill-new ] if ;
+: spill-status ( new -- use-pos )
+    H{ } clone
+    [ inactive-positions ] [ active-positions ] [ nip ] 2tri
+    >alist alist-max ;
+
+: spill-new? ( new pair -- ? )
+    [ uses>> first ] [ second ] bi* > ;
+
+: spill-new ( new pair -- )
+    drop
+    {
+        [ trim-after-ranges ]
+        [ compute-start/end ]
+        [ assign-reload ]
+        [ add-unhandled ]
+    } cleave ;
+
+: split-intersecting? ( live-interval new reg -- ? )
+    { [ [ drop reg>> ] dip = ] [ drop intervals-intersect? ] } 3&& ;
 
+: split-live-out ( live-interval -- )
+    {
+        [ trim-before-ranges ]
+        [ compute-start/end ]
+        [ assign-spill ]
+        [ add-handled ]
+    } cleave ;
+
+: split-live-in ( live-interval -- )
+    {
+        [ trim-after-ranges ]
+        [ compute-start/end ]
+        [ assign-reload ]
+        [ add-unhandled ]
+    } cleave ;
+
+: (split-intersecting) ( live-interval new -- )
+    start>> {
+        { [ 2dup [ uses>> last ] dip < ] [ drop split-live-out ] }
+        { [ 2dup [ uses>> first ] dip > ] [ drop split-live-in ] }
+        [ split-and-spill [ add-handled ] [ add-unhandled ] bi* ]
+    } cond ;
+
+: (split-intersecting-active) ( active new -- )
+    [ drop delete-active ]
+    [ (split-intersecting) ] 2bi ;
+
+: split-intersecting-active ( new reg -- )
+    [ [ vreg>> active-intervals-for ] keep ] dip
+    [ '[ _ _ split-intersecting? ] filter ] 2keep drop
+    '[ _ (split-intersecting-active) ] each ;
+
+: (split-intersecting-inactive) ( inactive new -- )
+    [ drop delete-inactive ]
+    [ (split-intersecting) ] 2bi ;
+
+: split-intersecting-inactive ( new reg -- )
+    [ [ vreg>> inactive-intervals-for ] keep ] dip
+    [ '[ _ _ split-intersecting? ] filter ] 2keep drop
+    '[ _ (split-intersecting-inactive) ] each ;
+
+: split-intersecting ( new reg -- )
+    [ split-intersecting-active ]
+    [ split-intersecting-inactive ]
+    2bi ;
+
+: spill-available ( new pair -- )
+    [ first split-intersecting ] [ register-available ] 2bi ;
+
+: spill-partially-available ( new pair -- )
+    [ second 1 - split-and-spill add-unhandled ] keep
+    spill-available ;
+
+: assign-blocked-register ( new -- )
+    dup spill-status {
+        { [ 2dup spill-new? ] [ spill-new ] }
+        { [ 2dup register-available? ] [ spill-available ] }
+        [ spill-partially-available ]
+    } cond ;
\ No newline at end of file
index e31fcedace01db642b2b4dab63e15d0edb3b5f9d..71d3d56285c7a48fe56ba9fc8a149e6c28c2c435 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays assocs combinators fry hints kernel locals
-math sequences sets sorting splitting
+math sequences sets sorting splitting namespaces
 compiler.cfg.linear-scan.allocation.state
 compiler.cfg.linear-scan.live-intervals ;
 IN: compiler.cfg.linear-scan.allocation.splitting
@@ -32,12 +32,17 @@ IN: compiler.cfg.linear-scan.allocation.splitting
 
 ERROR: splitting-too-early ;
 
+ERROR: splitting-too-late ;
+
 ERROR: splitting-atomic-interval ;
 
 : check-split ( live-interval n -- )
-    [ [ start>> ] dip > [ splitting-too-early ] when ]
-    [ drop [ end>> ] [ start>> ] bi - 0 = [ splitting-atomic-interval ] when ]
-    2bi ; inline
+    check-allocation? get [
+        [ [ start>> ] dip > [ splitting-too-early ] when ]
+        [ [ end>> ] dip <= [ splitting-too-late ] when ]
+        [ drop [ end>> ] [ start>> ] bi = [ splitting-atomic-interval ] when ]
+        2tri
+    ] [ 2drop ] if ; inline
 
 : split-before ( before -- before' )
     f >>spill-to ; inline
@@ -62,11 +67,12 @@ HINTS: split-interval live-interval object ;
     2dup [ compute-start/end ] bi@ ;
 
 : insert-use-for-copy ( seq n -- seq' )
-    dup 1 + [ nip 1array split1 ] 2keep 2array glue ;
+    [ '[ _ < ] filter ]
+    [ nip dup 1 + 2array ]
+    [ 1 + '[ _ > ] filter ]
+    2tri 3append ;
 
 : split-before-use ( new n -- before after )
-    ! Find optimal split position
-    ! Insert move instruction
     1 -
     2dup swap covers? [
         [ '[ _ insert-use-for-copy ] change-uses ] keep
index 737133aa32ad5591dbb2ee7d46fbc44a99345945..3e646b40f04b6644c24927b8133c5b4fcde546df 100644 (file)
@@ -1,10 +1,24 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors assocs combinators cpu.architecture fry heaps
-kernel math namespaces sequences vectors
+kernel math math.order namespaces sequences vectors
 compiler.cfg.linear-scan.live-intervals ;
 IN: compiler.cfg.linear-scan.allocation.state
 
+! Start index of current live interval. We ensure that all
+! live intervals added to the unhandled set have a start index
+! strictly greater than this one. This ensures that we can catch
+! infinite loop situations. We also ensure that all live
+! intervals added to the handled set have an end index strictly
+! smaller than this one. This helps catch bugs.
+SYMBOL: progress
+
+: check-unhandled ( live-interval -- )
+    start>> progress get <= [ "check-unhandled" throw ] when ; inline
+
+: check-handled ( live-interval -- )
+    end>> progress get > [ "check-handled" throw ] when ; inline
+
 ! Mapping from register classes to sequences of machine registers
 SYMBOL: registers
 
@@ -32,11 +46,14 @@ SYMBOL: inactive-intervals
 : add-inactive ( live-interval -- )
     dup vreg>> inactive-intervals-for push ;
 
+: delete-inactive ( live-interval -- )
+    dup vreg>> inactive-intervals-for delq ;
+
 ! Vector of handled live intervals
 SYMBOL: handled-intervals
 
 : add-handled ( live-interval -- )
-    handled-intervals get push ;
+    [ check-handled ] [ handled-intervals get push ] bi ;
 
 : finished? ( n live-interval -- ? ) end>> swap < ;
 
@@ -90,17 +107,8 @@ ERROR: register-already-used live-interval ;
 ! Minheap of live intervals which still need a register allocation
 SYMBOL: unhandled-intervals
 
-! Start index of current live interval. We ensure that all
-! live intervals added to the unhandled set have a start index
-! strictly greater than ths one. This ensures that we can catch
-! infinite loop situations.
-SYMBOL: progress
-
-: check-progress ( live-interval -- )
-    start>> progress get <= [ "No progress" throw ] when ; inline
-
 : add-unhandled ( live-interval -- )
-    [ check-progress ]
+    [ check-unhandled ]
     [ dup start>> unhandled-intervals get heap-push ]
     bi ;
 
@@ -109,20 +117,40 @@ CONSTANT: reg-classes { int-regs double-float-regs }
 : reg-class-assoc ( quot -- assoc )
     [ reg-classes ] dip { } map>assoc ; inline
 
+! Mapping from register classes to spill counts
 SYMBOL: spill-counts
 
-: next-spill-location ( reg-class -- n )
+: next-spill-slot ( reg-class -- n )
     spill-counts get [ dup 1 + ] change-at ;
 
+! Mapping from vregs to spill slots
+SYMBOL: spill-slots
+
+: assign-spill-slot ( vreg -- n )
+    spill-slots get [ reg-class>> next-spill-slot ] cache ;
+
 : init-allocator ( registers -- )
     registers set
-    [ 0 ] reg-class-assoc spill-counts set
     <min-heap> unhandled-intervals set
     [ V{ } clone ] reg-class-assoc active-intervals set
     [ V{ } clone ] reg-class-assoc inactive-intervals set
     V{ } clone handled-intervals set
+    [ 0 ] reg-class-assoc spill-counts set
+    H{ } clone spill-slots set
     -1 progress set ;
 
 : init-unhandled ( live-intervals -- )
     [ [ start>> ] keep ] { } map>assoc
-    unhandled-intervals get heap-push-all ;
\ No newline at end of file
+    unhandled-intervals get heap-push-all ;
+
+! A utility used by register-status and spill-status words
+: free-positions ( new -- assoc )
+    vreg>> reg-class>> registers get at [ 1/0. ] H{ } map>assoc ;
+
+: add-use-position ( n reg assoc -- ) [ [ min ] when* ] change-at ;
+
+: register-available? ( new result -- ? )
+    [ end>> ] [ second ] bi* < ; inline
+
+: register-available ( new result -- )
+    first >>reg add-active ;
index ea717f9218eab6d145b6500519606939a3554a27..c995569c2e2c5b5dd86e49ae5836c6afa349c6b8 100644 (file)
@@ -1,9 +1,11 @@
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors kernel math assocs namespaces sequences heaps
-fry make combinators sets
+fry make combinators sets locals
 cpu.architecture
+compiler.cfg
 compiler.cfg.def-use
+compiler.cfg.liveness
 compiler.cfg.registers
 compiler.cfg.instructions
 compiler.cfg.linear-scan.allocation
@@ -27,17 +29,18 @@ SYMBOL: unhandled-intervals
 : init-unhandled ( live-intervals -- )
     [ add-unhandled ] each ;
 
-! Mapping spill slots to vregs
-SYMBOL: spill-slots
+! Mapping from basic blocks to values which are live at the start
+SYMBOL: register-live-ins
 
-: spill-slots-for ( vreg -- assoc )
-    reg-class>> spill-slots get at ;
+! Mapping from basic blocks to values which are live at the end
+SYMBOL: register-live-outs
 
-ERROR: already-spilled ;
-
-: record-spill ( live-interval -- )
-    [ dup spill-to>> ] [ vreg>> spill-slots-for ] bi
-    2dup key? [ already-spilled ] [ set-at ] if ;
+: init-assignment ( live-intervals -- )
+    V{ } clone pending-intervals set
+    <min-heap> unhandled-intervals set
+    H{ } clone register-live-ins set
+    H{ } clone register-live-outs set
+    init-unhandled ;
 
 : insert-spill ( live-interval -- )
     {
@@ -48,19 +51,24 @@ ERROR: already-spilled ;
     } cleave f swap \ _spill boa , ;
 
 : handle-spill ( live-interval -- )
-    dup spill-to>> [ [ record-spill ] [ insert-spill ] bi ] [ drop ] if ;
+    dup spill-to>> [ insert-spill ] [ drop ] if ;
+
+: first-split ( live-interval -- live-interval' )
+    dup split-before>> [ first-split ] [ ] ?if ;
+
+: next-interval ( live-interval -- live-interval' )
+    split-next>> first-split ;
 
 : insert-copy ( live-interval -- )
     {
-        [ split-next>> reg>> ]
+        [ next-interval reg>> ]
         [ reg>> ]
         [ vreg>> reg-class>> ]
         [ end>> ]
     } cleave f swap \ _copy boa , ;
 
 : handle-copy ( live-interval -- )
-    dup [ spill-to>> not ] [ split-next>> ] bi and
-    [ insert-copy ] [ drop ] if ;
+    dup split-next>> [ insert-copy ] [ drop ] if ;
 
 : expire-old-intervals ( n -- )
     [ pending-intervals get ] dip '[
@@ -68,22 +76,16 @@ ERROR: already-spilled ;
         [ [ handle-spill ] [ handle-copy ] bi f ] [ drop t ] if
     ] filter-here ;
 
-ERROR: already-reloaded ;
-
-: record-reload ( live-interval -- )
-    [ reload-from>> ] [ vreg>> spill-slots-for ] bi
-    2dup key? [ delete-at ] [ already-reloaded ] if ;
-
 : insert-reload ( live-interval -- )
     {
         [ reg>> ]
         [ vreg>> reg-class>> ]
         [ reload-from>> ]
-        [ end>> ]
+        [ start>> ]
     } cleave f swap \ _reload boa , ;
 
 : handle-reload ( live-interval -- )
-    dup reload-from>> [ [ record-reload ] [ insert-reload ] bi ] [ drop ] if ;
+    dup reload-from>> [ insert-reload ] [ drop ] if ;
 
 : activate-new-intervals ( n -- )
     #! Any live intervals which start on the current instruction
@@ -96,10 +98,13 @@ ERROR: already-reloaded ;
         ] [ 2drop ] if
     ] if ;
 
+: prepare-insn ( n -- )
+    [ expire-old-intervals ] [ activate-new-intervals ] bi ;
+
 GENERIC: assign-registers-in-insn ( insn -- )
 
 : register-mapping ( live-intervals -- alist )
-    [ [ vreg>> ] [ reg>> ] bi ] { } map>assoc ;
+    [ [ vreg>> ] [ reg>> ] bi ] H{ } map>assoc ;
 
 : all-vregs ( insn -- vregs )
     [ defs-vregs ] [ temp-vregs ] [ uses-vregs ] tri 3append ;
@@ -112,55 +117,75 @@ ERROR: overlapping-registers intervals ;
     dup [ copy-from>> ] map sift '[ vreg>> _ member? not ] filter
     dup [ reg>> ] map all-unique? [ drop ] [ overlapping-registers ] if ;
 
-: active-intervals ( insn -- intervals )
-    insn#>> pending-intervals get [ covers? ] with filter
-    check-assignment? get [
-        dup check-assignment
-    ] when ;
+: active-intervals ( n -- intervals )
+    pending-intervals get [ covers? ] with filter
+    check-assignment? get [ dup check-assignment ] when ;
 
 M: vreg-insn assign-registers-in-insn
-    dup [ active-intervals ] [ all-vregs ] bi
-    '[ vreg>> _ member? ] filter
+    dup [ all-vregs ] [ insn#>> active-intervals ] bi
+    '[ _ [ vreg>> = ] with find nip ] map
     register-mapping
     >>regs drop ;
 
-: compute-live-registers ( insn -- regs )
-    [ active-intervals ] [ temp-vregs ] bi
-    '[ vreg>> _ memq? not ] filter
-    register-mapping ;
-
-: compute-live-spill-slots ( -- spill-slots )
-    spill-slots get values [ values ] map concat
-    [ [ vreg>> ] [ reload-from>> ] bi ] { } map>assoc ;
-
 M: ##gc assign-registers-in-insn
+    ! This works because ##gc is always the first instruction
+    ! in a block.
     dup call-next-method
-    dup compute-live-registers >>live-registers
-    compute-live-spill-slots >>live-spill-slots
+    basic-block get register-live-ins get at >>live-values
     drop ;
 
 M: insn assign-registers-in-insn drop ;
 
-: init-assignment ( live-intervals -- )
-    V{ } clone pending-intervals set
-    <min-heap> unhandled-intervals set
-    [ H{ } clone ] reg-class-assoc spill-slots set 
-    init-unhandled ;
+: compute-live-spill-slots ( vregs -- assoc )
+    spill-slots get '[ _ at dup [ <spill-slot> ] when ] assoc-map ;
+
+: compute-live-registers ( n -- assoc )
+    active-intervals register-mapping ;
+
+ERROR: bad-live-values live-values ;
+
+: check-live-values ( assoc -- assoc )
+    check-assignment? get [
+        dup values [ not ] any? [ bad-live-values ] when
+    ] when ;
+
+: compute-live-values ( vregs n -- assoc )
+    ! If a live vreg is not in active or inactive, then it must have been
+    ! spilled.
+    [ compute-live-spill-slots ] [ compute-live-registers ] bi*
+    assoc-union check-live-values ;
+
+: begin-block ( bb -- )
+    dup basic-block set
+    dup block-from prepare-insn
+    [ [ live-in ] [ block-from ] bi compute-live-values ] keep
+    register-live-ins get set-at ;
+
+: end-block ( bb -- )
+    [ [ live-out ] [ block-to ] bi compute-live-values ] keep
+    register-live-outs get set-at ;
+
+ERROR: bad-vreg vreg ;
+
+: vreg-at-start ( vreg bb -- state )
+    register-live-ins get at ?at [ bad-vreg ] unless ;
+
+: vreg-at-end ( vreg bb -- state )
+    register-live-outs get at ?at [ bad-vreg ] unless ;
 
-: assign-registers-in-block ( bb -- )
-    [
+:: assign-registers-in-block ( bb -- )
+    bb [
         [
+            bb begin-block
             [
-                [
-                    insn#>>
-                    [ expire-old-intervals ]
-                    [ activate-new-intervals ]
-                    bi
-                ]
-                [ assign-registers-in-insn ]
-                [ , ]
-                tri
+                {
+                    [ insn#>> 1 - prepare-insn ]
+                    [ insn#>> prepare-insn ]
+                    [ assign-registers-in-insn ]
+                    [ , ]
+                } cleave
             ] each
+            bb end-block
         ] V{ } make
     ] change-instructions drop ;
 
index be3fb2bea8fde22de2ec00dca80b9bc9fc6b789c..a350ee5f43b5b42a542673a00bbe52e94042c4fd 100644 (file)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors kernel sequences sets arrays math strings fry
 namespaces prettyprint compiler.cfg.linear-scan.live-intervals
-compiler.cfg.linear-scan.allocation compiler.cfg ;
+compiler.cfg.linear-scan.allocation compiler.cfg assocs ;
 IN: compiler.cfg.linear-scan.debugger
 
 : check-assigned ( live-intervals -- )
@@ -19,7 +19,10 @@ IN: compiler.cfg.linear-scan.debugger
     ] [ 1array ] if ;
 
 : check-linear-scan ( live-intervals machine-registers -- )
-    [ [ clone ] map ] dip allocate-registers
+    [
+        [ clone ] map dup [ [ vreg>> ] keep ] H{ } map>assoc
+        live-intervals set
+    ] dip allocate-registers
     [ split-children ] map concat check-assigned ;
 
 : picture ( uses -- str )
index 5d11e2a5a0829a8a2ca2e7c1c9e43d80d82856a1..b5999838ca63e95c8408f7d52e504463f4d74a0b 100644 (file)
@@ -1,7 +1,7 @@
 IN: compiler.cfg.linear-scan.tests
 USING: tools.test random sorting sequences sets hashtables assocs
 kernel fry arrays splitting namespaces math accessors vectors locals
-math.order grouping
+math.order grouping strings strings.private
 cpu.architecture
 compiler.cfg
 compiler.cfg.optimizer
@@ -13,6 +13,7 @@ compiler.cfg.rpo
 compiler.cfg.linearization
 compiler.cfg.debugger
 compiler.cfg.linear-scan
+compiler.cfg.linear-scan.numbering
 compiler.cfg.linear-scan.live-intervals
 compiler.cfg.linear-scan.allocation
 compiler.cfg.linear-scan.allocation.state
@@ -24,6 +25,7 @@ FROM: compiler.cfg.linear-scan.assignment => check-assignment? ;
 
 check-allocation? on
 check-assignment? on
+check-numbering? on
 
 [
     { T{ live-range f 1 10 } T{ live-range f 15 15 } }
@@ -76,36 +78,6 @@ check-assignment? on
     { T{ live-range f 0 5 } } 0 split-ranges
 ] unit-test
 
-[ 7 ] [
-    T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 2 } } }
-        { start 0 }
-        { end 10 }
-        { uses V{ 0 1 3 7 10 } }
-    }
-    4 [ >= ] find-use
-] unit-test
-
-[ 4 ] [
-    T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 2 } } }
-        { start 0 }
-        { end 10 }
-        { uses V{ 0 1 3 4 10 } }
-    }
-    4 [ >= ] find-use
-] unit-test
-
-[ f ] [
-    T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 2 } } }
-        { start 0 }
-        { end 10 }
-        { uses V{ 0 1 3 4 10 } }
-    }
-    100 [ >= ] find-use
-] unit-test
-
 [
     T{ live-interval
        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
@@ -156,6 +128,31 @@ check-assignment? on
     } 0 split-for-spill [ f >>split-next ] bi@
 ] unit-test
 
+[
+    T{ live-interval
+       { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+       { start 0 }
+       { end 0 }
+       { uses V{ 0 } }
+       { ranges V{ T{ live-range f 0 0 } } }
+    }
+    T{ live-interval
+       { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+       { start 20 }
+       { end 30 }
+       { uses V{ 20 30 } }
+       { ranges V{ T{ live-range f 20 30 } } }
+    }
+] [
+    T{ live-interval
+       { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+       { 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 } } }
@@ -184,86 +181,130 @@ check-assignment? on
 [
     T{ live-interval
         { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-        { start 3 }
-        { end 10 }
-        { uses V{ 3 10 } }
-    }
-] [
-    {
-        T{ live-interval
-            { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-            { start 1 }
-            { end 15 }
-            { uses V{ 1 3 7 10 15 } }
-        }
-        T{ live-interval
-            { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-            { start 3 }
-            { end 8 }
-            { uses V{ 3 4 8 } }
-        }
-        T{ live-interval
-            { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-            { start 3 }
-            { end 10 }
-            { uses V{ 3 10 } }
-        }
+        { 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 5 }
-        { uses V{ 5 } }
+        { end 10 }
+        { uses V{ 5 10 } }
+        { ranges V{ T{ live-range f 5 10 } } }
     }
-    interval-to-spill
+] [
+    T{ live-interval
+       { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+       { start 0 }
+       { end 10 }
+       { uses V{ 0 1 10 } }
+       { ranges V{ T{ live-range f 0 10 } } }
+    } 5 split-before-use [ f >>split-next ] bi@
 ] unit-test
 
-[ t ] [
+[
     T{ live-interval
         { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-        { start 5 }
-        { end 15 }
-        { uses V{ 5 10 15 } }
+        { 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 1 }
-        { end 20 }
-        { uses V{ 1 20 } }
+        { start 5 }
+        { end 10 }
+        { uses V{ 5 10 } }
+        { ranges V{ T{ live-range f 5 10 } } }
     }
-    spill-existing?
+] [
+    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 } } }
+    } 5 split-before-use [ f >>split-next ] bi@
 ] unit-test
 
-[ f ] [
-    T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-        { start 5 }
-        { end 15 }
-        { uses V{ 5 10 15 } }
+[
+    {
+        3
+        10
     }
+] [
+    H{
+        { int-regs
+          V{
+              T{ live-interval
+                 { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+                 { reg 1 }
+                 { start 1 }
+                 { end 15 }
+                 { uses V{ 1 3 7 10 15 } }
+              }
+              T{ live-interval
+                 { vreg T{ vreg { reg-class int-regs } { n 2 } } }
+                 { reg 2 }
+                 { start 3 }
+                 { end 8 }
+                 { uses V{ 3 4 8 } }
+              }
+              T{ live-interval
+                 { vreg T{ vreg { reg-class int-regs } { n 3 } } }
+                 { reg 3 }
+                 { start 3 }
+                 { end 10 }
+                 { uses V{ 3 10 } }
+              }
+          }
+        }
+    } active-intervals set
+    H{ } inactive-intervals set
     T{ live-interval
         { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-        { start 1 }
-        { end 20 }
-        { uses V{ 1 7 20 } }
+        { start 5 }
+        { end 5 }
+        { uses V{ 5 } }
     }
-    spill-existing?
+    spill-status
 ] unit-test
 
-[ t ] [
+[
+    {
+        1
+        1/0.
+    }
+] [
+    H{
+        { int-regs
+          V{
+              T{ live-interval
+                 { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+                 { reg 1 }
+                 { start 1 }
+                 { end 15 }
+                 { uses V{ 1 } }
+              }
+              T{ live-interval
+                 { vreg T{ vreg { reg-class int-regs } { n 2 } } }
+                 { reg 2 }
+                 { start 3 }
+                 { end 8 }
+                 { uses V{ 3 8 } }
+              }
+          }
+        }
+    } active-intervals set
+    H{ } inactive-intervals set
     T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
+        { vreg T{ vreg { reg-class int-regs } { n 3 } } }
         { start 5 }
         { end 5 }
         { uses V{ 5 } }
     }
-    T{ live-interval
-        { vreg T{ vreg { reg-class int-regs } { n 1 } } }
-        { start 1 }
-        { end 20 }
-        { uses V{ 1 7 20 } }
-    }
-    spill-existing?
+    spill-status
 ] unit-test
 
 [ ] [
@@ -1328,7 +1369,7 @@ USING: math.private ;
 
 ! Spill slot liveness was computed incorrectly, leading to a FEP
 ! early in bootstrap on x86-32
-[ t ] [
+[ t ] [
     [
         H{ } clone live-ins set
         H{ } clone live-outs set
@@ -1354,8 +1395,7 @@ USING: math.private ;
            }
         } dup 1array { { int-regs V{ 0 1 2 3 } } } (linear-scan)
         instructions>> first
-        [ live-spill-slots>> empty? ]
-        [ live-registers>> empty? ] bi
+        live-values>> assoc-empty?
     ] with-scope
 ] unit-test
 
@@ -1403,6 +1443,20 @@ USING: math.private ;
     intersect-live-ranges
 ] unit-test
 
+[ f ] [
+    {
+        T{ live-range f 0 10 }
+        T{ live-range f 20 30 }
+        T{ live-range f 40 50 }
+    }
+    {
+        T{ live-range f 11 15 }
+        T{ live-range f 31 36 }
+        T{ live-range f 51 55 }
+    }
+    intersect-live-ranges
+] unit-test
+
 [ 5 ] [
     T{ live-interval
        { start 0 }
@@ -1419,7 +1473,7 @@ USING: math.private ;
     relevant-ranges intersect-live-ranges
 ] unit-test
 
-! compute-free-pos had problems because it used map>assoc where the sequence
+! register-status had problems because it used map>assoc where the sequence
 ! had multiple keys
 [ { 0 10 } ] [
     H{ { int-regs { 0 1 } } } registers set
@@ -1468,7 +1522,7 @@ USING: math.private ;
         { ranges V{ T{ live-range f 8 10 } } }
         { uses V{ 8 10 } }
     }
-    compute-free-pos
+    register-status
 ] unit-test
 
 ! Bug in live spill slots calculation
@@ -1531,18 +1585,18 @@ V{
 SYMBOL: linear-scan-result
 
 :: test-linear-scan-on-cfg ( regs -- )
-    [ ] [
+    [
         cfg new 0 get >>entry
         compute-predecessors
         compute-liveness
         dup reverse-post-order
         { { int-regs regs } } (linear-scan)
         flatten-cfg 1array mr.
-    ] unit-test ;
+    ] with-scope ;
 
 ! This test has a critical edge -- do we care about these?
 
-! { 1 2 } test-linear-scan-on-cfg
+! [ { 1 2 } test-linear-scan-on-cfg ] unit-test
 
 ! Bug in inactive interval handling
 ! [ rot dup [ -rot ] when ]
@@ -1619,7 +1673,7 @@ V{
 
 test-diamond
 
-{ 1 2 3 4 } test-linear-scan-on-cfg
+[ ] [ { 1 2 3 4 } test-linear-scan-on-cfg ] unit-test
 
 ! Similar to the above
 ! [ swap dup [ rot ] when ]
@@ -1705,7 +1759,7 @@ V{
 
 test-diamond
 
-{ 1 2 3 4 } test-linear-scan-on-cfg
+[ ] [ { 1 2 3 4 } test-linear-scan-on-cfg ] unit-test
 
 ! compute-live-registers was inaccurate since it didn't take
 ! lifetime holes into account
@@ -1758,7 +1812,7 @@ V{
 
 test-diamond
 
-{ 1 2 3 4 } test-linear-scan-on-cfg
+[ ] [ { 1 2 3 4 } test-linear-scan-on-cfg ] unit-test
 
 ! Inactive interval handling: splitting active interval
 ! if it fits in lifetime hole only partially
@@ -1791,7 +1845,7 @@ V{
 
 test-diamond
 
-{ 1 2 } test-linear-scan-on-cfg
+[ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
 
 USING: classes ;
 
 
 test-diamond
 
-{ 1 2 } test-linear-scan-on-cfg
+[ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
 
 [ _spill ] [ 2 get instructions>> first class ] unit-test
 
 [ _spill ] [ 3 get instructions>> second class ] unit-test
 
-[ _reload ] [ 4 get instructions>> first class ] unit-test
\ No newline at end of file
+[ f ] [ 3 get instructions>> [ _reload? ] any? ] unit-test
+
+[ _reload ] [ 4 get instructions>> first class ] unit-test
+
+! Resolve pass
+V{
+    T{ ##branch }
+} 0 test-bb
+
+V{
+    T{ ##peek f V int-regs 0 D 0 }
+    T{ ##compare-imm-branch f V int-regs 0 5 cc= }
+} 1 test-bb
+
+V{
+    T{ ##replace 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 }
+    T{ ##replace f V int-regs 1 D 0 }
+    T{ ##replace f V int-regs 2 D 0 }
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##branch }
+} 3 test-bb
+
+V{
+    T{ ##peek f V int-regs 1 D 0 }
+    T{ ##compare-imm-branch f V int-regs 1 5 cc= }
+} 4 test-bb
+
+V{
+    T{ ##replace f V int-regs 0 D 0 }
+    T{ ##return }
+} 5 test-bb
+
+V{
+    T{ ##replace f V int-regs 0 D 0 }
+    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
+
+[ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
+
+[ t ] [ 2 get instructions>> [ _spill? ] any? ] unit-test
+
+[ t ] [ 3 get instructions>> [ _spill? ] any? ] unit-test
+
+[ t ] [ 5 get instructions>> [ _reload? ] any? ] unit-test
+
+! A more complicated failure case with resolve that came up after the above
+! got fixed
+V{ T{ ##branch } } 0 test-bb
+V{
+    T{ ##peek f V int-regs 0 D 0 }
+    T{ ##peek f V int-regs 1 D 1 }
+    T{ ##peek f V int-regs 2 D 2 }
+    T{ ##peek f V int-regs 3 D 3 }
+    T{ ##peek f V int-regs 4 D 0 }
+    T{ ##branch }
+} 1 test-bb
+V{ T{ ##branch } } 2 test-bb
+V{ T{ ##branch } } 3 test-bb
+V{
+    
+    T{ ##replace f V int-regs 1 D 1 }
+    T{ ##replace f V int-regs 2 D 2 }
+    T{ ##replace f V int-regs 3 D 3 }
+    T{ ##replace f V int-regs 4 D 4 }
+    T{ ##replace f V int-regs 0 D 0 }
+    T{ ##branch }
+} 4 test-bb
+V{ T{ ##replace f V int-regs 0 D 0 } T{ ##branch } } 5 test-bb
+V{ T{ ##return } } 6 test-bb
+V{ T{ ##branch } } 7 test-bb
+V{
+    T{ ##replace f V int-regs 1 D 1 }
+    T{ ##replace f V int-regs 2 D 2 }
+    T{ ##replace f V int-regs 3 D 3 }
+    T{ ##peek f V int-regs 5 D 1 }
+    T{ ##peek f V int-regs 6 D 2 }
+    T{ ##peek f V int-regs 7 D 3 }
+    T{ ##peek f V int-regs 8 D 4 }
+    T{ ##replace f V int-regs 5 D 1 }
+    T{ ##replace f V int-regs 6 D 2 }
+    T{ ##replace f V int-regs 7 D 3 }
+    T{ ##replace f V int-regs 8 D 4 }
+    T{ ##branch }
+} 8 test-bb
+V{
+    T{ ##replace f V int-regs 1 D 1 }
+    T{ ##replace f V int-regs 2 D 2 }
+    T{ ##replace f V int-regs 3 D 3 }
+    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
+
+[ ] [ { 1 2 3 4 } test-linear-scan-on-cfg ] unit-test
+
+[ _spill ] [ 1 get instructions>> second class ] unit-test
+[ _reload ] [ 4 get instructions>> 4 swap nth class ] unit-test
+[ V{ 3 2 1 } ] [ 8 get instructions>> [ _spill? ] filter [ n>> ] map ] unit-test
+[ V{ 3 2 1 } ] [ 9 get instructions>> [ _reload? ] filter [ n>> ] map ] unit-test
+
+! Resolve pass should insert this
+[ _reload ] [ 5 get instructions>> first class ] unit-test
+
+! Some random bug
+V{
+    T{ ##peek f V int-regs 1 D 1 }
+    T{ ##peek f V int-regs 2 D 2 }
+    T{ ##replace f V int-regs 1 D 1 }
+    T{ ##replace f V int-regs 2 D 2 }
+    T{ ##peek f V int-regs 3 D 0 }
+    T{ ##peek f V int-regs 0 D 0 }
+    T{ ##branch }
+} 0 test-bb
+
+V{ T{ ##branch } } 1 test-bb
+
+V{
+    T{ ##peek f V int-regs 1 D 1 }
+    T{ ##peek f V int-regs 2 D 2 }
+    T{ ##replace f V int-regs 3 D 3 }
+    T{ ##replace f V int-regs 1 D 1 }
+    T{ ##replace f V int-regs 2 D 2 }
+    T{ ##replace f V int-regs 0 D 3 }
+    T{ ##branch }
+} 2 test-bb
+
+V{ T{ ##branch } } 3 test-bb
+
+V{
+    T{ ##return }
+} 4 test-bb
+
+test-diamond
+
+[ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
+
+! Spilling an interval immediately after its activated;
+! and the interval does not have a use at the activation point
+V{
+    T{ ##peek f V int-regs 1 D 1 }
+    T{ ##peek f V int-regs 2 D 2 }
+    T{ ##replace f V int-regs 1 D 1 }
+    T{ ##replace f V int-regs 2 D 2 }
+    T{ ##peek f V int-regs 0 D 0 }
+    T{ ##branch }
+} 0 test-bb
+
+V{ T{ ##branch } } 1 test-bb
+
+V{
+    T{ ##peek f V int-regs 1 D 1 }
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##replace f V int-regs 1 D 1 }
+    T{ ##peek f V int-regs 2 D 2 }
+    T{ ##replace f V int-regs 2 D 2 }
+    T{ ##branch }
+} 3 test-bb
+
+V{ T{ ##branch } } 4 test-bb
+
+V{
+    T{ ##replace f V int-regs 0 D 0 }
+    T{ ##return }
+} 5 test-bb
+
+1 get 1vector 0 get (>>successors)
+2 get 4 get V{ } 2sequence 1 get (>>successors)
+5 get 1vector 4 get (>>successors)
+3 get 1vector 2 get (>>successors)
+5 get 1vector 3 get (>>successors)
+
+[ ] [ { 1 2 } test-linear-scan-on-cfg ] unit-test
+
+! Reduction of push-all regression, x86-32
+V{ T{ ##prologue } T{ ##branch } } 0 test-bb
+
+V{
+    T{ ##load-immediate { dst V int-regs 61 } }
+    T{ ##peek { dst V int-regs 62 } { loc D 0 } }
+    T{ ##peek { dst V int-regs 64 } { loc D 1 } }
+    T{ ##slot-imm
+        { dst V int-regs 69 }
+        { obj V int-regs 64 }
+        { slot 1 }
+        { tag 2 }
+    }
+    T{ ##copy { dst V int-regs 79 } { src V int-regs 69 } }
+    T{ ##slot-imm
+        { dst V int-regs 85 }
+        { obj V int-regs 62 }
+        { slot 2 }
+        { tag 7 }
+    }
+    T{ ##compare-branch
+        { src1 V int-regs 69 }
+        { src2 V int-regs 85 }
+        { cc cc> }
+    }
+} 1 test-bb
+
+V{
+    T{ ##slot-imm
+        { dst V int-regs 97 }
+        { obj V int-regs 62 }
+        { slot 2 }
+        { tag 7 }
+    }
+    T{ ##replace { src V int-regs 79 } { loc D 3 } }
+    T{ ##replace { src V int-regs 62 } { loc D 4 } }
+    T{ ##replace { src V int-regs 79 } { loc D 1 } }
+    T{ ##replace { src V int-regs 62 } { loc D 2 } }
+    T{ ##replace { src V int-regs 61 } { loc D 5 } }
+    T{ ##replace { src V int-regs 62 } { loc R 0 } }
+    T{ ##replace { src V int-regs 69 } { loc R 1 } }
+    T{ ##replace { src V int-regs 97 } { loc D 0 } }
+    T{ ##call { word resize-array } }
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##peek { dst V int-regs 98 } { loc R 0 } }
+    T{ ##peek { dst V int-regs 100 } { loc D 0 } }
+    T{ ##set-slot-imm
+        { src V int-regs 100 }
+        { obj V int-regs 98 }
+        { slot 2 }
+        { tag 7 }
+    }
+    T{ ##peek { dst V int-regs 108 } { loc D 2 } }
+    T{ ##peek { dst V int-regs 110 } { loc D 3 } }
+    T{ ##peek { dst V int-regs 112 } { loc D 0 } }
+    T{ ##peek { dst V int-regs 114 } { loc D 1 } }
+    T{ ##peek { dst V int-regs 116 } { loc D 4 } }
+    T{ ##peek { dst V int-regs 119 } { loc R 0 } }
+    T{ ##copy { dst V int-regs 109 } { src V int-regs 108 } }
+    T{ ##copy { dst V int-regs 111 } { src V int-regs 110 } }
+    T{ ##copy { dst V int-regs 113 } { src V int-regs 112 } }
+    T{ ##copy { dst V int-regs 115 } { src V int-regs 114 } }
+    T{ ##copy { dst V int-regs 117 } { src V int-regs 116 } }
+    T{ ##copy { dst V int-regs 120 } { src V int-regs 119 } }
+    T{ ##branch }
+} 3 test-bb
+
+V{
+    T{ ##copy { dst V int-regs 109 } { src V int-regs 62 } }
+    T{ ##copy { dst V int-regs 111 } { src V int-regs 61 } }
+    T{ ##copy { dst V int-regs 113 } { src V int-regs 62 } }
+    T{ ##copy { dst V int-regs 115 } { src V int-regs 79 } }
+    T{ ##copy { dst V int-regs 117 } { src V int-regs 64 } }
+    T{ ##copy { dst V int-regs 120 } { src V int-regs 69 } }
+    T{ ##branch }
+} 4 test-bb
+
+V{
+    T{ ##replace { src V int-regs 120 } { loc D 0 } }
+    T{ ##replace { src V int-regs 109 } { loc D 3 } }
+    T{ ##replace { src V int-regs 111 } { loc D 4 } }
+    T{ ##replace { src V int-regs 113 } { loc D 1 } }
+    T{ ##replace { src V int-regs 115 } { loc D 2 } }
+    T{ ##replace { src V int-regs 117 } { loc D 5 } }
+    T{ ##epilogue }
+    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
+
+[ ] [ { 1 2 3 4 5 } test-linear-scan-on-cfg ] unit-test
+
+! Another reduction of push-all
+V{ T{ ##prologue } T{ ##branch } } 0 test-bb
+
+V{
+    T{ ##peek { dst V int-regs 85 } { loc D 0 } }
+    T{ ##slot-imm
+        { dst V int-regs 89 }
+        { obj V int-regs 85 }
+        { slot 3 }
+        { tag 7 }
+    }
+    T{ ##peek { dst V int-regs 91 } { loc D 1 } }
+    T{ ##slot-imm
+        { dst V int-regs 96 }
+        { obj V int-regs 91 }
+        { slot 1 }
+        { tag 2 }
+    }
+    T{ ##add
+        { dst V int-regs 109 }
+        { src1 V int-regs 89 }
+        { src2 V int-regs 96 }
+    }
+    T{ ##slot-imm
+        { dst V int-regs 115 }
+        { obj V int-regs 85 }
+        { slot 2 }
+        { tag 7 }
+    }
+    T{ ##slot-imm
+        { dst V int-regs 118 }
+        { obj V int-regs 115 }
+        { slot 1 }
+        { tag 2 }
+    }
+    T{ ##compare-branch
+        { src1 V int-regs 109 }
+        { src2 V int-regs 118 }
+        { cc cc> }
+    }
+} 1 test-bb
+
+V{
+    T{ ##add-imm
+        { dst V int-regs 128 }
+        { src1 V int-regs 109 }
+        { src2 8 }
+    }
+    T{ ##load-immediate { dst V int-regs 129 } { val 24 } }
+    T{ ##inc-d { n 4 } }
+    T{ ##inc-r { n 1 } }
+    T{ ##replace { src V int-regs 109 } { loc D 2 } }
+    T{ ##replace { src V int-regs 85 } { loc D 3 } }
+    T{ ##replace { src V int-regs 128 } { loc D 0 } }
+    T{ ##replace { src V int-regs 85 } { loc D 1 } }
+    T{ ##replace { src V int-regs 89 } { loc D 4 } }
+    T{ ##replace { src V int-regs 96 } { loc R 0 } }
+    T{ ##fixnum-mul
+        { src1 V int-regs 128 }
+        { src2 V int-regs 129 }
+        { temp1 V int-regs 132 }
+        { temp2 V int-regs 133 }
+    }
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##peek { dst V int-regs 134 } { loc D 1 } }
+    T{ ##slot-imm
+        { dst V int-regs 140 }
+        { obj V int-regs 134 }
+        { slot 2 }
+        { tag 7 }
+    }
+    T{ ##inc-d { n 1 } }
+    T{ ##inc-r { n 1 } }
+    T{ ##replace { src V int-regs 140 } { loc D 0 } }
+    T{ ##replace { src V int-regs 134 } { loc R 0 } }
+    T{ ##call { word resize-array } }
+    T{ ##branch }
+} 3 test-bb
+
+V{
+    T{ ##peek { dst V int-regs 141 } { loc R 0 } }
+    T{ ##peek { dst V int-regs 143 } { loc D 0 } }
+    T{ ##set-slot-imm
+        { src V int-regs 143 }
+        { obj V int-regs 141 }
+        { slot 2 }
+        { tag 7 }
+    }
+    T{ ##write-barrier
+        { src V int-regs 141 }
+        { card# V int-regs 145 }
+        { table V int-regs 146 }
+    }
+    T{ ##inc-d { n -1 } }
+    T{ ##inc-r { n -1 } }
+    T{ ##peek { dst V int-regs 156 } { loc D 2 } }
+    T{ ##peek { dst V int-regs 158 } { loc D 3 } }
+    T{ ##peek { dst V int-regs 160 } { loc D 0 } }
+    T{ ##peek { dst V int-regs 162 } { loc D 1 } }
+    T{ ##peek { dst V int-regs 164 } { loc D 4 } }
+    T{ ##peek { dst V int-regs 167 } { loc R 0 } }
+    T{ ##copy { dst V int-regs 157 } { src V int-regs 156 } }
+    T{ ##copy { dst V int-regs 159 } { src V int-regs 158 } }
+    T{ ##copy { dst V int-regs 161 } { src V int-regs 160 } }
+    T{ ##copy { dst V int-regs 163 } { src V int-regs 162 } }
+    T{ ##copy { dst V int-regs 165 } { src V int-regs 164 } }
+    T{ ##copy { dst V int-regs 168 } { src V int-regs 167 } }
+    T{ ##branch }
+} 4 test-bb
+
+V{
+    T{ ##inc-d { n 3 } }
+    T{ ##inc-r { n 1 } }
+    T{ ##copy { dst V int-regs 157 } { src V int-regs 85 } }
+    T{ ##copy { dst V int-regs 159 } { src V int-regs 89 } }
+    T{ ##copy { dst V int-regs 161 } { src V int-regs 85 } }
+    T{ ##copy { dst V int-regs 163 } { src V int-regs 109 } }
+    T{ ##copy { dst V int-regs 165 } { src V int-regs 91 } }
+    T{ ##copy { dst V int-regs 168 } { src V int-regs 96 } }
+    T{ ##branch }
+} 5 test-bb
+
+V{
+    T{ ##set-slot-imm
+        { src V int-regs 163 }
+        { obj V int-regs 161 }
+        { slot 3 }
+        { tag 7 }
+    }
+    T{ ##inc-d { n 1 } }
+    T{ ##inc-r { n -1 } }
+    T{ ##replace { src V int-regs 168 } { loc D 0 } }
+    T{ ##replace { src V int-regs 157 } { loc D 3 } }
+    T{ ##replace { src V int-regs 159 } { loc D 4 } }
+    T{ ##replace { src V int-regs 161 } { loc D 1 } }
+    T{ ##replace { src V int-regs 163 } { loc D 2 } }
+    T{ ##replace { src V int-regs 165 } { loc D 5 } }
+    T{ ##epilogue }
+    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
+
+[ ] [ { 1 2 3 4 5 } test-linear-scan-on-cfg ] unit-test
+
+! Another push-all reduction to demonstrate numbering anamoly
+V{ T{ ##prologue } T{ ##branch } }
+0 test-bb
+
+V{
+    T{ ##peek { dst V int-regs 1 } { loc D 0 } }
+    T{ ##slot-imm
+        { dst V int-regs 5 }
+        { obj V int-regs 1 }
+        { slot 3 }
+        { tag 7 }
+    }
+    T{ ##peek { dst V int-regs 7 } { loc D 1 } }
+    T{ ##slot-imm
+        { dst V int-regs 12 }
+        { obj V int-regs 7 }
+        { slot 1 }
+        { tag 6 }
+    }
+    T{ ##add
+        { dst V int-regs 25 }
+        { src1 V int-regs 5 }
+        { src2 V int-regs 12 }
+    }
+    T{ ##compare-branch
+        { src1 V int-regs 25 }
+        { src2 V int-regs 5 }
+        { cc cc> }
+    }
+}
+1 test-bb
+
+V{
+    T{ ##slot-imm
+        { dst V int-regs 41 }
+        { obj V int-regs 1 }
+        { slot 2 }
+        { tag 7 }
+    }
+    T{ ##slot-imm
+        { dst V int-regs 44 }
+        { obj V int-regs 41 }
+        { slot 1 }
+        { tag 6 }
+    }
+    T{ ##compare-branch
+        { src1 V int-regs 25 }
+        { src2 V int-regs 44 }
+        { cc cc> }
+    }
+}
+2 test-bb
+
+V{
+    T{ ##add-imm
+        { dst V int-regs 54 }
+        { src1 V int-regs 25 }
+        { src2 8 }
+    }
+    T{ ##load-immediate { dst V int-regs 55 } { val 24 } }
+    T{ ##inc-d { n 4 } }
+    T{ ##inc-r { n 1 } }
+    T{ ##replace { src V int-regs 25 } { loc D 2 } }
+    T{ ##replace { src V int-regs 1 } { loc D 3 } }
+    T{ ##replace { src V int-regs 5 } { loc D 4 } }
+    T{ ##replace { src V int-regs 1 } { loc D 1 } }
+    T{ ##replace { src V int-regs 54 } { loc D 0 } }
+    T{ ##replace { src V int-regs 12 } { loc R 0 } }
+    T{ ##fixnum-mul
+        { src1 V int-regs 54 }
+        { src2 V int-regs 55 }
+        { temp1 V int-regs 58 }
+        { temp2 V int-regs 59 }
+    }
+    T{ ##branch }
+}
+3 test-bb
+
+V{
+    T{ ##peek { dst V int-regs 60 } { loc D 1 } }
+    T{ ##slot-imm
+        { dst V int-regs 66 }
+        { obj V int-regs 60 }
+        { slot 2 }
+        { tag 7 }
+    }
+    T{ ##inc-d { n 1 } }
+    T{ ##inc-r { n 1 } }
+    T{ ##replace { src V int-regs 66 } { loc D 0 } }
+    T{ ##replace { src V int-regs 60 } { loc R 0 } }
+    T{ ##call { word resize-string } }
+    T{ ##branch }
+}
+4 test-bb
+
+V{
+    T{ ##peek { dst V int-regs 67 } { loc R 0 } }
+    T{ ##peek { dst V int-regs 68 } { loc D 0 } }
+    T{ ##set-slot-imm
+        { src V int-regs 68 }
+        { obj V int-regs 67 }
+        { slot 2 }
+        { tag 7 }
+    }
+    T{ ##write-barrier
+        { src V int-regs 67 }
+        { card# V int-regs 75 }
+        { table V int-regs 76 }
+    }
+    T{ ##inc-d { n -1 } }
+    T{ ##inc-r { n -1 } }
+    T{ ##peek { dst V int-regs 94 } { loc D 0 } }
+    T{ ##peek { dst V int-regs 96 } { loc D 1 } }
+    T{ ##peek { dst V int-regs 98 } { loc D 2 } }
+    T{ ##peek { dst V int-regs 100 } { loc D 3 } }
+    T{ ##peek { dst V int-regs 102 } { loc D 4 } }
+    T{ ##peek { dst V int-regs 106 } { loc R 0 } }
+    T{ ##copy { dst V int-regs 95 } { src V int-regs 94 } }
+    T{ ##copy { dst V int-regs 97 } { src V int-regs 96 } }
+    T{ ##copy { dst V int-regs 99 } { src V int-regs 98 } }
+    T{ ##copy { dst V int-regs 101 } { src V int-regs 100 } }
+    T{ ##copy { dst V int-regs 103 } { src V int-regs 102 } }
+    T{ ##copy { dst V int-regs 107 } { src V int-regs 106 } }
+    T{ ##branch }
+}
+5 test-bb
+
+V{
+    T{ ##inc-d { n 3 } }
+    T{ ##inc-r { n 1 } }
+    T{ ##copy { dst V int-regs 95 } { src V int-regs 1 } }
+    T{ ##copy { dst V int-regs 97 } { src V int-regs 25 } }
+    T{ ##copy { dst V int-regs 99 } { src V int-regs 1 } }
+    T{ ##copy { dst V int-regs 101 } { src V int-regs 5 } }
+    T{ ##copy { dst V int-regs 103 } { src V int-regs 7 } }
+    T{ ##copy { dst V int-regs 107 } { src V int-regs 12 } }
+    T{ ##branch }
+}
+6 test-bb
+
+V{
+    T{ ##load-immediate
+        { dst V int-regs 78 }
+        { val 4611686018427387896 }
+    }
+    T{ ##and
+        { dst V int-regs 81 }
+        { src1 V int-regs 97 }
+        { src2 V int-regs 78 }
+    }
+    T{ ##set-slot-imm
+        { src V int-regs 81 }
+        { obj V int-regs 95 }
+        { slot 3 }
+        { tag 7 }
+    }
+    T{ ##inc-d { n -2 } }
+    T{ ##copy { dst V int-regs 110 } { src V int-regs 99 } }
+    T{ ##copy { dst V int-regs 111 } { src V int-regs 101 } }
+    T{ ##copy { dst V int-regs 112 } { src V int-regs 103 } }
+    T{ ##copy { dst V int-regs 117 } { src V int-regs 107 } }
+    T{ ##branch }
+}
+7 test-bb
+
+V{
+    T{ ##inc-d { n 1 } }
+    T{ ##inc-r { n 1 } }
+    T{ ##copy { dst V int-regs 110 } { src V int-regs 1 } }
+    T{ ##copy { dst V int-regs 111 } { src V int-regs 5 } }
+    T{ ##copy { dst V int-regs 112 } { src V int-regs 7 } }
+    T{ ##copy { dst V int-regs 117 } { src V int-regs 12 } }
+    T{ ##branch }
+}
+8 test-bb
+
+V{
+    T{ ##inc-d { n 1 } }
+    T{ ##inc-r { n -1 } }
+    T{ ##replace { src V int-regs 117 } { loc D 0 } }
+    T{ ##replace { src V int-regs 110 } { loc D 1 } }
+    T{ ##replace { src V int-regs 111 } { loc D 2 } }
+    T{ ##replace { src V int-regs 112 } { loc D 3 } }
+    T{ ##epilogue }
+    T{ ##return }
+}
+9 test-bb
+
+0 get 1 get 1vector >>successors drop
+1 get 2 get 8 get V{ } 2sequence >>successors drop
+2 get 3 get 6 get V{ } 2sequence >>successors drop
+3 get 4 get 1vector >>successors drop
+4 get 5 get 1vector >>successors drop
+5 get 7 get 1vector >>successors drop
+6 get 7 get 1vector >>successors drop
+7 get 9 get 1vector >>successors drop
+8 get 9 get 1vector >>successors drop
+
+[ ] [ { 1 2 3 4 5 } test-linear-scan-on-cfg ] unit-test
\ No newline at end of file
index 2d3ad41b223f31c375a054ef84eef5047e2e6e49..9013389cc9ddfffc986f1701958aea77c6922207 100644 (file)
@@ -31,7 +31,8 @@ IN: compiler.cfg.linear-scan
     rpo number-instructions
     rpo compute-live-intervals machine-registers allocate-registers
     rpo assign-registers
-    rpo resolve-data-flow ;
+    rpo resolve-data-flow
+    rpo check-numbering ;
 
 : linear-scan ( cfg -- cfg' )
     [
index c67a7bb021b6b5b9a56224ecc4f13af9cde439d9..bf7e8bc042e9882333cc0418215663745b4ffb99 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: namespaces kernel assocs accessors sequences math math.order fry
-binary-search combinators compiler.cfg.instructions compiler.cfg.registers
+combinators compiler.cfg.instructions compiler.cfg.registers
 compiler.cfg.def-use compiler.cfg.liveness compiler.cfg ;
 IN: compiler.cfg.linear-scan.live-intervals
 
@@ -57,7 +57,7 @@ ERROR: dead-value-error vreg ;
         V{ } clone >>ranges
         swap >>vreg ;
 
-: block-from ( bb -- n ) instructions>> first insn#>> ;
+: block-from ( bb -- n ) instructions>> first insn#>> 1 - ;
 
 : block-to ( bb -- n ) instructions>> last insn#>> ;
 
@@ -145,8 +145,7 @@ M: ##copy-float compute-live-intervals*
         <reversed> [ compute-live-intervals-step ] each
     ] keep values dup finish-live-intervals ;
 
-: relevant-ranges ( new inactive -- new' inactive' )
-    ! Slice off all ranges of 'inactive' that precede the start of 'new'
+: relevant-ranges ( interval1 interval2 -- ranges1 ranges2 )
     [ [ ranges>> ] bi@ ] [ nip start>> ] 2bi '[ to>> _ >= ] filter ;
 
 : intersect-live-range ( range1 range2 -- n/f )
@@ -155,8 +154,8 @@ M: ##copy-float compute-live-intervals*
 
 : intersect-live-ranges ( ranges1 ranges2 -- n )
     {
-        { [ over empty? ] [ 2drop 1/0. ] }
-        { [ dup empty? ] [ 2drop 1/0. ] }
+        { [ over empty? ] [ 2drop f ] }
+        { [ dup empty? ] [ 2drop f ] }
         [
             2dup [ first ] bi@ intersect-live-range dup [ 2nip ] [
                 drop
@@ -166,3 +165,6 @@ M: ##copy-float compute-live-intervals*
             ] if
         ]
     } cond ;
+
+: intervals-intersect? ( interval1 interval2 -- ? )
+    relevant-ranges intersect-live-ranges >boolean ; inline
\ No newline at end of file
index 6734f6a3596c447dc1854218631a13f768b71127..ac18b0cb2ec5b5317f44c32b94085688cdb85ded 100644 (file)
@@ -1,6 +1,6 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel accessors math sequences ;
+USING: kernel accessors math sequences grouping namespaces ;
 IN: compiler.cfg.linear-scan.numbering
 
 : number-instructions ( rpo -- )
@@ -8,4 +8,15 @@ IN: compiler.cfg.linear-scan.numbering
         instructions>> [
             [ (>>insn#) ] [ drop 2 + ] 2bi
         ] each
-    ] each drop ;
\ No newline at end of file
+    ] each drop ;
+
+SYMBOL: check-numbering?
+
+ERROR: bad-numbering bb ;
+
+: check-block-numbering ( bb -- )
+    dup instructions>> [ insn#>> ] map sift [ <= ] monotonic?
+    [ drop ] [ bad-numbering ] if ;
+
+: check-numbering ( rpo -- )
+    check-numbering? get [ [ check-block-numbering ] each ] [ drop ] if ;
\ No newline at end of file
index feb9ac2504fe7987ec8bcb7d57ff51c161320642..7e308cf231dc2044a41cca86f55f96d6ec2a588f 100644 (file)
@@ -3,6 +3,7 @@ compiler.cfg.debugger compiler.cfg.instructions
 compiler.cfg.linear-scan.debugger
 compiler.cfg.linear-scan.live-intervals
 compiler.cfg.linear-scan.numbering
+compiler.cfg.linear-scan.allocation.state
 compiler.cfg.linear-scan.resolve compiler.cfg.predecessors
 compiler.cfg.registers compiler.cfg.rpo cpu.architecture kernel
 namespaces tools.test vectors ;
@@ -12,68 +13,18 @@ IN: compiler.cfg.linear-scan.resolve.tests
     { 3 4 } V{ 1 2 } clone [ { 5 6 } 3append-here ] keep >array
 ] unit-test
 
-V{
-    T{ ##peek f V int-regs 0 D 0 }
-    T{ ##branch }
-} 0 test-bb
-
-V{
-    T{ ##replace f V int-regs 0 D 1 }
-    T{ ##return }
-} 1 test-bb
-
-1 get 1vector 0 get (>>successors)
-
-cfg new 0 get >>entry
-compute-predecessors
-dup reverse-post-order number-instructions
-drop
-
-CONSTANT: test-live-interval-1
-T{ live-interval
-   { start 0 }
-   { end 6 }
-   { uses V{ 0 6 } }
-   { ranges V{ T{ live-range f 0 2 } T{ live-range f 4 6 } } }
-   { spill-to 0 }
-   { vreg V int-regs 0 }
-}
-
-[ f ] [
-    0 get test-live-interval-1 spill-to
-] unit-test
-
-[ 0 ] [
-    1 get test-live-interval-1 spill-to
-] unit-test
-
-CONSTANT: test-live-interval-2
-T{ live-interval
-   { start 0 }
-   { end 6 }
-   { uses V{ 0 6 } }
-   { ranges V{ T{ live-range f 0 2 } T{ live-range f 4 6 } } }
-   { reload-from 0 }
-   { vreg V int-regs 0 }
-}
-
-[ 0 ] [
-    0 get test-live-interval-2 reload-from
-] unit-test
-
-[ f ] [
-    1 get test-live-interval-2 reload-from
-] unit-test
+H{ { int-regs 10 } { float-regs 20 } } clone spill-counts set
+H{ } clone spill-temps set
 
 [
     {
         T{ _copy { dst 5 } { src 4 } { class int-regs } }
-        T{ _spill { src 1 } { class int-regs } { n spill-temp } }
+        T{ _spill { src 1 } { class int-regs } { n 10 } }
         T{ _copy { dst 1 } { src 0 } { class int-regs } }
-        T{ _reload { dst 0 } { class int-regs } { n spill-temp } }
-        T{ _spill { src 1 } { class float-regs } { n spill-temp } }
+        T{ _reload { dst 0 } { class int-regs } { n 10 } }
+        T{ _spill { src 1 } { class float-regs } { n 20 } }
         T{ _copy { dst 1 } { src 0 } { class float-regs } }
-        T{ _reload { dst 0 } { class float-regs } { n spill-temp } }
+        T{ _reload { dst 0 } { class float-regs } { n 20 } }
     }
 ] [
     {
@@ -87,10 +38,10 @@ T{ live-interval
 
 [
     {
-        T{ _spill { src 2 } { class int-regs } { n spill-temp } }
+        T{ _spill { src 2 } { class int-regs } { n 10 } }
         T{ _copy { dst 2 } { src 1 } { class int-regs } }
         T{ _copy { dst 1 } { src 0 } { class int-regs } }
-        T{ _reload { dst 0 } { class int-regs } { n spill-temp } }
+        T{ _reload { dst 0 } { class int-regs } { n 10 } }
     }
 ] [
     {
@@ -102,10 +53,10 @@ T{ live-interval
 
 [
     {
-        T{ _spill { src 0 } { class int-regs } { n spill-temp } }
+        T{ _spill { src 0 } { class int-regs } { n 10 } }
         T{ _copy { dst 0 } { src 2 } { class int-regs } }
         T{ _copy { dst 2 } { src 1 } { class int-regs } }
-        T{ _reload { dst 1 } { class int-regs } { n spill-temp } }
+        T{ _reload { dst 1 } { class int-regs } { n 10 } }
     }
 ] [
     {
@@ -136,10 +87,14 @@ T{ live-interval
 ] unit-test
 
 [
-    { T{ _spill { src 4 } { class int-regs } { n spill-temp } } }
+    {
+        T{ _spill { src 3 } { class int-regs } { n 4 } }
+        T{ _reload { dst 2 } { class int-regs } { n 1 } } 
+    }
 ] [
     {
-       T{ register->memory { from 4 } { to 4 } { reg-class int-regs } }
+        T{ register->memory { from 3 } { to T{ spill-slot f 4 } } { reg-class int-regs } }
+        T{ memory->register { from T{ spill-slot f 1 } } { to 2 } { reg-class int-regs } }
     } mapping-instructions
 ] unit-test
 
@@ -162,10 +117,10 @@ T{ live-interval
     {
         T{ _copy { dst 1 } { src 0 } { class int-regs } }
         T{ _copy { dst 2 } { src 0 } { class int-regs } }
-        T{ _spill { src 4 } { class int-regs } { n spill-temp } }
+        T{ _spill { src 4 } { class int-regs } { n 10 } }
         T{ _copy { dst 4 } { src 0 } { class int-regs } }
         T{ _copy { dst 0 } { src 3 } { class int-regs } }
-        T{ _reload { dst 3 } { class int-regs } { n spill-temp } }
+        T{ _reload { dst 3 } { class int-regs } { n 10 } }
     }
 ] [
     {
@@ -182,10 +137,10 @@ T{ live-interval
         T{ _copy { dst 2 } { src 0 } { class int-regs } }
         T{ _copy { dst 9 } { src 1 } { class int-regs } }
         T{ _copy { dst 1 } { src 0 } { class int-regs } }
-        T{ _spill { src 4 } { class int-regs } { n spill-temp } }
+        T{ _spill { src 4 } { class int-regs } { n 10 } }
         T{ _copy { dst 4 } { src 0 } { class int-regs } }
         T{ _copy { dst 0 } { src 3 } { class int-regs } }
-        T{ _reload { dst 3 } { class int-regs } { n spill-temp } }
+        T{ _reload { dst 3 } { class int-regs } { n 10 } }
     }
 ] [
     {
index bd7528291d16f0e06f4b7acb5e00a02ff3f788e4..196d8e439f803ca610adc5396e3477e82d7b6ca2 100644 (file)
@@ -3,10 +3,15 @@
 USING: accessors arrays assocs classes.parser classes.tuple
 combinators combinators.short-circuit fry hashtables kernel locals
 make math math.order namespaces sequences sets words parser
-compiler.cfg.instructions compiler.cfg.linear-scan.live-intervals
-compiler.cfg.liveness ;
+compiler.cfg.instructions compiler.cfg.linear-scan.allocation.state
+compiler.cfg.linear-scan.assignment compiler.cfg.liveness ;
 IN: compiler.cfg.linear-scan.resolve
 
+SYMBOL: spill-temps
+
+: spill-temp ( reg-class -- n )
+    spill-temps get [ next-spill-slot ] cache ;
+
 <<
 
 TUPLE: operation from to reg-class ;
@@ -14,47 +19,33 @@ TUPLE: operation from to reg-class ;
 SYNTAX: OPERATION:
     CREATE-CLASS dup save-location
     [ operation { } define-tuple-class ]
-    [
-        [ scan-word scan-word ] keep
-        '[
-            [ [ _ execute ] [ _ execute ] bi* ]
-            [ vreg>> reg-class>> ]
-            bi _ boa ,
-        ] (( from to -- )) define-declared
-    ] bi ;
+    [ dup '[ _ boa , ] (( from to reg-class -- )) define-declared ] bi ;
 
 >>
 
-: reload-from ( bb live-interval -- n/f )
-    2dup [ block-from ] [ start>> ] bi* =
-    [ nip reload-from>> ] [ 2drop f ] if ;
+OPERATION: register->memory
+OPERATION: memory->register
+OPERATION: register->register
 
-: spill-to ( bb live-interval -- n/f )
-    2dup [ block-to ] [ end>> ] bi* =
-    [ nip spill-to>> ] [ 2drop f ] if ;
+! This should never come up because of how spill slots are assigned,
+! so make it an error.
+: memory->memory ( from to reg-class -- ) drop [ n>> ] bi@ assert= ;
 
-OPERATION: memory->memory spill-to>> reload-from>>
-OPERATION: register->memory reg>> reload-from>>
-OPERATION: memory->register spill-to>> reg>>
-OPERATION: register->register reg>> reg>>
-
-:: add-mapping ( bb1 bb2 li1 li2 -- )
-    bb2 li2 reload-from [
-        bb1 li1 spill-to
-        [ li1 li2 memory->memory ]
-        [ li1 li2 register->memory ] if
+: add-mapping ( from to reg-class -- )
+    over spill-slot? [
+        pick spill-slot?
+        [ memory->memory ]
+        [ register->memory ] if
     ] [
-        bb1 li1 spill-to
-        [ li1 li2 memory->register ]
-        [ li1 li2 register->register ] if
+        pick spill-slot?
+        [ memory->register ]
+        [ register->register ] if
     ] if ;
 
-: resolve-value-data-flow ( bb to vreg -- )
-    [ 2dup ] dip
-    live-intervals get at
-    [ [ block-to ] dip child-interval-at ]
-    [ [ block-from ] dip child-interval-at ]
-    bi-curry bi* 2dup eq? [ 2drop 2drop ] [ add-mapping ] if ;
+:: resolve-value-data-flow ( bb to vreg -- )
+    vreg bb vreg-at-end
+    vreg to vreg-at-start
+    2dup eq? [ 2drop ] [ vreg reg-class>> add-mapping ] if ;
 
 : compute-mappings ( bb to -- mappings )
     [
@@ -64,48 +55,23 @@ OPERATION: register->register reg>> reg>>
 
 GENERIC: >insn ( operation -- )
 
-M: memory->memory >insn
-    [ from>> ] [ to>> ] bi = [ "Not allowed" throw ] unless ;
-
 M: register->memory >insn
-    [ from>> ] [ reg-class>> ] bi spill-temp _spill ;
+    [ from>> ] [ reg-class>> ] [ to>> n>> ] tri _spill ;
 
 M: memory->register >insn
-    [ to>> ] [ reg-class>> ] bi spill-temp _reload ;
+    [ to>> ] [ reg-class>> ] [ from>> n>> ] tri  _reload ;
 
 M: register->register >insn
     [ to>> ] [ from>> ] [ reg-class>> ] tri _copy ;
 
-GENERIC: >collision-table ( operation -- )
-
-M: memory->memory >collision-table
-    [ from>> ] [ to>> ] bi = [ "Not allowed" throw ] unless ;
-
-M: register->memory >collision-table
-    [ from>> ] [ reg-class>> ] bi spill-temp _spill ;
-
-M: memory->register >collision-table
-    [ to>> ] [ reg-class>> ] bi spill-temp _reload ;
-
-M: register->register >collision-table
-    [ to>> ] [ from>> ] [ reg-class>> ] tri _copy ;
-
 SYMBOL: froms
 SYMBOL: tos
 
 SINGLETONS: memory register ;
 
-GENERIC: from-loc ( operation -- obj )
-M: memory->memory from-loc drop memory ;
-M: register->memory from-loc drop register ;
-M: memory->register from-loc drop memory ;
-M: register->register from-loc drop register ;
+: from-loc ( operation -- obj ) from>> spill-slot? memory register ? ;
 
-GENERIC: to-loc ( operation -- obj )
-M: memory->memory to-loc drop memory ;
-M: register->memory to-loc drop memory ;
-M: memory->register to-loc drop register ;
-M: register->register to-loc drop register ;
+: to-loc ( operation -- obj ) to>> spill-slot? memory register ? ;
 
 : from-reg ( operation -- seq )
     [ from-loc ] [ from>> ] [ reg-class>> ] tri 3array ;
@@ -139,7 +105,6 @@ M: register->register to-loc drop register ;
         dup dup associate (trace-chain)
     ] { } make prune reverse ;
 
-
 : trace-chains ( seq -- seq' )
     [ trace-chain ] map concat ;
 
@@ -156,11 +121,15 @@ ERROR: resolve-error ;
 
 : break-cycle-n ( operations -- operations' )
     split-cycle [
-        [ from>> spill-temp ]
-        [ reg-class>> ] bi \ register->memory boa
+        [ from>> ]
+        [ reg-class>> spill-temp <spill-slot> ]
+        [ reg-class>> ]
+        tri \ register->memory boa
     ] [
-        [ to>> spill-temp swap ]
-        [ reg-class>> ] bi \ memory->register boa
+        [ reg-class>> spill-temp <spill-slot> ]
+        [ to>> ]
+        [ reg-class>> ]
+        tri \ memory->register boa
     ] bi [ 1array ] bi@ surround ;
 
 : break-cycle ( operations -- operations' )
@@ -237,4 +206,5 @@ ERROR: resolve-error ;
     dup successors>> [ resolve-edge-data-flow ] with each ;
 
 : resolve-data-flow ( rpo -- )
+    H{ } clone spill-temps set
     [ resolve-block-data-flow ] each ;
index 9e222f1832e2fb82eb715f8b0e5a39c677e6bebb..15e7cef5534d60a1bc58332e4f2dd1e860ae858b 100755 (executable)
@@ -24,19 +24,8 @@ M: insn linearize-insn , drop ;
     #! don't need to branch.
     [ number>> ] bi@ 1 - = ; inline
 
-: branch-to-branch? ( successor -- ? )
-    #! A branch to a block containing just a jump return is cloned.
-    instructions>> dup length 2 = [
-        [ first ##epilogue? ]
-        [ second [ ##return? ] [ ##jump? ] bi or ] bi and
-    ] [ drop f ] if ;
-
 : emit-branch ( basic-block successor -- )
-    {
-        { [ 2dup useless-branch? ] [ 2drop ] }
-        { [ dup branch-to-branch? ] [ nip linearize-basic-block ] }
-        [ nip number>> _branch ]
-    } cond ;
+    2dup useless-branch? [ 2drop ] [ nip number>> _branch ] if ;
 
 M: ##branch linearize-insn
     drop dup successors>> first emit-branch ;
@@ -68,41 +57,31 @@ M: ##dispatch linearize-insn
     [ successors>> [ number>> _dispatch-label ] each ]
     bi* ;
 
-: gc-root-registers ( n live-registers -- n )
-    [
-        [ second 2array , ]
-        [ first reg-class>> reg-size + ]
-        2bi
-    ] each ;
-
-: gc-root-spill-slots ( n live-spill-slots -- n )
+: (compute-gc-roots) ( n live-values -- n )
     [
-        dup first reg-class>> int-regs eq? [
-            [ second <spill-slot> 2array , ]
-            [ first reg-class>> reg-size + ]
-            2bi
-        ] [ drop ] if
-    ] each ;
+        [ nip 2array , ]
+        [ drop reg-class>> reg-size + ]
+        3bi
+    ] assoc-each ;
 
-: oop-registers ( regs -- regs' )
-    [ first reg-class>> int-regs eq? ] filter ;
+: oop-values ( regs -- regs' )
+    [ drop reg-class>> int-regs eq? ] assoc-filter ;
 
-: data-registers ( regs -- regs' )
-    [ first reg-class>> double-float-regs eq? ] filter ;
+: data-values ( regs -- regs' )
+    [ drop reg-class>> double-float-regs eq? ] assoc-filter ;
 
-:: compute-gc-roots ( live-registers live-spill-slots -- alist )
+: compute-gc-roots ( live-values -- alist )
     [
-        0
+        [ 0 ] dip
         ! we put float registers last; the GC doesn't actually scan them
-        live-registers oop-registers gc-root-registers
-        live-spill-slots gc-root-spill-slots
-        live-registers data-registers gc-root-registers
+        [ oop-values (compute-gc-roots) ]
+        [ data-values (compute-gc-roots) ] bi
         drop
     ] { } make ;
 
-: count-gc-roots ( live-registers live-spill-slots -- n )
+: count-gc-roots ( live-values -- n )
     ! Size of GC root area, minus the float registers
-    [ oop-registers length ] bi@ + ;
+    oop-values assoc-size ;
 
 M: ##gc linearize-insn
     nip
@@ -110,11 +89,11 @@ M: ##gc linearize-insn
         [ temp1>> ]
         [ temp2>> ]
         [
-            [ live-registers>> ] [ live-spill-slots>> ] bi
+            live-values>>
             [ compute-gc-roots ]
             [ count-gc-roots ]
             [ gc-roots-size ]
-            2tri
+            tri
         ] tri
         _gc
     ] with-regs ;
diff --git a/basis/compiler/cfg/liveness/liveness-tests.factor b/basis/compiler/cfg/liveness/liveness-tests.factor
new file mode 100644 (file)
index 0000000..271dc60
--- /dev/null
@@ -0,0 +1,15 @@
+USING: compiler.cfg compiler.cfg.instructions compiler.cfg.registers
+compiler.cfg.liveness accessors tools.test cpu.architecture ;
+IN: compiler.cfg.liveness.tests
+
+[
+    H{
+        { "A" H{ { V int-regs 1 V int-regs 1 } { V int-regs 4 V int-regs 4 } } }
+        { "B" H{ { V int-regs 3 V int-regs 3 } { V int-regs 2 V int-regs 2 } } }
+    }
+] [
+    <basic-block> V{
+        T{ ##phi f V int-regs 0 { { "A" V int-regs 1 } { "B" V int-regs 2 } } }
+        T{ ##phi f V int-regs 1 { { "B" V int-regs 3 } { "A" V int-regs 4 } } }
+    } >>instructions compute-phi-live-in
+] unit-test
\ No newline at end of file
index 6c40bb37821bbfea213504b7f72c102f7dafd405..8a46b32070a1280b50f256a225dbe289d6001e0a 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel namespaces deques accessors sets sequences assocs fry
-dlists compiler.cfg.def-use compiler.cfg.instructions
+hashtables dlists compiler.cfg.def-use compiler.cfg.instructions
 compiler.cfg.rpo ;
 IN: compiler.cfg.liveness
 
@@ -16,9 +16,7 @@ SYMBOL: live-ins
 ! is in conrrespondence with a predecessor
 SYMBOL: phi-live-ins
 
-: phi-live-in ( predecessor basic-block -- set )
-    [ predecessors>> index ] keep phi-live-ins get at
-    dup [ nth ] [ 2drop f ] if ;
+: phi-live-in ( predecessor basic-block -- set ) phi-live-ins get at at ;
 
 ! Assoc mapping basic blocks to sets of vregs
 SYMBOL: live-outs
@@ -45,9 +43,15 @@ SYMBOL: work-list
     [ nip kill-set ]
     2bi assoc-diff ;
 
+: conjoin-at ( value key assoc -- )
+    [ dupd ?set-at ] change-at ;
+
 : compute-phi-live-in ( basic-block -- phi-live-in )
-    instructions>> [ ##phi? ] filter
-    [ f ] [ [ inputs>> ] map flip [ unique ] map ] if-empty ;
+    instructions>> [ ##phi? ] filter [ f ] [
+        H{ } clone [
+            '[ inputs>> [ swap _ conjoin-at ] assoc-each ] each
+        ] keep
+    ] if-empty ;
 
 : update-live-in ( basic-block -- changed? )
     [ [ compute-live-in ] keep live-ins get maybe-set-at ]
index ee601f23376fa756aa299ea9a09e385522422e54..97ebc7cc3eca14e13e110980d44f33706c10c82c 100644 (file)
@@ -1,7 +1,8 @@
-USING: arrays sequences tools.test compiler.cfg.checker
-compiler.cfg.debugger compiler.cfg.def-use sets kernel
-kernel.private fry slots.private vectors sequences.private
-math sbufs math.private strings ;
+USING: accessors arrays compiler.cfg.checker
+compiler.cfg.debugger compiler.cfg.def-use
+compiler.cfg.instructions fry kernel kernel.private math
+math.private sbufs sequences sequences.private sets
+slots.private strings tools.test vectors ;
 IN: compiler.cfg.optimizer.tests
 
 ! Miscellaneous tests
@@ -33,3 +34,11 @@ IN: compiler.cfg.optimizer.tests
 } [
     [ [ ] ] dip '[ _ test-mr first check-mr ] unit-test
 ] each
+
+[ t ]
+[
+    [
+        HEX: 7fff fixnum-bitand 13 fixnum-shift-fast
+        112 23 fixnum-shift-fast fixnum+fast
+    ] test-mr first instructions>> [ ##add? ] any?
+] unit-test
index e789fc9c2138f5d4494ae3cdf239d95964d946df..84eb8a84d13a03a94d0464f0aeae861778a6afdb 100644 (file)
@@ -1,12 +1,15 @@
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel sequences accessors combinators namespaces
+compiler.cfg.tco
 compiler.cfg.predecessors
-compiler.cfg.useless-blocks
+compiler.cfg.useless-conditionals
 compiler.cfg.stack-analysis
+compiler.cfg.branch-splitting
 compiler.cfg.alias-analysis
 compiler.cfg.value-numbering
 compiler.cfg.dce
+compiler.cfg.branch-folding
 compiler.cfg.write-barrier
 compiler.cfg.liveness
 compiler.cfg.rpo
@@ -22,14 +25,20 @@ SYMBOL: check-optimizer?
     ] when ;
 
 : optimize-cfg ( cfg -- cfg' )
+    ! Note that compute-predecessors has to be called several times.
+    ! The passes that need this document it.
     [
+        optimize-tail-calls
         compute-predecessors
-        ! delete-useless-blocks
         delete-useless-conditionals
+        split-branches
+        compute-predecessors
         stack-analysis
         compute-liveness
         alias-analysis
         value-numbering
+        fold-branches
+        compute-predecessors
         eliminate-dead-code
         eliminate-write-barriers
         eliminate-phis
diff --git a/basis/compiler/cfg/phi-elimination/phi-elimination-tests.factor b/basis/compiler/cfg/phi-elimination/phi-elimination-tests.factor
new file mode 100644 (file)
index 0000000..4577e70
--- /dev/null
@@ -0,0 +1,40 @@
+IN: compiler.cfg.phi-elimination.tests
+USING: compiler.cfg.instructions compiler.cfg compiler.cfg.registers
+compiler.cfg.debugger compiler.cfg.phi-elimination kernel accessors
+sequences classes namespaces tools.test cpu.architecture arrays ;
+
+V{ T{ ##branch } } 0 test-bb
+
+V{
+    T{ ##peek f V int-regs 0 D 0 }
+    T{ ##compare-branch f V int-regs 0 V int-regs 0 cc< }
+} 1 test-bb
+
+V{
+    T{ ##load-immediate f V int-regs 1 1 }
+    T{ ##branch }
+} 2 test-bb
+
+V{
+    T{ ##load-immediate f V int-regs 2 2 }
+    T{ ##branch }
+} 3 test-bb
+
+V{
+    T{ ##phi f V int-regs 3 { } }
+    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
+
+[ ] [ cfg new 0 get >>entry eliminate-phis drop ] unit-test
+
+[ T{ ##copy f V int-regs 3 V int-regs 1 } ] [ 2 get instructions>> second ] unit-test
+[ T{ ##copy f V int-regs 3 V int-regs 2 } ] [ 3 get instructions>> second ] unit-test
+[ 2 ] [ 4 get instructions>> length ] unit-test
\ No newline at end of file
index 3ebf553a4550d0ce7236d457a7e42ee14645eb1d..9c2f0adafd90b0914b081f2793bf06d52e428898 100644 (file)
@@ -1,21 +1,17 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors compiler.cfg compiler.cfg.instructions
-compiler.cfg.rpo fry kernel sequences ;
+USING: accessors assocs fry kernel sequences
+compiler.cfg compiler.cfg.instructions compiler.cfg.rpo ;
 IN: compiler.cfg.phi-elimination
 
 : insert-copy ( predecessor input output -- )
     '[ _ _ swap ##copy ] add-instructions ;
 
-: eliminate-phi ( bb ##phi -- )
-    [ predecessors>> ] [ [ inputs>> ] [ dst>> ] bi ] bi*
-    '[ _ insert-copy ] 2each ;
+: eliminate-phi ( ##phi -- )
+    [ inputs>> ] [ dst>> ] bi '[ _ insert-copy ] assoc-each ;
 
 : eliminate-phi-step ( bb -- )
-    dup [
-        [ ##phi? ] partition
-        [ [ eliminate-phi ] with each ] dip
-    ] change-instructions drop ;
+    instructions>> [ dup ##phi? [ eliminate-phi f ] [ drop t ] if ] filter-here ;
 
 : eliminate-phis ( cfg -- cfg' )
     dup [ eliminate-phi-step ] each-basic-block ;
\ No newline at end of file
index 54efc53bc424e0d055aaaf5501219a132c1c95cf..73ae3ee242365c07933ac300dd23185a35419723 100644 (file)
@@ -1,13 +1,27 @@
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel accessors sequences compiler.cfg.rpo ;
+USING: kernel accessors combinators fry sequences assocs compiler.cfg.rpo
+compiler.cfg.instructions ;
 IN: compiler.cfg.predecessors
 
-: predecessors-step ( bb -- )
+: update-predecessors ( bb -- )
     dup successors>> [ predecessors>> push ] with each ;
 
+: update-phi ( bb ##phi -- )
+    [
+        swap predecessors>>
+        '[ drop _ memq? ] assoc-filter
+    ] change-inputs drop ;
+
+: update-phis ( bb -- )
+    dup instructions>> [
+        dup ##phi? [ update-phi ] [ 2drop ] if
+    ] with each ;
+
 : compute-predecessors ( cfg -- cfg' )
-    [ [ V{ } clone >>predecessors drop ] each-basic-block ]
-    [ [ predecessors-step ] each-basic-block ]
-    [ ]
-    tri ;
+    {
+        [ [ V{ } clone >>predecessors drop ] each-basic-block ]
+        [ [ update-predecessors ] each-basic-block ]
+        [ [ update-phis ] each-basic-block ]
+        [ ]
+    } cleave ;
index e5193089744c5d87321362b427c988c4493c8c9f..14a81958a9137b6f3ca631271e9d212853750892 100644 (file)
@@ -17,7 +17,7 @@ sequences kernel classes ;
     <state> H{ { D 0 V int-regs 0 } } >>locs>vregs
     <state> H{ { D 0 V int-regs 1 } } >>locs>vregs 2array
 
-    [ merge-locs locs>vregs>> keys ] { } make first inputs>>
+    [ merge-locs locs>vregs>> keys ] { } make first inputs>> values
 ] unit-test
 
 [
index 04643a31f0ac56796285d4fc3317b6f9e1536b60..b6c443a2d325eb1be61267795e2f5d8ff7eda381 100644 (file)
@@ -48,8 +48,9 @@ IN: compiler.cfg.stack-analysis.merge
 : merge-loc ( predecessors vregs loc state -- vreg )
     ! Insert a ##phi in the current block where the input
     ! is the vreg storing loc from each predecessor block
+    [ dup ] 3dip
     '[ [ ] [ _ _ insert-peek ] ?if ] 2map
-    dup all-equal? [ first ] [ ^^phi ] if ;
+    dup all-equal? [ nip first ] [ zip ^^phi ] if ;
 
 :: merge-locs ( state predecessors states -- state )
     states [ locs>vregs>> ] map states collect-locs
index 6f4b88e28e68c4f582553060bcc528870e7d52d5..cbc939b1f2c28296b077bab6330f99df3f5aa067 100644 (file)
@@ -3,7 +3,7 @@ compiler.cfg.predecessors compiler.cfg.stack-analysis
 compiler.cfg.instructions sequences kernel tools.test accessors
 sequences.private alien math combinators.private compiler.cfg
 compiler.cfg.checker compiler.cfg.rpo
-compiler.cfg.dce compiler.cfg.registers compiler.cfg.useless-blocks
+compiler.cfg.dce compiler.cfg.registers
 sets namespaces arrays cpu.architecture ;
 IN: compiler.cfg.stack-analysis.tests
 
index 1e7f33c7e047a84de3fe9d6bb2a9f41132d77cb2..fb71fe332dbe25fd048a184330c4e34c2fe478c1 100644 (file)
@@ -48,7 +48,8 @@ M: ##inc-r visit
 ! Instructions which don't have any effect on the stack
 UNION: neutral-insn
     ##effect
-    ##flushable ;
+    ##flushable
+    ##no-tco ;
 
 M: neutral-insn visit , ;
 
index 5cb5762b786ee965267f45df9556e761275eab07..9eb6d27521cde24a5360cde0677ffcfb33cf23aa 100644 (file)
@@ -34,8 +34,8 @@ spill-counts ;
 
 : gc-root-offset ( n -- n' ) gc-root-base + ;
 
-: gc-roots-size ( live-registers live-spill-slots -- n )
-    [ keys [ reg-class>> reg-size ] sigma ] bi@ + ;
+: gc-roots-size ( live-values -- n )
+    keys [ reg-class>> reg-size ] sigma ;
 
 : (stack-frame-size) ( stack-frame -- n )
     [
diff --git a/basis/compiler/cfg/tco/tco.factor b/basis/compiler/cfg/tco/tco.factor
new file mode 100644 (file)
index 0000000..df5d962
--- /dev/null
@@ -0,0 +1,85 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors combinators.short-circuit kernel math
+namespaces sequences fry combinators
+compiler.cfg
+compiler.cfg.rpo
+compiler.cfg.hats
+compiler.cfg.instructions ;
+IN: compiler.cfg.tco
+
+! Tail call optimization. You must run compute-predecessors after this
+
+: return? ( bb -- ? )
+    skip-empty-blocks
+    instructions>> {
+        [ length 2 = ]
+        [ first ##epilogue? ]
+        [ second ##return? ]
+    } 1&& ;
+
+: penultimate ( seq -- elt ) [ length 2 - ] keep nth ;
+
+: tail-call? ( bb -- ? )
+    {
+        [ instructions>> { [ length 2 >= ] [ last ##branch? ] } 1&& ]
+        [ successors>> first return? ]
+    } 1&& ;
+
+: word-tail-call? ( bb -- ? )
+    instructions>> penultimate ##call? ;
+
+: convert-tail-call ( bb quot: ( insn -- tail-insn ) -- )
+    '[
+        instructions>>
+        [ pop* ] [ pop ] [ ] tri
+        [ [ \ ##epilogue new-insn ] dip push ]
+        [ _ dip push ] bi
+    ]
+    [ successors>> delete-all ]
+    bi ; inline
+
+: convert-word-tail-call ( bb -- )
+    [ word>> \ ##jump new-insn ] convert-tail-call ;
+
+: loop-tail-call? ( bb -- ? )
+    instructions>> penultimate
+    { [ ##call? ] [ word>> cfg get label>> eq? ] } 1&& ;
+
+: convert-loop-tail-call ( bb -- )
+    ! If a word calls itself, this becomes a loop in the CFG.
+    [ instructions>> [ pop* ] [ pop* ] [ [ \ ##branch new-insn ] dip push ] tri ]
+    [ successors>> delete-all ]
+    [ [ cfg get entry>> successors>> first ] dip successors>> push ]
+    tri ;
+
+: fixnum-tail-call? ( bb -- ? )
+    instructions>> penultimate
+    { [ ##fixnum-add? ] [ ##fixnum-sub? ] [ ##fixnum-mul? ] } 1|| ;
+
+GENERIC: convert-fixnum-tail-call* ( src1 src2 insn -- insn' )
+
+M: ##fixnum-add convert-fixnum-tail-call* drop \ ##fixnum-add-tail new-insn ;
+M: ##fixnum-sub convert-fixnum-tail-call* drop \ ##fixnum-sub-tail new-insn ;
+M: ##fixnum-mul convert-fixnum-tail-call* drop i i \ ##fixnum-mul-tail new-insn ;
+
+: convert-fixnum-tail-call ( bb -- )
+    [
+        [ src1>> ] [ src2>> ] [ ] tri
+        convert-fixnum-tail-call*
+    ] convert-tail-call ;
+
+: optimize-tail-call ( bb -- )
+    dup tail-call? [
+        {
+            { [ dup loop-tail-call? ] [ convert-loop-tail-call ] }
+            { [ dup word-tail-call? ] [ convert-word-tail-call ] }
+            { [ dup fixnum-tail-call? ] [ convert-fixnum-tail-call ] }
+            [ drop ]
+        } cond
+    ] [ drop ] if ;
+
+: optimize-tail-calls ( cfg -- cfg' )
+    dup cfg set
+    dup [ optimize-tail-call ] each-basic-block
+    f >>post-order ;
\ No newline at end of file
diff --git a/basis/compiler/cfg/useless-blocks/summary.txt b/basis/compiler/cfg/useless-blocks/summary.txt
deleted file mode 100644 (file)
index 616fae7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Eliminating unreachable basic blocks and unconditional jumps
diff --git a/basis/compiler/cfg/useless-blocks/useless-blocks-tests.factor b/basis/compiler/cfg/useless-blocks/useless-blocks-tests.factor
deleted file mode 100644 (file)
index 1d14cef..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-IN: compiler.cfg.useless-blocks.tests
-USING: fry kernel sequences compiler.cfg.useless-blocks compiler.cfg.checker
-compiler.cfg.debugger compiler.cfg.predecessors tools.test ;
-
-{
-    [ [ drop 1 ] when ]
-    [ [ drop 1 ] unless ]
-} [
-    [ [ ] ] dip
-    '[ _ test-cfg first compute-predecessors delete-useless-blocks check-cfg ] unit-test
-] each
\ No newline at end of file
diff --git a/basis/compiler/cfg/useless-blocks/useless-blocks.factor b/basis/compiler/cfg/useless-blocks/useless-blocks.factor
deleted file mode 100644 (file)
index cbe006b..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: kernel accessors sequences combinators combinators.short-circuit
-classes vectors compiler.cfg compiler.cfg.instructions compiler.cfg.rpo ;
-IN: compiler.cfg.useless-blocks
-
-: update-predecessor-for-delete ( bb -- )
-    ! We have to replace occurrences of bb with bb's successor
-    ! in bb's predecessor's list of successors.
-    dup predecessors>> first [
-        [
-            2dup eq? [ drop successors>> first ] [ nip ] if
-        ] with map
-    ] change-successors drop ;
-
-: update-successor-for-delete ( bb -- )
-    ! We have to replace occurrences of bb with bb's predecessor
-    ! in bb's sucessor's list of predecessors.
-    dup successors>> first [
-        [
-            2dup eq? [ drop predecessors>> first ] [ nip ] if
-        ] with map
-    ] change-predecessors drop ;
-
-: delete-basic-block ( bb -- )
-    [ update-predecessor-for-delete ]
-    [ update-successor-for-delete ]
-    bi ;
-
-: delete-basic-block? ( bb -- ? )
-    {
-        [ instructions>> length 1 = ]
-        [ predecessors>> length 1 = ]
-        [ successors>> length 1 = ]
-        [ instructions>> first ##branch? ]
-    } 1&& ;
-
-: delete-useless-blocks ( cfg -- cfg' )
-    dup [
-        dup delete-basic-block? [ delete-basic-block ] [ drop ] if
-    ] each-basic-block
-    f >>post-order ;
-
-: delete-conditional? ( bb -- ? )
-    dup instructions>> [ drop f ] [
-        last class {
-            ##compare-branch
-            ##compare-imm-branch
-            ##compare-float-branch
-        } memq? [ successors>> first2 eq? ] [ drop f ] if
-    ] if-empty ;
-
-: delete-conditional ( bb -- )
-    dup successors>> first 1vector >>successors
-    [ but-last \ ##branch new-insn suffix ] change-instructions
-    drop ;
-
-: delete-useless-conditionals ( cfg -- cfg' )
-    dup [
-        dup delete-conditional? [ delete-conditional ] [ drop ] if
-    ] each-basic-block
-    f >>post-order ;
diff --git a/basis/compiler/cfg/useless-conditionals/summary.txt b/basis/compiler/cfg/useless-conditionals/summary.txt
new file mode 100644 (file)
index 0000000..616fae7
--- /dev/null
@@ -0,0 +1 @@
+Eliminating unreachable basic blocks and unconditional jumps
diff --git a/basis/compiler/cfg/useless-conditionals/useless-conditionals.factor b/basis/compiler/cfg/useless-conditionals/useless-conditionals.factor
new file mode 100644 (file)
index 0000000..6f4a6ee
--- /dev/null
@@ -0,0 +1,21 @@
+! Copyright (C) 2008, 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel accessors sequences math combinators combinators.short-circuit
+classes vectors compiler.cfg compiler.cfg.instructions compiler.cfg.rpo ;
+IN: compiler.cfg.useless-conditionals
+
+: delete-conditional? ( bb -- ? )
+    {
+        [ instructions>> last class { ##compare-branch ##compare-imm-branch ##compare-float-branch } memq? ]
+        [ successors>> first2 [ skip-empty-blocks ] bi@ eq? ]
+    } 1&& ;
+
+: delete-conditional ( bb -- )
+    [ first skip-empty-blocks 1vector ] change-successors
+    instructions>> [ pop* ] [ [ \ ##branch new-insn ] dip push ] bi ;
+
+: delete-useless-conditionals ( cfg -- cfg' )
+    dup [
+        dup delete-conditional? [ delete-conditional ] [ drop ] if
+    ] each-basic-block
+    f >>post-order ;
index e415008808fc4fe2a5cccdd3affb730c8b76d54b..99a138a7636b6a95220a8ec18d886c0ae4690546 100644 (file)
@@ -35,8 +35,5 @@ IN: compiler.cfg.utilities
 
 : stop-iterating ( -- next ) end-basic-block f ;
 
-: call-height ( ##call -- n )
-    [ out-d>> length ] [ in-d>> length ] bi - ;
-
 : emit-primitive ( node -- )
-    [ word>> ] [ call-height ] bi ##call ##branch begin-basic-block ;
+    word>> ##call ##branch begin-basic-block ;
index 7ec9eaf7ce1a4466891ce488070d05d67889a85f..41e72019533658d459f7bd8ecf5521b992738aa0 100644 (file)
@@ -26,6 +26,8 @@ SYMBOL: vregs>vns
 
 : vn>constant ( vn -- constant ) vn>expr value>> ; inline
 
+: vreg>constant ( vreg -- constant ) vreg>vn vn>constant ; inline
+
 : init-value-graph ( -- )
     0 vn-counter set
     <bihash> exprs>vns set
old mode 100644 (file)
new mode 100755 (executable)
index 7630d0a..ca7a959
@@ -1,26 +1,23 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2009 Slava Pestov, Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel sequences layouts accessors combinators namespaces
-math fry
-compiler.cfg.hats
-compiler.cfg.instructions
+USING: accessors locals combinators combinators.short-circuit arrays
+fry kernel layouts math namespaces sequences cpu.architecture
+math.bitwise compiler.cfg.hats compiler.cfg.instructions
+compiler.cfg.value-numbering.expressions
 compiler.cfg.value-numbering.graph
-compiler.cfg.value-numbering.simplify
-compiler.cfg.value-numbering.expressions ;
+compiler.cfg.value-numbering.simplify ;
 IN: compiler.cfg.value-numbering.rewrite
 
 GENERIC: rewrite ( insn -- insn' )
 
-M: ##mul-imm rewrite
-    dup src2>> dup power-of-2? [
-        [ [ dst>> ] [ src1>> ] bi ] [ log2 ] bi* \ ##shl-imm new-insn
-        dup number-values
-    ] [ drop ] if ;
+M: insn rewrite ;
 
 : ##branch-t? ( insn -- ? )
     dup ##compare-imm-branch? [
-        [ cc>> cc/= eq? ]
-        [ src2>> \ f tag-number eq? ] bi and
+        {
+            [ cc>> cc/= eq? ]
+            [ src2>> \ f tag-number eq? ]
+        } 1&&
     ] [ drop f ] if ; inline
 
 : rewrite-boolean-comparison? ( insn -- ? )
@@ -47,9 +44,10 @@ M: ##mul-imm rewrite
 
 : rewrite-tagged-comparison? ( insn -- ? )
     #! Are we comparing two tagged fixnums? Then untag them.
-    [ src1>> vreg>expr tag-fixnum-expr? ]
-    [ src2>> tag-mask get bitand 0 = ]
-    bi and ; inline
+    {
+        [ src1>> vreg>expr tag-fixnum-expr? ]
+        [ src2>> tag-mask get bitand 0 = ]
+    } 1&& ; inline
 
 : (rewrite-tagged-comparison) ( insn -- src1 src2 cc )
     [ src1>> vreg>expr in1>> vn>vreg ]
@@ -72,27 +70,41 @@ M: ##compare-imm-branch rewrite
         dup rewrite-tagged-comparison? [ rewrite-tagged-comparison ] when
     ] when ;
 
-: flip-comparison? ( insn -- ? )
-    dup cc>> cc= eq? [ src1>> vreg>expr constant-expr? ] [ drop f ] if ;
-
-: flip-comparison ( insn -- insn' )
-    [ dst>> ]
-    [ src2>> ]
-    [ src1>> vreg>vn vn>constant ] tri
-    cc= i \ ##compare-imm new-insn ;
-
-M: ##compare rewrite
-    dup flip-comparison? [
-        flip-comparison
-        dup number-values
-        rewrite
-    ] when ;
+:: >compare-imm ( insn swap? -- insn' )
+    insn dst>>
+    insn src1>>
+    insn src2>> swap? [ swap ] when vreg>constant
+    insn cc>> swap? [ swap-cc ] when
+    i \ ##compare-imm new-insn ; inline
+
+! M: ##compare rewrite
+!     dup [ src1>> ] [ src2>> ] bi
+!     [ vreg>expr constant-expr? ] bi@ 2array {
+!         { { f t } [ f >compare-imm ] }
+!         { { t f } [ t >compare-imm ] }
+!         [ drop ]
+!     } case ;
+
+:: >compare-imm-branch ( insn swap? -- insn' )
+    insn src1>>
+    insn src2>> swap? [ swap ] when vreg>constant
+    insn cc>> swap? [ swap-cc ] when
+    \ ##compare-imm-branch new-insn ; inline
+
+! M: ##compare-branch rewrite
+!     dup [ src1>> ] [ src2>> ] bi
+!     [ vreg>expr constant-expr? ] bi@ 2array {
+!         { { f t } [ f >compare-imm-branch ] }
+!         { { t f } [ t >compare-imm-branch ] }
+!         [ drop ]
+!     } case ;
 
 : rewrite-redundant-comparison? ( insn -- ? )
-    [ src1>> vreg>expr compare-expr? ]
-    [ src2>> \ f tag-number = ]
-    [ cc>> { cc= cc/= } memq? ]
-    tri and and ; inline
+    {
+        [ src1>> vreg>expr compare-expr? ]
+        [ src2>> \ f tag-number = ]
+        [ cc>> { cc= cc/= } memq? ]
+    } 1&& ; inline
 
 : rewrite-redundant-comparison ( insn -- insn' )
     [ cc>> ] [ dst>> ] [ src1>> vreg>expr dup op>> ] tri {
@@ -114,4 +126,89 @@ M: ##compare-imm rewrite
         ] when
     ] when ;
 
-M: insn rewrite ;
+: constant-fold ( insn -- insn' )
+    dup dst>> vreg>expr dup constant-expr? [
+        [ dst>> ] [ value>> ] bi* \ ##load-immediate new-insn
+        dup number-values
+    ] [
+        drop
+    ] if ;
+
+: (new-imm-insn) ( insn dst src1 n op -- new-insn/insn )
+    [ cell-bits bits ] dip over small-enough? [
+        new-insn dup number-values nip
+    ] [
+        2drop 2drop
+    ] if constant-fold ; inline
+
+: new-imm-insn ( insn dst src n op -- n' op' )
+    2dup [ sgn ] dip 2array
+    {
+        { { -1 ##add-imm } [ drop neg \ ##sub-imm (new-imm-insn) ] }
+        { { -1 ##sub-imm } [ drop neg \ ##add-imm (new-imm-insn) ] }
+        [ drop (new-imm-insn) ]
+    } case ; inline
+
+: combine-imm? ( insn op -- ? )
+    [ src1>> vreg>expr op>> ] dip = ;
+
+: (combine-imm) ( insn quot op -- insn )
+    [
+        {
+            [ ]
+            [ dst>> ]
+            [ src1>> vreg>expr [ in1>> vn>vreg ] [ in2>> vn>constant ] bi ]
+            [ src2>> ]
+        } cleave
+    ] [ call ] [ ] tri* new-imm-insn ; inline
+
+:: combine-imm ( insn quot op -- insn )
+    insn op combine-imm? [
+        insn quot op (combine-imm)
+    ] [
+        insn
+    ] if ; inline
+
+M: ##add-imm rewrite
+    {
+        { [ dup \ ##add-imm combine-imm? ] [ [ + ] \ ##add-imm (combine-imm) ] }
+        { [ dup \ ##sub-imm combine-imm? ] [ [ - ] \ ##sub-imm (combine-imm) ] }
+        [ ]
+    } cond ;
+
+M: ##sub-imm rewrite
+    {
+        { [ dup \ ##add-imm combine-imm? ] [ [ - ] \ ##add-imm (combine-imm) ] }
+        { [ dup \ ##sub-imm combine-imm? ] [ [ + ] \ ##sub-imm (combine-imm) ] }
+        [ ]
+    } cond ;
+
+M: ##mul-imm rewrite
+    dup src2>> dup power-of-2? [
+        [ [ dst>> ] [ src1>> ] bi ] [ log2 ] bi* \ ##shl-imm new-insn
+        dup number-values
+    ] [
+        drop [ * ] \ ##mul-imm combine-imm
+    ] if ;
+
+M: ##and-imm rewrite [ bitand ] \ ##and-imm combine-imm ;
+
+M: ##or-imm rewrite [ bitor ] \ ##or-imm combine-imm ;
+
+M: ##xor-imm rewrite [ bitxor ] \ ##xor-imm combine-imm ;
+
+: rewrite-add? ( insn -- ? )
+    src2>> {
+        [ vreg>expr constant-expr? ]
+        [ vreg>constant small-enough? ]
+    } 1&& ;
+
+M: ##add rewrite
+    dup rewrite-add? [
+        [ dst>> ]
+        [ src1>> ]
+        [ src2>> vreg>constant ] tri \ ##add-imm new-insn
+        dup number-values
+    ] when ;
+
+M: ##sub rewrite constant-fold ;
index e70ba4b54b43079587b7cf76c371366ee6572eb8..b7526528e41e4217080d5decb677f162e8b8ca27 100644 (file)
@@ -3,7 +3,7 @@
 USING: kernel accessors combinators classes math layouts
 compiler.cfg.instructions
 compiler.cfg.value-numbering.graph
-compiler.cfg.value-numbering.expressions ;
+compiler.cfg.value-numbering.expressions locals ;
 IN: compiler.cfg.value-numbering.simplify
 
 ! Return value of f means we didn't simplify.
@@ -42,6 +42,13 @@ M: unary-expr simplify*
         [ 2drop f ]
     } cond ; inline
 
+: simplify-sub ( expr -- vn/expr/f )
+    >binary-expr< {
+        { [ 2dup eq? ] [ 2drop T{ constant-expr f f 0 } ] }
+        { [ dup expr-zero? ] [ drop ] }
+        [ 2drop f ]
+    } cond ; inline
+
 : useless-shift? ( in1 in2 -- ? )
     over op>> \ ##shl-imm eq?
     [ [ in2>> ] [ expr>vn ] bi* = ] [ 2drop f ] if ; inline
@@ -54,6 +61,8 @@ M: binary-expr simplify*
     dup op>> {
         { \ ##add [ simplify-add ] }
         { \ ##add-imm [ simplify-add ] }
+        { \ ##sub [ simplify-sub ] }
+        { \ ##sub-imm [ simplify-sub ] }
         { \ ##shr-imm [ simplify-shift ] }
         { \ ##sar-imm [ simplify-shift ] }
         [ 2drop f ]
index a1583d2a5d6bd8488c6613fbc4212a7c515738c6..df6e91aec979413eef89c20a13a58d3bba7810a8 100755 (executable)
@@ -67,6 +67,8 @@ SYMBOL: labels
 : lookup-label ( id -- label )
     labels get [ drop <label> ] cache ;
 
+M: ##no-tco generate-insn drop ;
+
 M: ##load-immediate generate-insn
     [ dst>> register ] [ val>> ] bi %load-immediate ;
 
index 36ee5eb94d58d8c758f273211eb07f8f90dfbe52..82da31b5fe0531b59aab628ae23ecb7ef97134f0 100644 (file)
@@ -310,4 +310,8 @@ M: cucumber equal? "The cucumber has no equal" throw ;
     }
 ] [
     [ { 1 2 3 } "x" "y" linear-scan-regression ] { } make
-] unit-test
\ No newline at end of file
+] unit-test
+
+! Regression from Doug's value numbering changes
+[ t ] [ 2 [ 1 swap fixnum< ] compile-call ] unit-test
+[ 3 ] [ 2 [ 1 swap fixnum< [ 3 ] [ 4 ] if ] compile-call ] unit-test
\ No newline at end of file
index d0cfc127e3e86042448f3c1dac8753af18f8dffd..df7f1c85135c7697cd90d13c048549f57d4a4ccb 100644 (file)
@@ -238,6 +238,13 @@ IN: compiler.tests.intrinsics
 
 [ t ] [ f [ f eq? ] compile-call ] unit-test
 
+cell 8 = [
+    [ HEX: 40400000 ] [
+        HEX: 4200 [ HEX: 7fff fixnum-bitand 13 fixnum-shift-fast 112 23 fixnum-shift-fast fixnum+fast ]
+        compile-call
+    ] unit-test
+] when
+
 ! regression
 [ 3 ] [
     100001 f <array> 3 100000 pick set-nth
index 549d492d20e1061c6a8a3ebc28bceb03e78cd1ca..e5b75bb5b0e0261799023cc11842444d12844d24 100755 (executable)
@@ -6,6 +6,7 @@ definitions system layouts vectors math.partial-dispatch
 math.order math.functions accessors hashtables classes assocs
 io.encodings.utf8 io.encodings.ascii io.encodings fry slots
 sorting.private combinators.short-circuit grouping prettyprint
+generalizations
 compiler.tree
 compiler.tree.combinators
 compiler.tree.cleanup
@@ -518,3 +519,23 @@ cell-bits 32 = [
     [ { integer integer } declare + drop ]
     { + +-integer-integer } inlined?
 ] unit-test
+
+[ [ ] ] [
+    [
+        20 f <array>
+        [ 0 swap nth ] keep
+        [ 1 swap nth ] keep
+        [ 2 swap nth ] keep
+        [ 3 swap nth ] keep
+        [ 4 swap nth ] keep
+        [ 5 swap nth ] keep
+        [ 6 swap nth ] keep
+        [ 7 swap nth ] keep
+        [ 8 swap nth ] keep
+        [ 9 swap nth ] keep
+        [ 10 swap nth ] keep
+        [ 11 swap nth ] keep
+        [ 12 swap nth ] keep
+        14 ndrop
+    ] cleaned-up-tree nodes>quot
+] unit-test
\ No newline at end of file
index c9b73808a12a9e97b70685375193c4489070a822..5134a67a5bb53edf0cce2f3d010ee1a7fa6cf9cf 100755 (executable)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel accessors words assocs sequences arrays namespaces
-fry locals definitions classes.algebra
+fry locals definitions classes classes.algebra generic
 stack-checker.state
 stack-checker.backend
 compiler.tree
@@ -9,8 +9,13 @@ compiler.tree.propagation.info
 compiler.tree.dead-code.liveness ;
 IN: compiler.tree.dead-code.simple
 
-: flushable? ( word -- ? )
-    [ "flushable" word-prop ] [ "predicating" word-prop ] bi or ;
+GENERIC: flushable? ( word -- ? )
+
+M: predicate flushable? drop t ;
+
+M: word flushable? "flushable" word-prop ;
+
+M: method-body flushable? "method-generic" word-prop flushable? ;
 
 : flushable-call? ( #call -- ? )
     dup word>> dup flushable? [
index d1f5b03be0b6e3292e36fd9d14d975743a0ec55d..d9abb27fcfb24ec5c166564e5da1588905715b37 100644 (file)
@@ -20,7 +20,6 @@ SYMBOL: check-optimizer?
 
 : ?check ( nodes -- nodes' )
     check-optimizer? get [
-        compute-def-use
         dup check-nodes
     ] when ;
 
index 86cd53712d6bb2049aeb675b4659e437ac596728..96a99f4d5e4c86e94ef359f830f4abc120114e5d 100755 (executable)
@@ -1,6 +1,6 @@
-! Copyright (C) 2005, 2008 Slava Pestov.
+! Copyright (C) 2005, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: locals alien.c-types alien.syntax arrays kernel
+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
@@ -97,13 +97,12 @@ M: float-regs store-return-reg
     align-stack incr-stack-reg ;
 
 : with-aligned-stack ( n quot -- )
-    [ [ align-sub ] [ call ] bi* ]
-    [ [ align-add ] [ drop ] bi* ] 2bi ; inline
+    '[ align-sub @ ] [ align-add ] bi ; inline
 
 M: x86.32 %prologue ( n -- )
     dup PUSH
     0 PUSH rc-absolute-cell rel-this
-    stack-reg swap 3 cells - SUB ;
+    3 cells - decr-stack-reg ;
 
 M: object %load-param-reg 3drop ;
 
index f81490bcf2c09a3306c5150ee6f8df8d70f5f17e..da6a589031ed0ae9aa8d1aff2ef0f361f500f990 100644 (file)
@@ -3,8 +3,9 @@
 USING: parser lexer kernel namespaces sequences definitions
 io.files io.backend io.pathnames io summary continuations
 tools.crossref vocabs.hierarchy prettyprint source-files
-source-files.errors assocs vocabs vocabs.loader splitting
+source-files.errors assocs vocabs.loader splitting
 accessors debugger help.topics ;
+FROM: vocabs => vocab-name >vocab-link ;
 IN: editors
 
 TUPLE: no-edit-hook ;
@@ -15,7 +16,7 @@ M: no-edit-hook summary
 SYMBOL: edit-hook
 
 : available-editors ( -- seq )
-    "editors" all-child-vocabs-seq [ vocab-name ] map ;
+    "editors" child-vocabs no-roots no-prefixes [ vocab-name ] map ;
 
 : editor-restarts ( -- alist )
     available-editors
index 63cbcb3f1ed0f63e80e9eb61fd5686ddce2f4095..3bcc8151911fb042ccab52becf2966e8c78f743c 100644 (file)
@@ -42,7 +42,8 @@ M: more-completions article-content
     [ dup name>> >lower ] { } map>assoc ;
 
 : vocab-candidates ( -- candidates )
-    all-vocabs-seq [ dup vocab-name >lower ] { } map>assoc ;
+    all-vocabs-recursive no-roots no-prefixes
+    [ dup vocab-name >lower ] { } map>assoc ;
 
 : help-candidates ( seq -- candidates )
     [ [ >link ] [ article-title >lower ] bi ] { } map>assoc
index fbfc42829ee1faaf1d03f2716962ccad2ac48dcb..84f708a6870a4a39754061286c4b6355ad7f6a0b 100644 (file)
@@ -5,7 +5,8 @@ io.files io.files.temp io.directories html.streams help kernel
 assocs sequences make words accessors arrays help.topics vocabs
 vocabs.hierarchy help.vocabs namespaces prettyprint io
 vocabs.loader serialize fry memoize unicode.case math.order
-sorting debugger html xml.syntax xml.writer math.parser ;
+sorting debugger html xml.syntax xml.writer math.parser
+sets hashtables ;
 FROM: io.encodings.ascii => ascii ;
 FROM: ascii => ascii? ;
 IN: help.html
@@ -24,6 +25,7 @@ IN: help.html
             { CHAR: / "__slash__" }
             { CHAR: , "__comma__" }
             { CHAR: @ "__at__" }
+            { CHAR: # "__hash__" }
         } at [ % ] [ , ] ?if
     ] [ number>string "__" "__" surround % ] if ;
 
@@ -71,9 +73,7 @@ M: topic url-of topic>filename ;
     dup topic>filename utf8 [ help>html write-xml ] with-file-writer ;
 
 : all-vocabs-really ( -- seq )
-    #! Hack.
-    all-vocabs values concat
-    vocabs [ find-vocab-root not ] filter [ vocab ] map append ;
+    all-vocabs >hashtable f over delete-at no-roots remove-redundant-prefixes ;
 
 : all-topics ( -- topics )
     [
index 1fb836427ae76e5674f7cec97565b0413cc7dafd..e0cea42b4fa9fcf35b83795623be66aaec87a135 100755 (executable)
@@ -5,6 +5,7 @@ help.topics io kernel namespaces parser sequences
 source-files.errors vocabs.hierarchy vocabs words classes
 locals tools.errors listener ;
 FROM: help.lint.checks => all-vocabs ;
+FROM: vocabs => child-vocabs ;
 IN: help.lint
 
 SYMBOL: lint-failures
@@ -79,7 +80,7 @@ PRIVATE>
 : help-lint ( prefix -- )
     [
         auto-use? off
-        all-vocabs-seq [ vocab-name ] map all-vocabs set
+        all-vocab-names all-vocabs set
         group-articles vocab-articles set
         child-vocabs
         [ check-vocab ] each
index b23143e57287aaf427d64a60f331a6cf531d0bfe..7d994936911ce6360b77744fef13d8cdd308662a 100644 (file)
@@ -8,6 +8,7 @@ help.topics io io.files io.pathnames io.styles kernel macros
 make namespaces prettyprint sequences sets sorting summary
 vocabs vocabs.files vocabs.hierarchy vocabs.loader
 vocabs.metadata words words.symbol definitions.icons ;
+FROM: vocabs.hierarchy => child-vocabs ;
 IN: help.vocabs
 
 : about ( vocab -- )
@@ -35,7 +36,7 @@ IN: help.vocabs
     $heading ;
 
 : $vocabs ( seq -- )
-    [ vocab-row ] map vocab-headings prefix $table ;
+    convert-prefixes [ vocab-row ] map vocab-headings prefix $table ;
 
 : $vocab-roots ( assoc -- )
     [
@@ -67,7 +68,8 @@ C: <vocab-author> vocab-author
     ] unless-empty ;
 
 : describe-children ( vocab -- )
-    vocab-name all-child-vocabs $vocab-roots ;
+    vocab-name child-vocabs
+    $vocab-roots ;
 
 : files. ( seq -- )
     snippet-style get [
index 2f6bcfafe9540150229b2ce27c5db7c9c85ce004..016e347e89bc2b66d62d5c2a8a983f3215cef796 100644 (file)
@@ -12,8 +12,6 @@ IN: http.client
 
 ERROR: too-many-redirects ;
 
-CONSTANT: max-redirects 10
-
 <PRIVATE
 
 : write-request-line ( request -- request )
@@ -79,7 +77,7 @@ SYMBOL: redirects
 
 :: do-redirect ( quot: ( chunk -- ) response -- response )
     redirects inc
-    redirects get max-redirects < [
+    redirects get request get redirects>> < [
         request get clone
         response "location" header redirect-url
         response code>> 307 = [ "GET" >>method ] unless
@@ -116,7 +114,8 @@ SYMBOL: redirects
                 with-output-stream*
             ] [
                 in>> [
-                    read-response dup redirect? [ t ] [
+                    read-response dup redirect?
+                    request get redirects>> 0 > and [ t ] [
                         [ nip response set ]
                         [ read-response-body ]
                         [ ]
index 413ae7bd85e3e839c074d40601baf0d393878f13..3688f3819381c49243d1a3fbc1d38b2f2283c699 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel summary debugger io make math.parser
-prettyprint http.client accessors ;
+prettyprint http http.client accessors ;
 IN: http.client.debugger
 
 M: too-many-redirects summary
index 210066176f6ecd1378c4b18384c92e22bc48e782..e7ff38ac42eeee02db3e6f0c72c7c886049a38f8 100644 (file)
@@ -17,6 +17,7 @@ $nl
     { { $slot "header" } { "An assoc of HTTP header values. See " { $link "http.headers" } } }
     { { $slot "post-data" } { "See " { $link "http.post-data" } } }
     { { $slot "cookies" } { "A sequence of HTTP cookies. See " { $link "http.cookies" } } }
+    { { $slot "redirects" } { "Number of redirects to attempt before throwing an error. Default is " { $snippet "max-redirects" } " ." } }
 } } ;
 
 HELP: <response>
index 2b68edfb8e3f0f6e50873e21d5bd6426c9fc0884..4c32954eee29cddac0b1de331530209bb6ec3e02 100755 (executable)
@@ -10,6 +10,8 @@ http.parsers
 base64 ;
 IN: http
 
+CONSTANT: max-redirects 10
+
 : (read-header) ( -- alist )
     [ read-crlf dup f like ] [ parse-header-line ] produce nip ;
 
@@ -137,7 +139,8 @@ url
 version
 header
 post-data
-cookies ;
+cookies
+redirects ;
 
 : set-header ( request/response value key -- request/response )
     pick header>> set-at ;
@@ -154,7 +157,8 @@ cookies ;
         H{ } clone >>header
         V{ } clone >>cookies
         "close" "connection" set-header
-        "Factor http.client" "user-agent" set-header ;
+        "Factor http.client" "user-agent" set-header
+        max-redirects >>redirects ;
 
 : header ( request/response key -- value )
     swap header>> at ;
index e1b1daa75ce98292663e408682514dda3cf1b353..83fabeafebe024f42c983cbd06988aad9539402b 100755 (executable)
@@ -23,7 +23,7 @@ UNION: component-order
     INTENSITY DEPTH DEPTH-STENCIL R RG ;
 
 UNION: component-type
-    ubyte-components ushort-components
+    ubyte-components ushort-components uint-components
     half-components float-components
     byte-integer-components ubyte-integer-components
     short-integer-components ushort-integer-components
@@ -40,6 +40,16 @@ UNION: unnormalized-integer-components
     short-integer-components ushort-integer-components
     int-integer-components uint-integer-components ;
 
+UNION: signed-unnormalized-integer-components
+    byte-integer-components 
+    short-integer-components 
+    int-integer-components ;
+
+UNION: unsigned-unnormalized-integer-components
+    ubyte-integer-components
+    ushort-integer-components
+    uint-integer-components ;
+
 UNION: packed-components
     u-5-5-5-1-components u-5-6-5-components
     u-10-10-10-2-components
@@ -109,13 +119,15 @@ GENERIC: load-image* ( path class -- image )
         { RG [ 2 ] }
     } case ;
 
-: bytes-per-pixel ( image -- n )
-    dup component-type>> packed-components?
-    [ component-type>> bytes-per-packed-pixel ] [
-        [ component-order>> component-count ]
-        [ component-type>>  bytes-per-component ] bi *
+: (bytes-per-pixel) ( component-order component-type -- n )
+    dup packed-components?
+    [ nip bytes-per-packed-pixel ] [
+        [ component-count ] [ bytes-per-component ] bi* *
     ] if ;
 
+: bytes-per-pixel ( image -- n )
+    [ component-order>> ] [ component-type>> ] bi (bytes-per-pixel) ;
+
 <PRIVATE
 
 : pixel@ ( x y image -- start end bitmap )
index d6bee78c145efe2ddbeae4bb101e8aa0013cfb14..b9391625771c160609ff8fc7601d9d743d96cf96 100644 (file)
@@ -1,7 +1,8 @@
 ! Copyright (C) 2005, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors arrays columns kernel math math.bits
-math.order math.vectors sequences sequences.private fry ;
+USING: accessors arrays columns kernel locals math math.bits
+math.functions math.order math.vectors sequences
+sequences.private fry ;
 IN: math.matrices
 
 ! Matrices
@@ -12,6 +13,80 @@ IN: math.matrices
     #! Make a nxn identity matrix.
     dup [ [ = 1 0 ? ] with map ] curry map ;
 
+:: rotation-matrix3 ( axis theta -- matrix )
+    theta cos :> c
+    theta sin :> s
+    axis first3 :> z :> y :> x
+    x sq 1.0 x sq - c * +     x y * 1.0 c - * z s * -   x z * 1.0 c - * y s * + 3array
+    x y * 1.0 c - * z s * +   y sq 1.0 y sq - c * +     y z * 1.0 c - * x s * - 3array
+    x z * 1.0 c - * y s * -   y z * 1.0 c - * x s * +   z sq 1.0 z sq - c * +   3array
+    3array ;
+
+:: rotation-matrix4 ( axis theta -- matrix )
+    theta cos :> c
+    theta sin :> s
+    axis first3 :> z :> y :> x
+    x sq 1.0 x sq - c * +     x y * 1.0 c - * z s * -   x z * 1.0 c - * y s * +   0 4array
+    x y * 1.0 c - * z s * +   y sq 1.0 y sq - c * +     y z * 1.0 c - * x s * -   0 4array
+    x z * 1.0 c - * y s * -   y z * 1.0 c - * x s * +   z sq 1.0 z sq - c * +     0 4array
+    { 0.0 0.0 0.0 1.0 } 4array ;
+
+:: translation-matrix4 ( offset -- matrix )
+    offset first3 :> z :> y :> x
+    {
+        { 1.0 0.0 0.0 x   }
+        { 0.0 1.0 0.0 y   }
+        { 0.0 0.0 1.0 z   }
+        { 0.0 0.0 0.0 1.0 }
+    } ;
+
+: >scale-factors ( number/sequence -- x y z )
+    dup number? [ dup dup ] [ first3 ] if ;
+
+:: scale-matrix3 ( factors -- matrix )
+    factors >scale-factors :> z :> y :> x
+    {
+        { x   0.0 0.0 }
+        { 0.0 y   0.0 }
+        { 0.0 0.0 z   }
+    } ;
+
+:: scale-matrix4 ( factors -- matrix )
+    factors >scale-factors :> z :> y :> x
+    {
+        { x   0.0 0.0 0.0 }
+        { 0.0 y   0.0 0.0 }
+        { 0.0 0.0 z   0.0 }
+        { 0.0 0.0 0.0 1.0 }
+    } ;
+
+: ortho-matrix4 ( dim -- matrix )
+    [ recip ] map scale-matrix4 ;
+
+:: frustum-matrix4 ( xy-dim near far -- matrix )
+    xy-dim first2 :> y :> x
+    near x /f :> xf
+    near y /f :> yf
+    near far + near far - /f :> zf
+    2 near far * * near far - /f :> wf
+
+    {
+        { xf  0.0  0.0 0.0 }
+        { 0.0 yf   0.0 0.0 }
+        { 0.0 0.0  zf  wf  }
+        { 0.0 0.0 -1.0 0.0 }
+    } ;
+
+:: skew-matrix4 ( theta -- matrix )
+    theta tan :> zf
+
+    {
+        { 1.0 0.0 0.0 0.0 }
+        { 0.0 1.0 0.0 0.0 }
+        { 0.0 zf  1.0 0.0 }
+        { 0.0 0.0 0.0 1.0 }
+    } ;
+
 ! Matrix operations
 : mneg ( m -- m ) [ vneg ] map ;
 
index 968af6a3aa6159fa2956d88a65ebdf906e5d9b95..3e56644d3e9e18c222155a91a168204b263f55d1 100644 (file)
@@ -16,3 +16,5 @@ USING: math.vectors tools.test ;
 [ { 1.75 2.125 } ] [ { 1.0 2.5 } { 2.5 1.0 } { 0.5 0.25 } vlerp ] unit-test 
 
 [ 1.125 ] [ 0.0 1.0 2.0 4.0 { 0.5 0.25 } bilerp ] unit-test
+
+[ 17 ] [ 0 1 2 3 4 5 6 7 { 1 2 3 } trilerp ] unit-test
\ No newline at end of file
index 7d79516a2ce38046f068c76bc01998ce6ee538d8..bb5847e734f84bdcff77c254311c26832e15696f 100644 (file)
@@ -128,12 +128,12 @@ MACRO: all-enabled-client-state ( seq quot -- )
 : (gen-gl-object) ( quot -- id )
     [ 1 0 <uint> ] dip keep *uint ; inline
 
-: gen-gl-buffer ( -- id )
-    [ glGenBuffers ] (gen-gl-object) ;
-
 : (delete-gl-object) ( id quot -- )
     [ 1 swap <uint> ] dip call ; inline
 
+: gen-gl-buffer ( -- id )
+    [ glGenBuffers ] (gen-gl-object) ;
+
 : delete-gl-buffer ( id -- )
     [ glDeleteBuffers ] (delete-gl-object) ;
 
@@ -146,6 +146,16 @@ MACRO: all-enabled-client-state ( seq quot -- )
         GL_ARRAY_BUFFER swap _ with-gl-buffer
     ] with-gl-buffer ; inline
 
+: gen-vertex-array ( -- id )
+    [ glGenVertexArrays ] (gen-gl-object) ;
+
+: delete-vertex-array ( id -- )
+    [ glDeleteVertexArrays ] (delete-gl-object) ;
+
+:: with-vertex-array ( id quot -- )
+    id glBindVertexArray
+    quot [ 0 glBindVertexArray ] [ ] cleanup ; inline
+
 : <gl-buffer> ( target data hint -- id )
     pick gen-gl-buffer [
         [
index e908fd81470054edbccbcf80a9b75042523eaf78..96aa7b24f29f46f5ed6c493388bd606a2616f091 100644 (file)
@@ -5,4 +5,4 @@ USING: tools.test vocabs.hierarchy present math vocabs sequences kernel ;
 [ "Hi" ] [ "Hi" present ] unit-test
 [ "+" ] [ \ + present ] unit-test
 [ "kernel" ] [ "kernel" vocab present ] unit-test
-[ ] [ all-vocabs-seq [ present ] map drop ] unit-test
\ No newline at end of file
+[ ] [ all-vocabs-recursive no-roots no-prefixes [ present ] map drop ] unit-test
\ No newline at end of file
index 465d1665f992c84d15ccb98757e7f84922c8af67..a2bca17a9ae0fb19d2d7b7a846b92c50113e1a48 100644 (file)
@@ -1,4 +1,5 @@
 USE: specialized-arrays.functor
 IN: specialized-arrays.alien
 
-<< "void*" define-array >>
\ No newline at end of file
+<< "void*" define-array >>
+<< "ptrdiff_t" define-array >>
diff --git a/basis/stuff.factor b/basis/stuff.factor
new file mode 100644 (file)
index 0000000..2e5fa2d
--- /dev/null
@@ -0,0 +1,20 @@
+
+: 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-float@ ( n -- offset )
+    double-float-regs reg-size * param@ ;
+
+: (stack-frame-size) ( stack-frame -- n )
+    [
+        {
+            [ spill-counts>> [ swap reg-size * ] { } assoc>map sum ]
+            [ gc-roots>> cells ]
+            [ params>> ]
+            [ return>> ]
+        } cleave
+    ] sum-outputs ;
\ No newline at end of file
index cacc628e2a5a6c7dff401bbc2cbf51b0f056de62..dec44625f72a74b10a023942b46fcc9cabc5183f 100644 (file)
@@ -43,13 +43,15 @@ sleep-entry ;
 : thread-registered? ( thread -- ? )
     id>> threads key? ;
 
+ERROR: already-stopped thread ;
+
 : check-unregistered ( thread -- thread )
-    dup thread-registered?
-    [ "Thread already stopped" throw ] when ;
+    dup thread-registered? [ already-stopped ] when ;
+
+ERROR: not-running thread ;
 
 : check-registered ( thread -- thread )
-    dup thread-registered?
-    [ "Thread is not running" throw ] unless ;
+    dup thread-registered? [ not-running ] unless ;
 
 <PRIVATE
 
index c312b54edb69b9d8df6b15f57c62da2e0a621cd9..79aef90bead4b36f435a93d3fa973337b245315e 100644 (file)
@@ -49,3 +49,14 @@ M: string blah-generic ;
 [ ] [ M\ string blah-generic watch ] unit-test
 
 [ "hi" ] [ "hi" blah-generic ] unit-test
+
+! See how well watch interacts with optimizations.
+GENERIC: my-generic ( a -- b )
+M: object my-generic ;
+
+\ my-generic watch
+
+: some-code ( -- )
+    f my-generic drop ;
+
+[ ] [ some-code ] unit-test
\ No newline at end of file
index 3aac371a6ada19d26c6e5dd87157781003ef0b1a..e7e5837ee8315aa2d2e4e98040304c3659d2129c 100644 (file)
@@ -3,7 +3,8 @@
 USING: accessors kernel math sorting words parser io summary
 quotations sequences prettyprint continuations effects
 definitions compiler.units namespaces assocs tools.walker
-tools.time generic inspector fry tools.continuations ;
+tools.time generic inspector fry tools.continuations
+locals generalizations macros ;
 IN: tools.annotations
 
 GENERIC: reset ( word -- )
@@ -46,17 +47,20 @@ M: word annotate
 
 <PRIVATE
 
-: stack-values ( names -- alist )
-    [ datastack ] dip [ nip ] [ length tail* ] 2bi zip ;
-
-: trace-message ( word quot str -- )
-    "--- " write write bl over .
-    [ stack-effect ] dip '[ @ stack-values ] [ f ] if*
-    [ simple-table. ] unless-empty flush ; inline
+:: trace-quot ( word effect quot str -- quot' )
+    effect quot call :> values
+    values length :> n
+    [
+        "--- " write str write bl word .
+        n ndup n narray values swap zip simple-table.
+        flush
+    ] ; inline
 
-: entering ( str -- ) [ in>> ] "Entering" trace-message ;
+MACRO: entering ( word -- quot )
+    dup stack-effect [ in>> ] "Entering" trace-quot ;
 
-: leaving ( str -- ) [ out>> ] "Leaving" trace-message ;
+MACRO: leaving ( word -- quot )
+    dup stack-effect [ out>> ] "Leaving" trace-quot ;
 
 : (watch) ( word def -- def )
     over '[ _ entering @ _ leaving ] ;
index c8fd3a6658a2b8547e8c7b0f9d876273e8353b52..fb664c495c35f5e5553b0d465d58e79c5eca4d32 100644 (file)
@@ -75,7 +75,7 @@ IN: tools.completion
     all-words name-completions ;
 
 : vocabs-matching ( str -- seq )
-    all-vocabs-seq name-completions ;
+    all-vocabs-recursive no-roots no-prefixes name-completions ;
 
 : chars-matching ( str -- seq )
     name-map keys dup zip completions ;
index 3d38439f6914e865e09deaa110c75a5b18501f9f..62636fdcdfd2350cef521f26540dc1a02b9a910a 100755 (executable)
@@ -27,10 +27,6 @@ GENERIC: flush-gl-context ( handle -- )
 
 HOOK: offscreen-pixels ui-backend ( world -- alien w h )
 
-: with-gl-context ( handle quot -- )
-    '[ select-gl-context @ ]
-    [ flush-gl-context gl-error ] bi ; inline
-
 HOOK: (with-ui) ui-backend ( quot -- )
 
 HOOK: (grab-input) ui-backend ( handle -- )
index 2c5ed596acdb269639aa8ab1385e2f626ce9dd03..6f68c32ff0455e53a655d558d8ae6e09739c3e38 100644 (file)
@@ -397,8 +397,8 @@ M: f sloppy-pick-up*
     ] [ drop ] if ;
 
 : end-selection ( pane -- )
-    f >>selecting?
-    hand-moved?
+    dup selecting?>> hand-moved? or
+    [ f >>selecting? ] dip
     [ [ com-copy-selection ] [ request-focus ] bi ]
     [ [ relayout-1 ] [ focus-input ] bi ]
     if ;
index 390e652ac6c80c275617aa6cd2008593421439fa..3beb0af79f946a75cbe630b046a982005c725a2a 100644 (file)
@@ -313,13 +313,14 @@ PRIVATE>
     if ;
 
 : row-action? ( table -- ? )
-    [ [ mouse-row ] keep valid-line? ]
-    [ single-click?>> hand-click# get 2 = or ] bi and ;
+    single-click?>> hand-click# get 2 = or ;
 
 <PRIVATE
 
 : table-button-up ( table -- )
-    dup row-action? [ row-action ] [ update-selected-value ] if ;
+    dup [ mouse-row ] keep valid-line? [
+        dup row-action? [ row-action ] [ update-selected-value ] if
+    ] [ drop ] if ;
 
 PRIVATE>
 
index d0fd169871eb9deca394f5e796ef93cf0df8d46e..ddaad93b1b185881998366c5eb76052eff99f804 100755 (executable)
@@ -1,6 +1,6 @@
 USING: ui.gadgets ui.render ui.text ui.text.private
 ui.gestures ui.backend help.markup help.syntax
-models opengl sequences strings ;
+models opengl sequences strings destructors ;
 IN: ui.gadgets.worlds
 
 HELP: user-input
@@ -29,10 +29,17 @@ HELP: set-title
 { $description "Sets the title bar of the native window containing the world." }
 { $notes "This word should not be called directly by user code. Instead, change the " { $snippet "title" } " slot model; see " { $link "models" } "." } ;
 
-HELP: select-gl-context
-{ $values { "handle" "a backend-specific handle" } }
+HELP: context-world
+{ $var-description "Holds the " { $link world } " whose OpenGL context was most recently made active by " { $link set-gl-context } "." } ;
+
+HELP: set-gl-context
+{ $values { "world" world } }
 { $description "Selects an OpenGL context to be the implicit destination for subsequent GL rendering calls. This word is called automatically by the UI before drawing a " { $link world } "." } ;
 
+HELP: window-resource
+{ $values { "resource" disposable } { "resource" disposable } }
+{ $description "Marks " { $snippet "resource" } " to be destroyed with " { $link dispose } " when the window with the currently active OpenGL context (set by " { $link set-gl-context } ") is closed. " { $snippet "resource" } " is left unmodified at the top of the stack." } ;
+
 HELP: flush-gl-context
 { $values { "handle" "a backend-specific handle" } }
 { $description "Ensures all GL rendering calls made to an OpenGL context finish rendering to the screen. This word is called automatically by the UI after drawing a " { $link world } "." } ;
index 82f3637b83f5402fc4ec93136bc88aefbde93bcf..ed21c85b19a315c1c8a8956ad53c2682c1f5f3e0 100755 (executable)
@@ -34,7 +34,8 @@ TUPLE: world < track
     text-handle handle images
     window-loc
     pixel-format-attributes
-    window-controls ;
+    window-controls
+    window-resources ;
 
 TUPLE: world-attributes
     { world-class initial: world }
@@ -77,11 +78,24 @@ TUPLE: world-attributes
         '[ f _ [ (>>status-owner) ] [ status>> set-model ] 2bi ] when
     ] [ 2drop ] if ;
 
+SYMBOL: context-world
+
+: window-resource ( resource -- resource )
+    dup context-world get-global window-resources>> push ;
+
+: set-gl-context ( world -- )
+    [ context-world set-global ]
+    [ handle>> select-gl-context ] bi ;
+
+: with-gl-context ( world quot -- )
+    '[ set-gl-context @ ]
+    [ handle>> flush-gl-context gl-error ] bi ; inline
+
 ERROR: no-world-found ;
 
 : find-gl-context ( gadget -- )
     find-world dup
-    [ handle>> select-gl-context ] [ no-world-found ] if ;
+    [ set-gl-context ] [ no-world-found ] if ;
 
 : (request-focus) ( child world ? -- )
     pick parent>> pick eq? [
@@ -98,7 +112,8 @@ M: world request-focus-on ( child gadget -- )
         t >>root?
         f >>active?
         { 0 0 } >>window-loc
-        f >>grab-input? ;
+        f >>grab-input?
+        V{ } clone >>window-resources ;
 
 : apply-world-attributes ( world attributes -- world )
     {
@@ -149,8 +164,8 @@ M: world (>>dim)
     [ call-next-method ]
     [
         dup handle>>
-        [ select-gl-context resize-world ]
-        [ drop ] if*
+        [ [ set-gl-context ] [ resize-world ] bi ]
+        [ drop ] if
     ] bi ;
 
 GENERIC: draw-world* ( world -- )
@@ -184,7 +199,7 @@ ui-error-hook [ [ rethrow ] ] initialize
     dup draw-world? [
         dup world [
             [
-                dup handle>> [ draw-world* ] with-gl-context
+                dup [ draw-world* ] with-gl-context
                 flush-layout-cache-hook get call( -- )
             ] [
                 over <world-error> ui-error
index f215e297ffcb7de1ec41c0722db13c638b592c9d..760b959e78b3c4c01745d6847f3adedc9917b776 100644 (file)
@@ -63,6 +63,7 @@ M: definition-completion row-columns
 
 M: word-completion row-color
     [ vocabulary>> ] [ manifest>> ] bi* {
+        { [ dup not ] [ COLOR: black ] }
         { [ 2dup search-vocabs>> memq? ] [ COLOR: black ] }
         { [ over ".private" tail? ] [ COLOR: dark-red ] }
         [ COLOR: dark-gray ]
index 5a2e3cf1b5bf66c78e7868fc7873cde385848d3e..068673889a515076f37b6fe00699cc332762c4ef 100644 (file)
@@ -52,3 +52,16 @@ IN: ui.tools.listener.history.tests
 [ ] [ "h" get history-recall-previous ] unit-test
 
 [ "22" ] [ "d" get doc-string ] unit-test
+
+[ ] [ <document> "d" set ] unit-test
+[ ] [ "d" get <history> "h" set ] unit-test
+
+[ ] [ "aaa" "d" get set-doc-string ] unit-test
+[ T{ input f "aaa" } ] [ "h" get history-add ] unit-test
+
+[ ] [ "" "d" get set-doc-string ] unit-test
+[ T{ input f "" } ] [ "h" get history-add ] unit-test
+[ T{ input f "" } ] [ "h" get history-add ] unit-test
+[ ] [ "   " "d" get set-doc-string ] unit-test
+[ ] [ "h" get history-recall-previous ] unit-test
+
index 333347dbac52b74e1cfec04263ce6c7538a55871..5e03ab21ad1242cb545377df63ceb509172d0ed8 100644 (file)
@@ -16,9 +16,15 @@ TUPLE: history document elements index ;
 
 <PRIVATE
 
+: (save-history) ( input index elements -- )
+    2dup length > [
+        [ [ T{ input f "" } ] dip push ] keep
+        (save-history)
+    ] [ set-nth ] if ;
+
 : save-history ( history -- )
     [ document>> doc-string ] keep
-    '[ <input> _ [ index>> ] [ elements>> ] bi set-nth ]
+    '[ <input> _ [ index>> ] [ elements>> ] bi (save-history) ]
     unless-empty ;
 
 : update-document ( history -- )
index 7ea34e651fc5639c3be1543b3702ea89f5134e8d..42bc0ef1f22d7b58a023badf037ce67418b7f96c 100644 (file)
@@ -26,7 +26,6 @@ tool "tool-switching" f {
 } define-command-map
 
 tool "common" f {
-    { T{ key-down f { A+ } "s" } save }
     { T{ key-down f { A+ } "w" } close-window }
     { T{ key-down f { A+ } "q" } com-exit }
     { T{ key-down f f "F2" } refresh-all }
index db05465986c35764841a77723401509dd6e15768..2486e701c0cec64c26cffb529785dc88575fdcfa 100644 (file)
@@ -61,7 +61,7 @@ SYMBOL: windows
 
 : set-up-window ( world -- )
     {
-        [ handle>> select-gl-context ]
+        [ set-gl-context ]
         [ [ title>> ] keep set-title ]
         [ begin-world ]
         [ resize-world ]
@@ -89,12 +89,13 @@ M: world graft*
 
 : (ungraft-world) ( world -- )
     {
-        [ handle>> select-gl-context ]
+        [ set-gl-context ]
         [ text-handle>> [ dispose ] when* ]
         [ images>> [ dispose ] when* ]
         [ hand-clicked close-global ]
         [ hand-gadget close-global ]
         [ end-world ]
+        [ [ <reversed> [ [ dispose ] when* ] each V{ } clone ] change-window-resources drop ]
     } cleave ;
 
 M: world ungraft*
index 552883a299331185bbdeb730c71ef755ca03e79e..9c57aab9f69f30d3e621a1146c60c75857c7f152 100644 (file)
@@ -7,11 +7,16 @@ ARTICLE: "unicode.breaks" "Word and grapheme breaks"
 "The " { $vocab-link "unicode.breaks" "unicode.breaks" } " vocabulary partially implements Unicode Standard Annex #29. This provides for segmentation of a string along grapheme and word boundaries. In Unicode, a grapheme, or a basic unit of display in text, may be more than one code point. For example, in the string \"e\\u000301\" (where U+0301 is a combining acute accent), there is only one grapheme, as the acute accent goes above the e, forming a single grapheme. Word breaks, in general, are more complicated than simply splitting by whitespace, and the Unicode algorithm provides for that."
 $nl "Operations for graphemes:"
 { $subsection first-grapheme }
+{ $subsection first-grapheme-from }
 { $subsection last-grapheme }
+{ $subsection last-grapheme-from }
 { $subsection >graphemes }
 { $subsection string-reverse }
 "Operations on words:"
 { $subsection first-word }
+{ $subsection first-word-from }
+{ $subsection last-word }
+{ $subsection last-word-from }
 { $subsection >words } ;
 
 HELP: first-grapheme
@@ -22,6 +27,14 @@ HELP: last-grapheme
 { $values { "str" string } { "i" "an index" } }
 { $description "Finds the index of the start of the last grapheme of the string. This can be used to traverse the graphemes of a string backwards." } ;
 
+HELP: first-grapheme-from
+{ $values { "start" "an index" } { "str" string } { "i" "an index" } }
+{ $description "Finds the length of the first grapheme of the string, starting from the given index. This can be used repeatedly to efficiently traverse the graphemes of the string, using slices." } ;
+
+HELP: last-grapheme-from
+{ $values { "end" "an index" } { "str" string } { "i" "an index" } }
+{ $description "Finds the index of the start of the last grapheme of the string, starting from the given index. This can be used to traverse the graphemes of a string backwards." } ;
+
 HELP: >graphemes
 { $values { "str" string } { "graphemes" "an array of strings" } }
 { $description "Divides a string into a sequence of individual graphemes." } ;
@@ -32,7 +45,19 @@ HELP: string-reverse
 
 HELP: first-word
 { $values { "str" string } { "i" "index" } }
-{ $description "Finds the length of the first word in the string." } ;
+{ $description "Finds the index of the end of the first word in the string." } ;
+
+HELP: last-word
+{ $values { "str" string } { "i" "index" } }
+{ $description "Finds the index of the beginning of the last word in the string." } ;
+
+HELP: first-word-from
+{ $values { "start" "index" } { "str" string } { "i" "index" } }
+{ $description "Finds the index of the end of the first word in the string, starting from the given index." } ;
+
+HELP: last-word-from
+{ $values { "end" "index" } { "str" string } { "i" "index" } }
+{ $description "Finds the index of the start of the word that the index is contained in." } ;
 
 HELP: >words
 { $values { "str" string } { "words" "an array of strings" } }
index 6d6d4233f572f043101fa48417ae80e62b6cb036..bbce857681bd17540a928ce624a8eff2ffae4fd5 100644 (file)
@@ -12,6 +12,11 @@ IN: unicode.breaks.tests
 [ 3 ] [ 2 "hello" first-grapheme-from ] unit-test
 [ 1 ] [ 2 "hello" last-grapheme-from ] unit-test
 
+[ 4 ] [ 2 "what am I saying" first-word-from ] unit-test
+[ 0 ] [ 2 "what am I saying" last-word-from ] unit-test
+[ 16 ] [ 11 "what am I saying" first-word-from ] unit-test
+[ 10 ] [ 11 "what am I saying" last-word-from ] unit-test
+
 : grapheme-break-test ( -- filename )
     "vocab:unicode/breaks/GraphemeBreakTest.txt" ;
 
index 6d6b5cc0cfd7a858f15b1715510656a75602324d..ed96842c41ad0f58d1c2e900c8b31ed451ff55c4 100644 (file)
@@ -247,3 +247,12 @@ PRIVATE>
             word-break-next nip
         ]
     } 2|| ;
+
+: first-word-from ( start str -- i )
+    over tail-slice first-word + ;
+
+: last-word ( str -- i )
+    [ length ] keep '[ _ word-break-at? ] find-last drop 0 or ;
+
+: last-word-from ( end str -- i )
+    swap head-slice last-word ;
index 63a8d6d292f2ae65f2478fb6c55191bbcb1b5bba..24ccd391f19dd00d4d93edee04cc4f3254f40cd6 100644 (file)
@@ -7,7 +7,7 @@ IN: vocabs.cache
 : reset-cache ( -- )
     root-cache get-global clear-assoc
     \ vocab-file-contents reset-memoized
-    \ all-vocabs-seq reset-memoized
+    \ all-vocabs-recursive reset-memoized
     \ all-authors reset-memoized
     \ all-tags reset-memoized ;
 
index 3bea36258231f3519059adbfc7795e45906629f1..8eb39732c04dc2b7056edd1cea662d62d2527f44 100644 (file)
@@ -7,19 +7,21 @@ $nl
 "Loading vocabulary hierarchies:"\r
 { $subsection load }\r
 { $subsection load-all }\r
-"Getting all vocabularies on disk:"\r
+"Getting all vocabularies from disk:"\r
 { $subsection all-vocabs }\r
-{ $subsection all-vocabs-seq }\r
-"Getting " { $link "vocabs.metadata" } " for all vocabularies on disk:"\r
+{ $subsection all-vocabs-recursive }\r
+"Getting all vocabularies from disk whose names which match a string prefix:"\r
+{ $subsection child-vocabs }\r
+{ $subsection child-vocabs-recursive }\r
+"Words for modifying output:"\r
+{ $subsection no-roots }\r
+{ $subsection no-prefixes }\r
+"Getting " { $link "vocabs.metadata" } " for all vocabularies from disk:"\r
 { $subsection all-tags }\r
 { $subsection all-authors } ;\r
 \r
 ABOUT: "vocabs.hierarchy"\r
 \r
-HELP: all-vocabs\r
-{ $values { "assoc" "an association list mapping vocabulary roots to sequences of vocabulary specifiers" } }\r
-{ $description "Outputs an association list of all vocabularies which have been loaded or are available for loading." } ;\r
-\r
 HELP: load\r
 { $values { "prefix" string } }\r
 { $description "Load all vocabularies that match the provided prefix." }\r
@@ -28,6 +30,3 @@ HELP: load
 HELP: load-all\r
 { $description "Load all vocabularies in the source tree." } ;\r
 \r
-HELP: all-vocabs-under\r
-{ $values { "prefix" string } { "vocabs" "a sequence of vocabularies" } }\r
-{ $description "Return a sequence of vocab or vocab-links for each vocab matching the provided prefix. Unlike " { $link all-child-vocabs } " this word will return both loaded and unloaded vocabularies." } ;\r
index 046ccb8c2d9f1687205547113f97d6a08908ed33..aa3e619660320d69eebf17928544b341acde7bba 100644 (file)
@@ -1,11 +1,18 @@
 ! Copyright (C) 2007, 2009 Slava Pestov.\r
 ! See http://factorcode.org/license.txt for BSD license.\r
-USING: arrays assocs combinators.short-circuit fry\r
+USING: accessors arrays assocs combinators.short-circuit fry\r
 io.directories io.files io.files.info io.pathnames kernel make\r
 memoize namespaces sequences sorting splitting vocabs sets\r
 vocabs.loader vocabs.metadata vocabs.errors ;\r
+RENAME: child-vocabs vocabs => vocabs:child-vocabs\r
 IN: vocabs.hierarchy\r
 \r
+TUPLE: vocab-prefix name ;\r
+\r
+C: <vocab-prefix> vocab-prefix\r
+\r
+M: vocab-prefix vocab-name name>> ;\r
+\r
 <PRIVATE\r
 \r
 : vocab-subdirs ( dir -- dirs )\r
@@ -15,74 +22,92 @@ IN: vocabs.hierarchy
         ] filter\r
     ] with-directory-files natural-sort ;\r
 \r
-: (all-child-vocabs) ( root name -- vocabs )\r
-    [\r
-        vocab-dir append-path dup exists?\r
-        [ vocab-subdirs ] [ drop { } ] if\r
-    ] keep\r
-    [ '[ [ _ "." ] dip 3append ] map ] unless-empty ;\r
-\r
 : vocab-dir? ( root name -- ? )\r
     over\r
     [ ".factor" vocab-dir+ append-path exists? ]\r
     [ 2drop f ]\r
     if ;\r
 \r
-: vocabs-in-dir ( root name -- )\r
-    dupd (all-child-vocabs) [\r
-        2dup vocab-dir? [ dup >vocab-link , ] when\r
-        vocabs-in-dir\r
-    ] with each ;\r
+: (child-vocabs) ( root prefix -- vocabs )\r
+    [ vocab-dir append-path dup exists? [ vocab-subdirs ] [ drop { } ] if ]\r
+    [ nip [ '[ [ _ "." ] dip 3append ] map ] unless-empty ]\r
+    [ drop '[ _ over vocab-dir? [ >vocab-link ] [ <vocab-prefix> ] if ] map ]\r
+    2tri ;\r
 \r
-PRIVATE>\r
+: ((child-vocabs-recursive)) ( root name -- )\r
+    dupd vocab-name (child-vocabs)\r
+    [ dup , ((child-vocabs-recursive)) ] with each ;\r
 \r
-: all-vocabs ( -- assoc )\r
-    vocab-roots get [\r
-        dup [ "" vocabs-in-dir ] { } make\r
-    ] { } map>assoc ;\r
-\r
-: all-vocabs-under ( prefix -- vocabs )\r
-    [\r
-        [ vocab-roots get ] dip '[ _ vocabs-in-dir ] each\r
-    ] { } make ;\r
+: (child-vocabs-recursive) ( root name -- seq )\r
+    [ ((child-vocabs-recursive)) ] { } make ;\r
 \r
-MEMO: all-vocabs-seq ( -- seq )\r
-    "" all-vocabs-under ;\r
+: no-rooted ( seq -- seq' ) [ find-vocab-root not ] filter ;\r
 \r
-<PRIVATE\r
+: one-level-only? ( name prefix -- ? )\r
+    ?head [ "." split1 nip not ] dip and ;\r
 \r
 : unrooted-child-vocabs ( prefix -- seq )\r
+    [ vocabs no-rooted ] dip\r
     dup empty? [ CHAR: . suffix ] unless\r
-    vocabs\r
-    [ find-vocab-root not ] filter\r
-    [\r
-        vocab-name swap ?head CHAR: . rot member? not and\r
-    ] with filter\r
-    [ vocab ] map ;\r
+    '[ vocab-name _ one-level-only? ] filter ;\r
+\r
+: unrooted-child-vocabs-recursive ( prefix -- seq )\r
+    vocabs:child-vocabs no-rooted ;\r
 \r
 PRIVATE>\r
 \r
-: all-child-vocabs ( prefix -- assoc )\r
-    vocab-roots get [\r
-        dup pick (all-child-vocabs) [ >vocab-link ] map\r
-    ] { } map>assoc\r
-    swap unrooted-child-vocabs f swap 2array suffix ;\r
+: no-prefixes ( seq -- seq' ) [ vocab-prefix? not ] filter ;\r
 \r
-: all-child-vocabs-seq ( prefix -- assoc )\r
-    vocab-roots get swap '[\r
-        dup _ (all-child-vocabs)\r
-        [ vocab-dir? ] with filter\r
-    ] map concat ;\r
+: convert-prefixes ( seq -- seq' )\r
+    [ dup vocab-prefix? [ name>> vocab-link boa ] when ] map ;\r
+\r
+: remove-redundant-prefixes ( seq -- seq' )\r
+    #! Hack.\r
+    [ vocab-prefix? ] partition\r
+    [\r
+        [ vocab-name ] map unique\r
+        '[ name>> _ key? not ] filter\r
+        convert-prefixes\r
+    ] keep\r
+    append ;\r
+\r
+: no-roots ( assoc -- seq ) values concat ;\r
+\r
+: child-vocabs ( prefix -- assoc )\r
+    [ [ vocab-roots get ] dip '[ dup _ (child-vocabs) ] { } map>assoc ]\r
+    [ unrooted-child-vocabs [ vocab ] map f swap 2array ]\r
+    bi suffix ;\r
+\r
+: all-vocabs ( -- assoc )\r
+    "" child-vocabs ;\r
+\r
+: child-vocabs-recursive ( prefix -- assoc )\r
+    [ [ vocab-roots get ] dip '[ dup _ (child-vocabs-recursive) ] { } map>assoc ]\r
+    [ unrooted-child-vocabs-recursive [ vocab ] map f swap 2array ]\r
+    bi suffix ;\r
+\r
+MEMO: all-vocabs-recursive ( -- assoc )\r
+    "" child-vocabs-recursive ;\r
+\r
+: all-vocab-names ( -- seq )\r
+    all-vocabs-recursive no-roots no-prefixes [ vocab-name ] map ;\r
+\r
+: child-vocab-names ( prefix -- seq )\r
+    child-vocabs no-roots no-prefixes [ vocab-name ] map ;\r
 \r
 <PRIVATE\r
 \r
 : filter-unportable ( seq -- seq' )\r
     [ vocab-name unportable? not ] filter ;\r
 \r
+: collect-vocabs ( quot -- seq )\r
+    [ all-vocabs-recursive no-roots no-prefixes ] dip\r
+    gather natural-sort ; inline\r
+\r
 PRIVATE>\r
 \r
 : (load) ( prefix -- failures )\r
-    all-vocabs-under\r
+    child-vocabs-recursive no-roots no-prefixes\r
     filter-unportable\r
     require-all ;\r
 \r
@@ -92,8 +117,6 @@ PRIVATE>
 : load-all ( -- )\r
     "" load ;\r
 \r
-MEMO: all-tags ( -- seq )\r
-    all-vocabs-seq [ vocab-tags ] gather natural-sort ;\r
+MEMO: all-tags ( -- seq ) [ vocab-tags ] collect-vocabs ;\r
 \r
-MEMO: all-authors ( -- seq )\r
-    all-vocabs-seq [ vocab-authors ] gather natural-sort ;
\ No newline at end of file
+MEMO: all-authors ( -- seq ) [ vocab-authors ] collect-vocabs ;\r
index 07f42caae36112ced1e7101dcf693094e3ce0bdc..cf01499bcb8561335a475cbfe859654f88f8affb 100644 (file)
@@ -39,3 +39,6 @@ word wrap.">
 [ "aaa bb\nccccccc\nddddddd" ] [ "aaa bb ccccccc ddddddd" 6 wrap-string ] unit-test
 
 [ "a b c d e f\ng h" ] [ "a b c d e f g h" 11 wrap-string ] unit-test
+
+[ "" ] [ "" 10 wrap-string ] unit-test
+[ "Hello" ] [ "\nHello\n" 10 wrap-string ] unit-test
diff --git a/basis/wrap/wrap-tests.factor b/basis/wrap/wrap-tests.factor
new file mode 100644 (file)
index 0000000..e597b95
--- /dev/null
@@ -0,0 +1,5 @@
+! Copyright (C) 2009 Daniel Ehrenberg
+! See http://factorcode.org/license.txt for BSD license.
+USING: wrap tools.test ;
+
+[ { } ] [ { } 10 10 wrap ] unit-test
index c648f6bd61bdef0408bac6b111a48d3e2c9b2cf0..b28b0bcbff98e84648ed609cf476ec91ce9cddde 100644 (file)
@@ -77,8 +77,10 @@ SYMBOL: line-ideal
     [
         line-ideal set
         line-max set
-        initialize
-        [ wrap-step ] reduce
-        min-cost
-        post-process
+        [ { } ] [
+            initialize
+            [ wrap-step ] reduce
+            min-cost
+            post-process
+        ] if-empty
     ] with-scope ;
index 6c64e34835fba1ea903e89ff265389695da0e3f9..ca71e22e9fa12db0ec820f84a8f22d4b52d9b47c 100755 (executable)
@@ -13,7 +13,7 @@ SYMBOL: errors
 PRIVATE>
 
 : run-benchmark ( vocab -- )
-    [ "=== " write vocab-name print flush ] [
+    [ "=== " write print flush ] [
         [ [ require ] [ gc [ run ] benchmark ] [ ] tri timings ]
         [ swap errors ]
         recover get set-at
@@ -23,7 +23,7 @@ PRIVATE>
     [
         V{ } clone timings set
         V{ } clone errors set
-        "benchmark" all-child-vocabs-seq
+        "benchmark" child-vocab-names
         [ run-benchmark ] each
         timings get
         errors get
diff --git a/extra/benchmark/hashtables/authors.txt b/extra/benchmark/hashtables/authors.txt
new file mode 100644 (file)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/extra/benchmark/hashtables/hashtables.factor b/extra/benchmark/hashtables/hashtables.factor
new file mode 100644 (file)
index 0000000..065ad9c
--- /dev/null
@@ -0,0 +1,75 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors assocs combinators kernel locals math
+math.ranges memoize sequences strings hashtables
+math.parser grouping ;
+IN: benchmark.hashtables
+
+MEMO: strings ( -- str )
+    1 100 [a,b] 1 [ + ] accumulate nip [ number>string ] map ;
+
+:: add-delete-mix ( hash keys -- )
+    keys [| k |
+        0 k hash set-at
+        k hash delete-at
+    ] each
+
+    keys [
+        0 swap hash set-at
+    ] each
+
+    keys [
+        hash delete-at
+    ] each ;
+
+:: store-lookup-mix ( hash keys -- )
+    keys [
+        0 swap hash set-at
+    ] each
+
+    keys [
+        hash at
+    ] map drop
+
+    keys [
+        hash [ 1 + ] change-at
+    ] each ;
+
+: string-mix ( hash -- )
+    strings
+    [ add-delete-mix ]
+    [ store-lookup-mix ]
+    2bi ;
+
+TUPLE: collision value ;
+
+M: collision hashcode* value>> hashcode* 15 bitand ;
+
+: collision-mix ( hash -- )
+    strings 30 head [ collision boa ] map
+    [ add-delete-mix ]
+    [ store-lookup-mix ]
+    2bi ;
+
+: small-mix ( hash -- )
+    strings 10 group [
+        [ add-delete-mix ]
+        [ store-lookup-mix ]
+        2bi
+    ] with each ;
+
+: hashtable-benchmark ( -- )
+    H{ } clone
+    10000 [
+        dup {
+            [ small-mix ]
+            [ clear-assoc ]
+            [ string-mix ]
+            [ clear-assoc ]
+            [ collision-mix ]
+            [ clear-assoc ]
+        } cleave
+    ] times
+    drop ;
+
+MAIN: hashtable-benchmark
\ No newline at end of file
index f20e67f9bcb9939f460e772dc8b3c0ad5ff87cbd..dcf5d69a748252cfe28f2540e8902f354d3b7c71 100644 (file)
@@ -6,7 +6,7 @@ help.markup help.topics io io.streams.string kernel make namespaces
 parser prettyprint sequences summary help.vocabs
 vocabs vocabs.loader vocabs.hierarchy vocabs.metadata words see
 listener ;
-
+FROM: vocabs.hierarchy => child-vocabs ;
 IN: fuel.help
 
 <PRIVATE
@@ -67,10 +67,10 @@ SYMBOL: describe-words
             [ fuel-vocab-help-table ] bi*
             [ 2array ] [ drop f ] if*
         ] if-empty
-    ] { } assoc>map [  ] filter ;
+    ] { } assoc>map sift ;
 
 : fuel-vocab-children-help ( name -- element )
-    all-child-vocabs fuel-vocab-list ; inline
+    child-vocabs fuel-vocab-list ; inline
 
 : fuel-vocab-describe-words ( name -- element )
     [ words. ] with-string-writer \ describe-words swap 2array ; inline
index 608667bae76eb407c290fafd991203cd7f7f39a7..86aa215e2104227803381e5cb2d54c3a8426bc0a 100644 (file)
@@ -64,7 +64,7 @@ PRIVATE>
 
 : article-location ( name -- loc ) article loc>> get-loc ;
 
-: get-vocabs ( -- seq ) all-vocabs-seq [ vocab-name ] map ;
+: get-vocabs ( -- seq ) all-vocab-names ;
 
 : get-vocabs/prefix ( prefix -- seq ) get-vocabs swap filter-prefix ;
 
index 001cc6200b57141968c5f702e9ad7f4a524b763c..3eff29635c99f8c7aadaa49b8b13d0bd27ed6b87 100644 (file)
@@ -25,6 +25,7 @@ IN: half-floats.tests
 [ -1.5  ] [ HEX: be00 bits>half ] unit-test
 [  1/0. ] [ HEX: 7c00 bits>half ] unit-test
 [ -1/0. ] [ HEX: fc00 bits>half ] unit-test
+[  3.0  ] [ HEX: 4200 bits>half ] unit-test
 [    t  ] [ HEX: 7e00 bits>half fp-nan? ] unit-test
 
 C-STRUCT: halves
index 26fc3e8a94a274fd2c6444d6810a560a49f4bfee..0f116f0d51fe6c52c9e411d38ff9923d7ee9aebf 100644 (file)
@@ -22,6 +22,6 @@ M: null-world pref-dim* drop { 512 512 } ;
     f swap open-window* ;
 
 : into-window ( world quot -- world )
-    [ dup handle>> ] dip with-gl-context ; inline
+    [ dup ] dip with-gl-context ; inline
 
 
index 8ba1623f2e796be5a9b1897f790f07599ea34b9e..f9b62e11f30c8f5a882b976e0a031f69aee6cd63 100644 (file)
@@ -13,7 +13,7 @@ VARIANT: class-name
     .
     .
     ; "> }
-{ $description "Defines " { $snippet "class-name" } " as a union of the following " { $link singleton-class } " and " { $link tuple-class } " definitions. Each " { $snippet "singleton" } " word is defined as a " { $snippet "singleton-class" } ", and each " { $snippet "tuple" } " word is defined aas a " { $snippet "tuple-class" } " with the given set of " { $snippet "slot" } "s, using the same syntax for slot specifiers as " { $link POSTPONE: TUPLE: } ". Typed tuple slots are able to recursively reference the variant " { $snippet "class-name" } " being defined. For " { $snippet "tuple" } " types, a " { $link boa } " constructor word " { $snippet "<tuple>" } " is defined as well." }
+{ $description "Defines " { $snippet "class-name" } " as a union of the following " { $link singleton-class } " and " { $link tuple-class } " definitions. Each " { $snippet "singleton" } " word is defined as a " { $snippet "singleton-class" } ", and each " { $snippet "tuple" } " word is defined aas a " { $snippet "tuple-class" } " with the given set of " { $snippet "slot" } "s, using the same syntax for slot specifiers as " { $link POSTPONE: TUPLE: } ". Typed tuple slots can recursively reference the variant " { $snippet "class-name" } " being defined. For " { $snippet "tuple" } " types, a " { $link boa } " constructor word " { $snippet "<tuple>" } " is defined as well." }
 { $examples { $code <"
 USING: kernel variants ;
 IN: scratchpad
@@ -26,7 +26,7 @@ VARIANT: list
 
 HELP: match
 { $values { "branches" array } }
-{ $description "Dispatches on the type of the value on the top of the stack. If the type is a " { $link singleton-class } ", the corresponding quotation is called with an empty stack. If the type is a " { $link tuple-class } ", the tuple slots are pushed onto the stack by order of arguments." }
+{ $description "Dispatches on the type of the value on the top of the stack. If the type is a " { $link singleton-class } ", the corresponding quotation is called with the underlying stack unchanged. If the type is a " { $link tuple-class } ", the tuple slots are pushed onto the stack by order of arguments." }
 { $examples { $example <"
 USING: kernel math prettyprint variants ;
 IN: scratchpad
index 728764226eb7954b30ee683416c1e378af67a10f..e6178a55c3604589045f2cc24a2415c2599b44ba 100644 (file)
@@ -1,12 +1,7 @@
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel
-cocoa
-cocoa.application
-cocoa.types
-cocoa.classes
-cocoa.windows
-core-graphics.types ;
+USING: cocoa cocoa.application cocoa.types cocoa.classes cocoa.windows
+core-graphics.types kernel math.bitwise ;
 IN: webkit-demo
 
 FRAMEWORK: /System/Library/Frameworks/WebKit.framework
@@ -18,8 +13,16 @@ IMPORT: WebView
     WebView -> alloc
     rect f f -> initWithFrame:frameName:groupName: ;
 
+: window-style ( -- n )
+    {
+        NSClosableWindowMask
+        NSMiniaturizableWindowMask
+        NSResizableWindowMask
+        NSTitledWindowMask
+    } flags ;
+
 : <WebWindow> ( -- id )
-    <WebView> rect <ViewWindow> ;
+    <WebView> rect window-style <ViewWindow> ;
 
 : load-url ( window url -- )
     [ -> contentView ] [ <NSString> ] bi* -> setMainFrameURL: ;
index af1e9e600ae9c243ca510a4ab04e81ab82788c4a..1659d1897ee9916c99ff2be209f340fece605de4 100644 (file)
@@ -41,12 +41,12 @@ syn match factorComment /\<! .*/ contains=factorTodo
 
 syn cluster factorDefnContents contains=@factorCluster,factorStackEffect,factorArray0,factorQuotation0
 
-syn region factorDefn matchgroup=factorDefnDelims start=/\<\(MACRO\|MEMO\|:\)\?:\s\+\S\+\>/ end=/\<;\>/ contains=@factorDefnContents
+syn region factorDefn matchgroup=factorDefnDelims start=/\<\(MACRO\|MACRO::\|MEMO:\|MEMO::\|:\|::\)\?:\s\+\S\+\>/ end=/\<;\>/ contains=@factorDefnContents
 syn region factorMethod matchgroup=factorMethodDelims start=/\<M:\s\+\S\+\s\+\S\+\>/ end=/\<;\>/ contains=@factorDefnContents
 syn region factorGeneric matchgroup=factorGenericDelims start=/\<GENERIC:\s\+\S\+\>/ end=/$/ contains=factorStackEffect
 syn region factorGenericN matchgroup=factorGenericNDelims start=/\<GENERIC#\s\+\S\+\s\+\d\+\>/ end=/$/ contains=factorStackEffect
 
-syn region factorPrivateDefn matchgroup=factorPrivateDefnDelims start=/\<\(MACRO\|MEMO\|:\)\?:\s\+\S\+\>/ end=/\<;\>/ contains=@factorDefnContents contained
+syn region factorPrivateDefn matchgroup=factorPrivateDefnDelims start=/\<\(MACRO\|MACRO::\|MEMO:\|MEMO::\|:\|::\)\?:\s\+\S\+\>/ end=/\<;\>/ contains=@factorDefnContents contained
 syn region factorPrivateMethod matchgroup=factorPrivateMethodDelims start=/\<M:\s\+\S\+\s\+\S\+\>/ end=/\<;\>/ contains=@factorDefnContents contained
 syn region factorPGeneric matchgroup=factorPGenericDelims start=/\<GENERIC:\s\+\S\+\>/ end=/$/ contains=factorStackEffect contained
 syn region factorPGenericN matchgroup=factorPGenericNDelims start=/\<GENERIC#\s\+\S\+\s\+\d\+\>/ end=/$/ contains=factorStackEffect