From 8d7ebc510603772433b865ae8aa99ec0413793da Mon Sep 17 00:00:00 2001 From: Slava Pestov <slava@slava-pestovs-macbook-pro.local> Date: Fri, 12 Sep 2008 18:08:19 -0500 Subject: [PATCH 01/16] Change stack effect of nths to match nth, rice bounds-check? --- .../strength-reduction-tests.factor | 119 ------------------ .../strength-reduction.factor | 5 - core/sequences/sequences.factor | 6 +- 3 files changed, 3 insertions(+), 127 deletions(-) delete mode 100644 basis/compiler/tree/strength-reduction/strength-reduction-tests.factor delete mode 100644 basis/compiler/tree/strength-reduction/strength-reduction.factor diff --git a/basis/compiler/tree/strength-reduction/strength-reduction-tests.factor b/basis/compiler/tree/strength-reduction/strength-reduction-tests.factor deleted file mode 100644 index 86fe74d939..0000000000 --- a/basis/compiler/tree/strength-reduction/strength-reduction-tests.factor +++ /dev/null @@ -1,119 +0,0 @@ -! TUPLE: declared-fixnum { x fixnum } ; -! -! [ t ] [ -! [ { declared-fixnum } declare [ 1 + ] change-x ] -! { + fixnum+ >fixnum } inlined? -! ] unit-test -! -! [ t ] [ -! [ { declared-fixnum } declare x>> drop ] -! { slot } inlined? -! ] unit-test -! -! [ t ] [ -! [ hashtable new ] \ new inlined? -! ] unit-test -! -! [ t ] [ -! [ dup hashtable eq? [ new ] when ] \ new inlined? -! ] unit-test -! -! [ f ] [ -! [ { integer } declare -63 shift 4095 bitand ] -! \ shift inlined? -! ] unit-test -! -! [ t ] [ -! [ { integer } declare 127 bitand 3 + ] -! { + +-integer-fixnum +-integer-fixnum-fast bitand } inlined? -! ] unit-test -! -! [ f ] [ -! [ { integer } declare 127 bitand 3 + ] -! { >fixnum } inlined? -! ] unit-test -! -! [ t ] [ -! [ -! { integer } declare -! dup 0 >= [ -! 615949 * 797807 + 20 2^ mod dup 19 2^ - -! ] [ dup ] if -! ] { * + shift mod fixnum-mod fixnum* fixnum+ fixnum- } inlined? -! ] unit-test -! -! [ t ] [ -! [ -! { fixnum } declare -! 615949 * 797807 + 20 2^ mod dup 19 2^ - -! ] { >fixnum } inlined? -! ] unit-test -! -! [ t ] [ -! [ -! { integer } declare 0 swap -! [ -! drop 615949 * 797807 + 20 2^ rem dup 19 2^ - -! ] map -! ] { * + shift rem mod fixnum-mod fixnum* fixnum+ fixnum- } inlined? -! ] unit-test -! -! [ t ] [ -! [ -! { fixnum } declare 0 swap -! [ -! drop 615949 * 797807 + 20 2^ rem dup 19 2^ - -! ] map -! ] { * + shift rem mod fixnum-mod fixnum* fixnum+ fixnum- >fixnum } inlined? -! ] unit-test -! -! [ t ] [ -! [ { string sbuf } declare ] \ push-all def>> append \ + inlined? -! ] unit-test -! -! [ t ] [ -! [ { string sbuf } declare ] \ push-all def>> append \ fixnum+ inlined? -! ] unit-test -! -! [ t ] [ -! [ { string sbuf } declare ] \ push-all def>> append \ >fixnum inlined? -! ] unit-test -! -! -! -! [ t ] [ -! [ -! { integer } declare [ 256 mod ] map -! ] { mod fixnum-mod } inlined? -! ] unit-test -! -! -! [ f ] [ -! [ -! 256 mod -! ] { mod fixnum-mod } inlined? -! ] unit-test -! -! [ f ] [ -! [ -! dup 0 >= [ 256 mod ] when -! ] { mod fixnum-mod } inlined? -! ] unit-test -! -! [ t ] [ -! [ -! { integer } declare dup 0 >= [ 256 mod ] when -! ] { mod fixnum-mod } inlined? -! ] unit-test -! -! [ t ] [ -! [ -! { integer } declare 256 rem -! ] { mod fixnum-mod } inlined? -! ] unit-test -! -! [ t ] [ -! [ -! { integer } declare [ 256 rem ] map -! ] { mod fixnum-mod rem } inlined? -! ] unit-test diff --git a/basis/compiler/tree/strength-reduction/strength-reduction.factor b/basis/compiler/tree/strength-reduction/strength-reduction.factor deleted file mode 100644 index c36395bbee..0000000000 --- a/basis/compiler/tree/strength-reduction/strength-reduction.factor +++ /dev/null @@ -1,5 +0,0 @@ -! Copyright (C) 2008 Slava Pestov. -! See http://factorcode.org/license.txt for BSD license. -IN: compiler.tree.strength-reduction - -: strength-reduce ( nodes -- nodes' ) ; diff --git a/core/sequences/sequences.factor b/core/sequences/sequences.factor index b08d6eb2c7..6cda7fc73f 100755 --- a/core/sequences/sequences.factor +++ b/core/sequences/sequences.factor @@ -51,7 +51,7 @@ M: sequence shorten 2dup length < [ set-length ] [ 2drop ] if ; : push ( elt seq -- ) [ length ] [ set-nth ] bi ; : bounds-check? ( n seq -- ? ) - length 1- 0 swap between? ; inline + dupd length < [ 0 >= ] [ drop f ] if ; inline ERROR: bounds-error index seq ; @@ -485,8 +485,8 @@ PRIVATE> [ rot = [ over push ] [ drop ] if ] curry each-index ; -: nths ( seq indices -- seq' ) - swap [ nth ] curry map ; +: nths ( indices seq -- seq' ) + [ nth ] curry map ; : contains? ( seq quot -- ? ) find drop >boolean ; inline From 10c68ebb21b4077210bddfc3a173908d66584e39 Mon Sep 17 00:00:00 2001 From: Slava Pestov <slava@slava-pestovs-macbook-pro.local> Date: Fri, 12 Sep 2008 18:08:38 -0500 Subject: [PATCH 02/16] New modular arithmetic optimization pass --- .../tree/cleanup/cleanup-tests.factor | 16 +-- basis/compiler/tree/cleanup/cleanup.factor | 8 -- .../tree/dead-code/branches/branches.factor | 2 +- basis/compiler/tree/debugger/debugger.factor | 45 +++++- .../simplified/simplified-tests.factor | 10 ++ .../tree/def-use/simplified/simplified.factor | 40 ++++++ .../tree/finalization/finalization.factor | 31 +---- .../late-optimizations.factor | 29 ++++ .../modular-arithmetic-tests.factor | 130 ++++++++++++++++++ .../modular-arithmetic.factor | 108 +++++++++++++++ .../compiler/tree/optimizer/optimizer.factor | 5 +- .../tree/propagation/inlining/inlining.factor | 13 +- .../known-words/known-words.factor | 26 ++++ .../tree/propagation/propagation-tests.factor | 27 ++-- .../partial-dispatch-tests.factor | 17 ++- .../partial-dispatch/partial-dispatch.factor | 54 ++++++-- 16 files changed, 482 insertions(+), 79 deletions(-) create mode 100644 basis/compiler/tree/def-use/simplified/simplified-tests.factor create mode 100644 basis/compiler/tree/def-use/simplified/simplified.factor create mode 100644 basis/compiler/tree/late-optimizations/late-optimizations.factor create mode 100644 basis/compiler/tree/modular-arithmetic/modular-arithmetic-tests.factor create mode 100644 basis/compiler/tree/modular-arithmetic/modular-arithmetic.factor diff --git a/basis/compiler/tree/cleanup/cleanup-tests.factor b/basis/compiler/tree/cleanup/cleanup-tests.factor index 2e8eb15959..b3ba62b73b 100644 --- a/basis/compiler/tree/cleanup/cleanup-tests.factor +++ b/basis/compiler/tree/cleanup/cleanup-tests.factor @@ -13,10 +13,8 @@ compiler.tree.builder compiler.tree.recursive compiler.tree.normalization compiler.tree.propagation -compiler.tree.checker ; - -: cleaned-up-tree ( quot -- nodes ) - build-tree analyze-recursive normalize propagate cleanup dup check-nodes ; +compiler.tree.checker +compiler.tree.debugger ; [ t ] [ [ [ 1 ] [ 2 ] if ] cleaned-up-tree [ #if? ] contains-node? ] unit-test @@ -34,12 +32,6 @@ compiler.tree.checker ; [ t ] [ [ t recursive-test ] cleaned-up-tree [ #recursive? ] contains-node? ] unit-test -: inlined? ( quot seq/word -- ? ) - [ cleaned-up-tree ] dip - dup word? [ 1array ] when - '[ dup #call? [ word>> _ member? ] [ drop f ] if ] - contains-node? not ; - [ f ] [ [ { integer } declare >fixnum ] \ >fixnum inlined? @@ -498,3 +490,7 @@ cell-bits 32 = [ [ 2 swap >fixnum ribs ] { <-integer-fixnum +-integer-fixnum } inlined? ] unit-test + +[ t ] [ + [ hashtable new ] \ new inlined? +] unit-test diff --git a/basis/compiler/tree/cleanup/cleanup.factor b/basis/compiler/tree/cleanup/cleanup.factor index 58dc07d868..563926f233 100644 --- a/basis/compiler/tree/cleanup/cleanup.factor +++ b/basis/compiler/tree/cleanup/cleanup.factor @@ -64,14 +64,6 @@ GENERIC: cleanup* ( node -- node/nodes ) ] [ body>> cleanup ] bi ; ! Removing overflow checks -: no-overflow-variant ( op -- fast-op ) - H{ - { fixnum+ fixnum+fast } - { fixnum- fixnum-fast } - { fixnum* fixnum*fast } - { fixnum-shift fixnum-shift-fast } - } at ; - : (remove-overflow-check?) ( #call -- ? ) node-output-infos first class>> fixnum class<= ; diff --git a/basis/compiler/tree/dead-code/branches/branches.factor b/basis/compiler/tree/dead-code/branches/branches.factor index a19e49494e..719c80f911 100644 --- a/basis/compiler/tree/dead-code/branches/branches.factor +++ b/basis/compiler/tree/dead-code/branches/branches.factor @@ -36,7 +36,7 @@ M: #branch remove-dead-code* '[ _ nth _ key? ] filter ; inline : drop-indexed-values ( values indices -- node ) - [ drop filter-live ] [ nths ] 2bi + [ drop filter-live ] [ swap nths ] 2bi [ make-values ] keep [ drop ] [ zip ] 2bi #shuffle ; diff --git a/basis/compiler/tree/debugger/debugger.factor b/basis/compiler/tree/debugger/debugger.factor index 691c564661..4d2881af5a 100644 --- a/basis/compiler/tree/debugger/debugger.factor +++ b/basis/compiler/tree/debugger/debugger.factor @@ -1,13 +1,21 @@ ! Copyright (C) 2006, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: kernel assocs fry match accessors namespaces make effects +USING: kernel assocs match fry accessors namespaces make effects sequences sequences.private quotations generic macros arrays prettyprint prettyprint.backend prettyprint.sections math words -combinators io sorting hints +combinators io sorting hints qualified compiler.tree +compiler.tree.recursive +compiler.tree.normalization +compiler.tree.cleanup +compiler.tree.propagation +compiler.tree.propagation.info +compiler.tree.def-use compiler.tree.builder compiler.tree.optimizer -compiler.tree.combinators ; +compiler.tree.combinators +compiler.tree.checker ; +RENAME: _ match => __ IN: compiler.tree.debugger ! A simple tool for turning tree IR into quotations and @@ -42,7 +50,7 @@ MATCH-VARS: ?a ?b ?c ; { { { ?a ?b ?c } { ?b ?c ?a } } [ rot ] } { { { ?a ?b } { ?b } } [ nip ] } { { { ?a ?b ?c } { ?c } } [ 2nip ] } - { _ f } + { __ f } } match-choose ; TUPLE: shuffle-node { effect effect } ; @@ -146,3 +154,32 @@ SYMBOL: node-count : optimizer-report. ( word -- ) make-report report. ; + +! More utilities + +: final-info ( quot -- seq ) + build-tree + analyze-recursive + normalize + propagate + compute-def-use + dup check-nodes + peek node-input-infos ; + +: final-classes ( quot -- seq ) + final-info [ class>> ] map ; + +: final-literals ( quot -- seq ) + final-info [ literal>> ] map ; + +: cleaned-up-tree ( quot -- nodes ) + [ + check-optimizer? on + build-tree optimize-tree + ] with-scope ; + +: inlined? ( quot seq/word -- ? ) + [ cleaned-up-tree ] dip + dup word? [ 1array ] when + '[ dup #call? [ word>> _ member? ] [ drop f ] if ] + contains-node? not ; diff --git a/basis/compiler/tree/def-use/simplified/simplified-tests.factor b/basis/compiler/tree/def-use/simplified/simplified-tests.factor new file mode 100644 index 0000000000..a1a768d429 --- /dev/null +++ b/basis/compiler/tree/def-use/simplified/simplified-tests.factor @@ -0,0 +1,10 @@ +USING: kernel tools.test compiler.tree compiler.tree.builder +compiler.tree.def-use compiler.tree.def-use.simplified accessors +sequences sorting classes ; +IN: compiler.tree.def-use.simplified + +[ { #call #return } ] [ + [ 1 dup reverse ] build-tree compute-def-use + first out-d>> first actually-used-by + [ node>> class ] map natural-sort +] unit-test diff --git a/basis/compiler/tree/def-use/simplified/simplified.factor b/basis/compiler/tree/def-use/simplified/simplified.factor new file mode 100644 index 0000000000..edfe633057 --- /dev/null +++ b/basis/compiler/tree/def-use/simplified/simplified.factor @@ -0,0 +1,40 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: sequences sequences.deep kernel +compiler.tree compiler.tree.def-use ; +IN: compiler.tree.def-use.simplified + +! Simplified def-use follows chains of copies. + +! A 'real' usage is a usage of a value that is not a #renaming. +TUPLE: real-usage value node ; + +GENERIC: actually-used-by* ( value node -- real-usages ) + +! Def +GENERIC: actually-defined-by* ( value node -- real-usage ) + +: actually-defined-by ( value -- real-usage ) + dup defined-by actually-defined-by* ; + +M: #renaming actually-defined-by* + inputs/outputs swap [ index ] dip nth actually-defined-by ; + +M: #return-recursive actually-defined-by* real-usage boa ; + +M: node actually-defined-by* real-usage boa ; + +! Use +: (actually-used-by) ( value -- real-usages ) + dup used-by [ actually-used-by* ] with map ; + +M: #renaming actually-used-by* + inputs/outputs [ indices ] dip nths + [ (actually-used-by) ] map ; + +M: #return-recursive actually-used-by* real-usage boa ; + +M: node actually-used-by* real-usage boa ; + +: actually-used-by ( value -- real-usages ) + (actually-used-by) flatten ; diff --git a/basis/compiler/tree/finalization/finalization.factor b/basis/compiler/tree/finalization/finalization.factor index ba7e4ff652..c312cb68dc 100644 --- a/basis/compiler/tree/finalization/finalization.factor +++ b/basis/compiler/tree/finalization/finalization.factor @@ -6,27 +6,20 @@ classes.tuple.private slots.private combinators layouts byte-arrays alien.accessors compiler.intrinsics compiler.tree -compiler.tree.builder -compiler.tree.recursive -compiler.tree.normalization -compiler.tree.propagation +compiler.tree.combinators compiler.tree.propagation.info -compiler.tree.cleanup -compiler.tree.def-use -compiler.tree.dead-code -compiler.tree.combinators ; +compiler.tree.late-optimizations ; IN: compiler.tree.finalization +! This is a late-stage optimization. +! See the comment in compiler.tree.late-optimizations. + ! This pass runs after propagation, so that it can expand ! built-in type predicates and memory allocation; these cannot ! be expanded before propagation since we need to see 'fixnum?' ! instead of 'tag 0 eq?' and so on, for semantic reasoning. ! We also delete empty stack shuffles and copies to facilitate -! tail call optimization in the code generator. After this pass -! runs, stack flow information is no longer accurate, since we -! punt in 'splice-quot' and don't update everything that we -! should; this simplifies the code, improves performance, and we -! don't need the stack flow information after this pass anyway. +! tail call optimization in the code generator. GENERIC: finalize* ( node -- nodes ) @@ -37,18 +30,6 @@ M: #shuffle finalize* [ in>> ] [ out>> ] bi sequence= [ drop f ] when ; -: splice-quot ( quot -- nodes ) - [ - build-tree - analyze-recursive - normalize - propagate - cleanup - compute-def-use - remove-dead-code - but-last - ] with-scope ; - : builtin-predicate? ( #call -- ? ) word>> "predicating" word-prop builtin-class? ; diff --git a/basis/compiler/tree/late-optimizations/late-optimizations.factor b/basis/compiler/tree/late-optimizations/late-optimizations.factor new file mode 100644 index 0000000000..e2641416b2 --- /dev/null +++ b/basis/compiler/tree/late-optimizations/late-optimizations.factor @@ -0,0 +1,29 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: sequences namespaces compiler.tree.builder +compiler.tree.recursive +compiler.tree.normalization +compiler.tree.propagation +compiler.tree.propagation.info +compiler.tree.cleanup +compiler.tree.def-use +compiler.tree.dead-code ; +IN: compiler.tree.late-optimizations + +! Late optimizations modify the tree such that stack flow +! information is no longer accurate, since we punt in +! 'splice-quot' and don't update everything that we should; +! this simplifies the code, improves performance, and we +! don't need the stack flow information after this pass anyway. + +: splice-quot ( quot -- nodes ) + [ + build-tree + analyze-recursive + normalize + propagate + cleanup + compute-def-use + remove-dead-code + but-last + ] with-scope ; diff --git a/basis/compiler/tree/modular-arithmetic/modular-arithmetic-tests.factor b/basis/compiler/tree/modular-arithmetic/modular-arithmetic-tests.factor new file mode 100644 index 0000000000..b535dfe39c --- /dev/null +++ b/basis/compiler/tree/modular-arithmetic/modular-arithmetic-tests.factor @@ -0,0 +1,130 @@ +IN: compiler.tree.modular-arithmetic.tests +USING: kernel kernel.private tools.test math math.partial-dispatch +math.private accessors slots.private sequences strings sbufs +compiler.tree.builder +compiler.tree.optimizer +compiler.tree.debugger ; + +: test-modular-arithmetic ( quot -- quot' ) + build-tree optimize-tree nodes>quot ; + +[ [ >r >fixnum r> >fixnum fixnum+fast ] ] +[ [ { integer integer } declare + >fixnum ] test-modular-arithmetic ] unit-test + +[ [ +-integer-integer dup >fixnum ] ] +[ [ { integer integer } declare + dup >fixnum ] test-modular-arithmetic ] unit-test + +[ [ >r >fixnum r> >fixnum fixnum+fast 4 fixnum*fast ] ] +[ [ { integer integer } declare + 4 * >fixnum ] test-modular-arithmetic ] unit-test + +TUPLE: declared-fixnum { x fixnum } ; + +[ t ] [ + [ { declared-fixnum } declare [ 1 + ] change-x ] + { + fixnum+ >fixnum } inlined? +] unit-test + +[ t ] [ + [ { declared-fixnum } declare x>> drop ] + { slot } inlined? +] unit-test + +[ f ] [ + [ { integer } declare -63 shift 4095 bitand ] + \ shift inlined? +] unit-test + +[ t ] [ + [ { integer } declare 127 bitand 3 + ] + { + +-integer-fixnum bitand } inlined? +] unit-test + +[ f ] [ + [ { integer } declare 127 bitand 3 + ] + { >fixnum } inlined? +] unit-test + +[ t ] [ + [ + { integer } declare + dup 0 >= [ + 615949 * 797807 + 20 2^ mod dup 19 2^ - + ] [ dup ] if + ] { * + shift mod fixnum-mod fixnum* fixnum+ fixnum- } inlined? +] unit-test + +[ t ] [ + [ + { fixnum } declare + 615949 * 797807 + 20 2^ mod dup 19 2^ - + ] { >fixnum } inlined? +] unit-test + +[ t ] [ + [ + { integer } declare 0 swap + [ + drop 615949 * 797807 + 20 2^ rem dup 19 2^ - + ] map + ] { * + shift rem mod fixnum-mod fixnum* fixnum+ fixnum- } inlined? +] unit-test + +[ t ] [ + [ + { fixnum } declare 0 swap + [ + drop 615949 * 797807 + 20 2^ rem dup 19 2^ - + ] map + ] { * + shift rem mod fixnum-mod fixnum* fixnum+ fixnum- >fixnum } inlined? +] unit-test + +[ t ] [ + [ { string sbuf } declare ] \ push-all def>> append \ + inlined? +] unit-test + +[ t ] [ + [ { string sbuf } declare ] \ push-all def>> append \ fixnum+ inlined? +] unit-test + +[ t ] [ + [ { string sbuf } declare ] \ push-all def>> append \ >fixnum inlined? +] unit-test + + + +[ t ] [ + [ + { integer } declare [ 256 mod ] map + ] { mod fixnum-mod } inlined? +] unit-test + + +[ f ] [ + [ + 256 mod + ] { mod fixnum-mod } inlined? +] unit-test + +[ f ] [ + [ + dup 0 >= [ 256 mod ] when + ] { mod fixnum-mod } inlined? +] unit-test + +[ t ] [ + [ + { integer } declare dup 0 >= [ 256 mod ] when + ] { mod fixnum-mod } inlined? +] unit-test + +[ t ] [ + [ + { integer } declare 256 rem + ] { mod fixnum-mod } inlined? +] unit-test + +[ t ] [ + [ + { integer } declare [ 256 rem ] map + ] { mod fixnum-mod rem } inlined? +] unit-test diff --git a/basis/compiler/tree/modular-arithmetic/modular-arithmetic.factor b/basis/compiler/tree/modular-arithmetic/modular-arithmetic.factor new file mode 100644 index 0000000000..d65b1def16 --- /dev/null +++ b/basis/compiler/tree/modular-arithmetic/modular-arithmetic.factor @@ -0,0 +1,108 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: math math.partial-dispatch namespaces sequences sets +accessors assocs words kernel memoize fry combinators +compiler.tree +compiler.tree.combinators +compiler.tree.def-use +compiler.tree.def-use.simplified +compiler.tree.late-optimizations ; +IN: compiler.tree.modular-arithmetic + +! This is a late-stage optimization. +! See the comment in compiler.tree.late-optimizations. + +! Modular arithmetic optimization pass. +! +! { integer integer } declare + >fixnum +! ==> +! [ >fixnum ] bi@ fixnum+fast + +{ + - * bitand bitor bitxor } [ + [ + t "modular-arithmetic" set-word-prop + ] each-integer-derived-op +] each + +{ bitand bitor bitxor bitnot } +[ t "modular-arithmetic" set-word-prop ] each + +SYMBOL: modularize-values + +: modular-value? ( value -- ? ) + modularize-values get key? ; + +: modularize-value ( value -- ) modularize-values get conjoin ; + +GENERIC: maybe-modularize* ( value node -- ) + +: maybe-modularize ( value -- ) + actually-defined-by [ value>> ] [ node>> ] bi + over actually-used-by length 1 = [ + maybe-modularize* + ] [ 2drop ] if ; + +M: #call maybe-modularize* + dup word>> "modular-arithmetic" word-prop [ + [ modularize-value ] + [ in-d>> [ maybe-modularize ] each ] bi* + ] [ 2drop ] if ; + +M: node maybe-modularize* 2drop ; + +GENERIC: compute-modularized-values* ( node -- ) + +M: #call compute-modularized-values* + dup word>> { + { [ \ >fixnum eq? ] [ in-d>> first maybe-modularize ] } + ! { [ + ! { + ! mod-integer-fixnum + ! mod-integer-integer + ! mod-fixnum-integer + ! } memq? + ! ] [ ] } + [ drop ] + } cond ; + +M: node compute-modularized-values* drop ; + +: compute-modularized-values ( nodes -- ) + [ compute-modularized-values* ] each-node ; + +GENERIC: optimize-modular-arithmetic* ( node -- nodes ) + +: redundant->fixnum? ( #call -- ? ) + in-d>> first actually-defined-by value>> modular-value? ; + +: optimize->fixnum ( #call -- nodes ) + dup redundant->fixnum? [ drop f ] when ; + +MEMO: fixnum-coercion ( flags -- nodes ) + [ [ ] [ >fixnum ] ? ] map '[ _ spread ] splice-quot ; + +: optimize-modular-op ( #call -- nodes ) + dup out-d>> first modular-value? [ + [ in-d>> ] [ word>> integer-op-input-classes ] [ ] tri + [ + [ + [ actually-defined-by value>> modular-value? ] + [ fixnum eq? ] + bi* or + ] 2map fixnum-coercion + ] [ [ modular-variant ] change-word ] bi* suffix + ] when ; + +M: #call optimize-modular-arithmetic* + dup word>> { + { [ dup \ >fixnum eq? ] [ drop optimize->fixnum ] } + { [ dup "modular-arithmetic" word-prop ] [ drop optimize-modular-op ] } + [ drop ] + } cond ; + +M: node optimize-modular-arithmetic* ; + +: optimize-modular-arithmetic ( nodes -- nodes' ) + H{ } clone modularize-values set + dup compute-modularized-values + [ optimize-modular-arithmetic* ] map-nodes ; diff --git a/basis/compiler/tree/optimizer/optimizer.factor b/basis/compiler/tree/optimizer/optimizer.factor index 3196253d45..e37323a2ec 100644 --- a/basis/compiler/tree/optimizer/optimizer.factor +++ b/basis/compiler/tree/optimizer/optimizer.factor @@ -10,7 +10,7 @@ compiler.tree.tuple-unboxing compiler.tree.identities compiler.tree.def-use compiler.tree.dead-code -compiler.tree.strength-reduction +compiler.tree.modular-arithmetic compiler.tree.finalization compiler.tree.checker ; IN: compiler.tree.optimizer @@ -27,9 +27,10 @@ SYMBOL: check-optimizer? apply-identities compute-def-use remove-dead-code - ! strength-reduce check-optimizer? get [ compute-def-use dup check-nodes ] when + compute-def-use + optimize-modular-arithmetic finalize ; diff --git a/basis/compiler/tree/propagation/inlining/inlining.factor b/basis/compiler/tree/propagation/inlining/inlining.factor index 48864d8782..197d1820bf 100644 --- a/basis/compiler/tree/propagation/inlining/inlining.factor +++ b/basis/compiler/tree/propagation/inlining/inlining.factor @@ -3,7 +3,7 @@ USING: accessors kernel arrays sequences math math.order math.partial-dispatch generic generic.standard generic.math classes.algebra classes.union sets quotations assocs combinators -words namespaces +words namespaces continuations compiler.tree compiler.tree.builder compiler.tree.recursive @@ -33,7 +33,7 @@ M: quotation splicing-nodes body>> (propagate) ; ! Dispatch elimination -: eliminate-dispatch ( #call class/f word/f -- ? ) +: eliminate-dispatch ( #call class/f word/quot/f -- ? ) dup [ [ >>class ] dip over method>> over = [ drop ] [ @@ -156,12 +156,19 @@ SYMBOL: history : always-inline-word? ( word -- ? ) { curry compose } memq? ; +: custom-inlining? ( word -- ? ) + "custom-inlining" word-prop ; + +: inline-custom ( #call word -- ? ) + [ dup 1array ] [ "custom-inlining" word-prop ] bi* with-datastack + first object swap eliminate-dispatch ; + : do-inlining ( #call word -- ? ) { + { [ dup custom-inlining? ] [ inline-custom ] } { [ dup always-inline-word? ] [ inline-word ] } { [ dup standard-generic? ] [ inline-standard-method ] } { [ dup math-generic? ] [ inline-math-method ] } - { [ dup math-partial? ] [ inline-math-partial ] } { [ dup method-body? ] [ inline-method-body ] } [ 2drop f ] } cond ; diff --git a/basis/compiler/tree/propagation/known-words/known-words.factor b/basis/compiler/tree/propagation/known-words/known-words.factor index d208d31389..9f208bdc12 100644 --- a/basis/compiler/tree/propagation/known-words/known-words.factor +++ b/basis/compiler/tree/propagation/known-words/known-words.factor @@ -230,6 +230,32 @@ generic-comparison-ops [ ] "outputs" set-word-prop ] assoc-each +{ + mod-integer-integer + mod-integer-fixnum + mod-fixnum-integer + fixnum-mod + rem +} [ + [ + in-d>> second value-info >literal< + [ power-of-2? [ 1- bitand ] f ? ] when + ] "custom-inlining" set-word-prop +] each + +{ + bitand-integer-integer + bitand-integer-fixnum + bitand-fixnum-integer +} [ + [ + in-d>> second value-info >literal< [ + 0 most-positive-fixnum between? + [ [ >fixnum ] bi@ fixnum-bitand ] f ? + ] when + ] "custom-inlining" set-word-prop +] each + { alien-signed-1 alien-unsigned-1 diff --git a/basis/compiler/tree/propagation/propagation-tests.factor b/basis/compiler/tree/propagation/propagation-tests.factor index a115ee53c2..6638951723 100644 --- a/basis/compiler/tree/propagation/propagation-tests.factor +++ b/basis/compiler/tree/propagation/propagation-tests.factor @@ -6,27 +6,12 @@ alien.accessors alien.c-types sequences.private byte-arrays classes.algebra classes.tuple.private math.functions math.private strings layouts compiler.tree.propagation.info compiler.tree.def-use -compiler.tree.checker slots.private words hashtables -classes assocs ; +compiler.tree.debugger compiler.tree.checker +slots.private words hashtables classes assocs ; IN: compiler.tree.propagation.tests \ propagate must-infer -: final-info ( quot -- seq ) - build-tree - analyze-recursive - normalize - propagate - compute-def-use - dup check-nodes - peek node-input-infos ; - -: final-classes ( quot -- seq ) - final-info [ class>> ] map ; - -: final-literals ( quot -- seq ) - final-info [ literal>> ] map ; - [ V{ } ] [ [ ] final-classes ] unit-test [ V{ fixnum } ] [ [ 1 ] final-classes ] unit-test @@ -594,6 +579,14 @@ MIXIN: empty-mixin [ { float } declare 0 eq? ] final-classes ] unit-test +[ V{ integer } ] [ + [ { integer fixnum } declare mod ] final-classes +] unit-test + +[ V{ integer } ] [ + [ { fixnum integer } declare bitand ] final-classes +] unit-test + ! [ V{ string } ] [ ! [ dup string? t xor [ "A" throw ] [ ] if ] final-classes ! ] unit-test diff --git a/basis/math/partial-dispatch/partial-dispatch-tests.factor b/basis/math/partial-dispatch/partial-dispatch-tests.factor index 64605b1818..388b4127cd 100644 --- a/basis/math/partial-dispatch/partial-dispatch-tests.factor +++ b/basis/math/partial-dispatch/partial-dispatch-tests.factor @@ -1,5 +1,6 @@ IN: math.partial-dispatch.tests -USING: math.partial-dispatch tools.test math kernel sequences ; +USING: math.partial-dispatch math.private +tools.test math kernel sequences ; [ t ] [ \ + integer fixnum math-both-known? ] unit-test [ t ] [ \ + bignum fixnum math-both-known? ] unit-test @@ -10,3 +11,17 @@ USING: math.partial-dispatch tools.test math kernel sequences ; [ f ] [ \ number= fixnum object math-both-known? ] unit-test [ t ] [ \ number= integer fixnum math-both-known? ] unit-test [ f ] [ \ >fixnum \ shift derived-ops memq? ] unit-test + +[ { integer fixnum } ] [ \ +-integer-fixnum integer-op-input-classes ] unit-test +[ { fixnum fixnum } ] [ \ fixnum+ integer-op-input-classes ] unit-test +[ { fixnum fixnum } ] [ \ fixnum+fast integer-op-input-classes ] unit-test +[ { integer } ] [ \ bitnot integer-op-input-classes ] unit-test + +[ shift ] [ \ fixnum-shift generic-variant ] unit-test +[ fixnum-shift-fast ] [ \ fixnum-shift no-overflow-variant ] unit-test + +[ fixnum-shift-fast ] [ \ shift modular-variant ] unit-test +[ fixnum-bitnot ] [ \ bitnot modular-variant ] unit-test +[ fixnum+fast ] [ \ fixnum+ modular-variant ] unit-test +[ fixnum+fast ] [ \ fixnum+fast modular-variant ] unit-test + diff --git a/basis/math/partial-dispatch/partial-dispatch.factor b/basis/math/partial-dispatch/partial-dispatch.factor index b162406e5a..61678eb088 100644 --- a/basis/math/partial-dispatch/partial-dispatch.factor +++ b/basis/math/partial-dispatch/partial-dispatch.factor @@ -6,13 +6,41 @@ generic generic.math hashtables effects compiler.units classes.algebra ; IN: math.partial-dispatch -! Partial dispatch. - -! This code will be overhauled and generalized when -! multi-methods go into the core. PREDICATE: math-partial < word "derived-from" word-prop >boolean ; +GENERIC: integer-op-input-classes ( word -- classes ) + +M: math-partial integer-op-input-classes + "derived-from" word-prop rest ; + +M: word integer-op-input-classes + "input-classes" word-prop + [ "Bug: integer-op-input-classes" throw ] unless* ; + +: generic-variant ( op -- generic-op/f ) + dup "derived-from" word-prop [ first ] [ ] ?if ; + +: no-overflow-variant ( op -- fast-op ) + H{ + { fixnum+ fixnum+fast } + { fixnum- fixnum-fast } + { fixnum* fixnum*fast } + { fixnum-shift fixnum-shift-fast } + } at ; + +: modular-variant ( op -- fast-op ) + generic-variant dup H{ + { + fixnum+fast } + { - fixnum-fast } + { * fixnum*fast } + { shift fixnum-shift-fast } + { bitand fixnum-bitand } + { bitor fixnum-bitor } + { bitxor fixnum-bitxor } + { bitnot fixnum-bitnot } + } at swap or ; + :: fixnum-integer-op ( a b fix-word big-word -- c ) b tag 0 eq? [ a b fix-word execute @@ -69,10 +97,17 @@ PREDICATE: math-partial < word } swap [ prefix ] curry map ; : define-integer-ops ( word fix-word big-word -- ) - >r >r integer-op-triples r> r> - [ define-integer-op-words ] - [ 2drop [ dup integer-op-word ] { } map>assoc % ] - 3bi ; + [ + rot tuck + [ fixnum fixnum 3array "derived-from" set-word-prop ] + [ bignum bignum 3array "derived-from" set-word-prop ] + 2bi* + ] [ + [ integer-op-triples ] 2dip + [ define-integer-op-words ] + [ 2drop [ dup integer-op-word ] { } map>assoc % ] + 3bi + ] 3bi ; : define-math-ops ( op -- ) { fixnum bignum float } @@ -125,6 +160,9 @@ SYMBOL: fast-math-ops : each-fast-derived-op ( word quot -- ) >r fast-derived-ops r> each ; inline +: each-integer-derived-op ( word quot -- ) + >r integer-derived-ops r> each ; inline + [ [ \ + define-math-ops From 379566374cd568810d33a39dc947dad5a80ae478 Mon Sep 17 00:00:00 2001 From: Slava Pestov <slava@slava-pestovs-macbook-pro.local> Date: Fri, 12 Sep 2008 18:15:22 -0500 Subject: [PATCH 03/16] Fix usages of nths --- extra/math/combinatorics/combinatorics.factor | 2 +- extra/project-euler/186/186.factor | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extra/math/combinatorics/combinatorics.factor b/extra/math/combinatorics/combinatorics.factor index 7c5d5ba4c0..a0c6df083b 100644 --- a/extra/math/combinatorics/combinatorics.factor +++ b/extra/math/combinatorics/combinatorics.factor @@ -39,7 +39,7 @@ PRIVATE> twiddle [ nPk ] keep factorial / ; : permutation ( n seq -- seq ) - tuck permutation-indices nths ; + tuck permutation-indices swap nths ; : all-permutations ( seq -- seq ) [ diff --git a/extra/project-euler/186/186.factor b/extra/project-euler/186/186.factor index ac846f6064..5308662daf 100644 --- a/extra/project-euler/186/186.factor +++ b/extra/project-euler/186/186.factor @@ -9,7 +9,7 @@ IN: project-euler.186 55 [1,b] [ (generator) ] map <circular> ; : advance ( lag -- ) - [ { 0 31 } nths sum 1000000 rem ] keep push-circular ; + [ { 0 31 } swap nths sum 1000000 rem ] keep push-circular ; : next ( lag -- n ) [ first ] [ advance ] bi ; From f2eeeb4ae80e5686a80f0ce260a2d61059c53b55 Mon Sep 17 00:00:00 2001 From: Slava Pestov <slava@slava-pestovs-macbook-pro.local> Date: Fri, 12 Sep 2008 18:15:26 -0500 Subject: [PATCH 04/16] Cleanup --- extra/benchmark/spectral-norm/spectral-norm.factor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/benchmark/spectral-norm/spectral-norm.factor b/extra/benchmark/spectral-norm/spectral-norm.factor index 6d4d42116c..3c20a1ceff 100644 --- a/extra/benchmark/spectral-norm/spectral-norm.factor +++ b/extra/benchmark/spectral-norm/spectral-norm.factor @@ -41,7 +41,7 @@ IN: benchmark.spectral-norm ] times ; inline : spectral-norm ( n -- norm ) - u/v [ v. ] keep norm-sq /f sqrt ; + u/v [ v. ] [ norm-sq ] bi /f sqrt ; HINTS: spectral-norm fixnum ; From 20cc730501312cdc9da64cfd61066edc26d39943 Mon Sep 17 00:00:00 2001 From: Slava Pestov <slava@slava-pestovs-macbook-pro.local> Date: Fri, 12 Sep 2008 18:57:34 -0500 Subject: [PATCH 05/16] Fix sequences tests --- core/sequences/sequences-tests.factor | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/sequences/sequences-tests.factor b/core/sequences/sequences-tests.factor index f8765bc946..e27f2410b3 100755 --- a/core/sequences/sequences-tests.factor +++ b/core/sequences/sequences-tests.factor @@ -250,11 +250,11 @@ unit-test [ 50 ] [ 100 [ even? ] count ] unit-test [ 50 ] [ 100 [ odd? ] count ] unit-test -[ { "b" "d" } ] [ { "a" "b" "c" "d" } { 1 3 } nths ] unit-test -[ { "a" "b" "c" "d" } ] [ { "a" "b" "c" "d" } { 0 1 2 3 } nths ] unit-test -[ { "d" "c" "b" "a" } ] [ { "a" "b" "c" "d" } { 3 2 1 0 } nths ] unit-test -[ { "d" "a" "b" "c" } ] [ { "a" "b" "c" "d" } { 3 0 1 2 } nths ] unit-test - +[ { "b" "d" } ] [ { 1 3 } { "a" "b" "c" "d" } nths ] unit-test +[ { "a" "b" "c" "d" } ] [ { 0 1 2 3 } { "a" "b" "c" "d" } nths ] unit-test +[ { "d" "c" "b" "a" } ] [ { 3 2 1 0 } { "a" "b" "c" "d" } nths ] unit-test +[ { "d" "a" "b" "c" } ] [ { 3 0 1 2 } { "a" "b" "c" "d" } nths ] unit-test + TUPLE: bogus-hashcode ; M: bogus-hashcode hashcode* 2drop 0 >bignum ; @@ -265,6 +265,6 @@ M: bogus-hashcode hashcode* 2drop 0 >bignum ; [ { 1 3 7 } ] [ 2 { 1 3 5 7 } remove-nth ] unit-test -[ { 1 3 "X" 5 7 } ] [ "X" 2 { 1 3 5 7 } insert-nth ] +[ { 1 3 "X" 5 7 } ] [ "X" 2 { 1 3 5 7 } insert-nth ] unit-test [ V{ 0 2 } ] [ "a" { "a" "b" "a" } indices ] unit-test From dab32f7abe9342a3cb4d435fb187da33ef8b9542 Mon Sep 17 00:00:00 2001 From: Doug Coleman <doug.coleman@gmail.com> Date: Fri, 12 Sep 2008 21:56:25 -0500 Subject: [PATCH 06/16] unbreak regexp2 for fry change, use dip some, pprint*, make \^ and \$ parse --- unfinished/regexp2/backend/backend.factor | 1 - unfinished/regexp2/dfa/dfa.factor | 2 +- unfinished/regexp2/parser/parser.factor | 2 ++ unfinished/regexp2/regexp2-tests.factor | 2 ++ unfinished/regexp2/regexp2.factor | 31 ++++++++++++++++++- unfinished/regexp2/traversal/traversal.factor | 4 ++- unfinished/regexp2/utils/utils.factor | 2 +- 7 files changed, 39 insertions(+), 5 deletions(-) diff --git a/unfinished/regexp2/backend/backend.factor b/unfinished/regexp2/backend/backend.factor index 81ffb334bd..fa5c1f7f97 100644 --- a/unfinished/regexp2/backend/backend.factor +++ b/unfinished/regexp2/backend/backend.factor @@ -21,7 +21,6 @@ TUPLE: regexp 0 >>state V{ } clone >>stack V{ } clone >>new-states - H{ } clone >>options H{ } clone >>visited-states ; SYMBOL: current-regexp diff --git a/unfinished/regexp2/dfa/dfa.factor b/unfinished/regexp2/dfa/dfa.factor index 468ffa73e5..cd2f4186f4 100644 --- a/unfinished/regexp2/dfa/dfa.factor +++ b/unfinished/regexp2/dfa/dfa.factor @@ -15,7 +15,7 @@ IN: regexp2.dfa eps swap find-delta ; : find-epsilon-closure ( states regexp -- new-states ) - '[ dup , (find-epsilon-closure) union ] [ length ] while-changes + '[ dup _ (find-epsilon-closure) union ] [ length ] while-changes natural-sort ; : find-closure ( states transition regexp -- new-states ) diff --git a/unfinished/regexp2/parser/parser.factor b/unfinished/regexp2/parser/parser.factor index 206db3883d..a970f82aab 100644 --- a/unfinished/regexp2/parser/parser.factor +++ b/unfinished/regexp2/parser/parser.factor @@ -291,6 +291,8 @@ ERROR: bad-escaped-literals seq ; { CHAR: f [ HEX: c <constant> ] } { CHAR: a [ HEX: 7 <constant> ] } { CHAR: e [ HEX: 1b <constant> ] } + { CHAR: $ [ CHAR: $ <constant> ] } + { CHAR: ^ [ CHAR: ^ <constant> ] } { CHAR: d [ digit-class ] } { CHAR: D [ digit-class <negation> ] } diff --git a/unfinished/regexp2/regexp2-tests.factor b/unfinished/regexp2/regexp2-tests.factor index 88bbc5f56c..f691c2becf 100644 --- a/unfinished/regexp2/regexp2-tests.factor +++ b/unfinished/regexp2/regexp2-tests.factor @@ -222,6 +222,8 @@ IN: regexp2-tests <regexp> drop ] unit-test +[ ] [ "(\\$[\\p{XDigit}]|[\\p{Digit}])" <regexp> drop ] unit-test + ! Comment [ t ] [ "ac" "a(?#boo)c" <regexp> matches? ] unit-test diff --git a/unfinished/regexp2/regexp2.factor b/unfinished/regexp2/regexp2.factor index 24221baeb6..feec8ea97e 100644 --- a/unfinished/regexp2/regexp2.factor +++ b/unfinished/regexp2/regexp2.factor @@ -3,7 +3,8 @@ USING: accessors combinators kernel math math.ranges sequences regexp2.backend regexp2.utils memoize sets regexp2.parser regexp2.nfa regexp2.dfa regexp2.traversal -regexp2.transition-tables ; +regexp2.transition-tables assocs prettyprint.backend +make ; IN: regexp2 : default-regexp ( string -- regexp ) @@ -14,6 +15,7 @@ IN: regexp2 <transition-table> >>minimized-table H{ } clone >>nfa-traversal-flags H{ } clone >>dfa-traversal-flags + H{ } clone >>options reset-regexp ; : construct-regexp ( regexp -- regexp' ) @@ -60,3 +62,30 @@ IN: regexp2 : R` CHAR: ` <regexp> ; parsing : R{ CHAR: } <regexp> ; parsing : R| CHAR: | <regexp> ; parsing + +: find-regexp-syntax ( string -- prefix suffix ) + { + { "R/ " "/" } + { "R! " "!" } + { "R\" " "\"" } + { "R# " "#" } + { "R' " "'" } + { "R( " ")" } + { "R@ " "@" } + { "R[ " "]" } + { "R` " "`" } + { "R{ " "}" } + { "R| " "|" } + } swap [ subseq? not nip ] curry assoc-find drop ; + +: option? ( option regexp -- ? ) + options>> key? ; + +M: regexp pprint* + [ + [ + dup raw>> + dup find-regexp-syntax swap % swap % % + case-insensitive swap option? [ "i" % ] when + ] "" make + ] keep present-text ; diff --git a/unfinished/regexp2/traversal/traversal.factor b/unfinished/regexp2/traversal/traversal.factor index 0bc304bfe0..ba9284c110 100644 --- a/unfinished/regexp2/traversal/traversal.factor +++ b/unfinished/regexp2/traversal/traversal.factor @@ -45,7 +45,9 @@ TUPLE: dfa-traverser ] when text-finished? ; : increment-state ( dfa-traverser state -- dfa-traverser ) - >r [ 1+ ] change-current-index dup current-state>> >>last-state r> + [ + [ 1+ ] change-current-index dup current-state>> >>last-state + ] dip first >>current-state ; : match-failed ( dfa-traverser -- dfa-traverser ) diff --git a/unfinished/regexp2/utils/utils.factor b/unfinished/regexp2/utils/utils.factor index 48c68d883f..ab51436f8b 100644 --- a/unfinished/regexp2/utils/utils.factor +++ b/unfinished/regexp2/utils/utils.factor @@ -9,7 +9,7 @@ IN: regexp2.utils : (while-changes) ( obj quot pred pred-ret -- obj ) ! quot: ( obj -- obj' ) ! pred: ( obj -- <=> ) - >r >r dup slip r> pick over call r> dupd = + [ [ dup slip ] dip pick over call ] dip dupd = [ 3drop ] [ (while-changes) ] if ; inline recursive : while-changes ( obj quot pred -- obj' ) From 7f832de824b131c06a1400baa94b3bb75971c5d7 Mon Sep 17 00:00:00 2001 From: Doug Coleman <doug.coleman@gmail.com> Date: Fri, 12 Sep 2008 22:04:35 -0500 Subject: [PATCH 07/16] fix help-lint --- basis/mime-types/mime-types-docs.factor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basis/mime-types/mime-types-docs.factor b/basis/mime-types/mime-types-docs.factor index 058a71d838..b7fa46d587 100644 --- a/basis/mime-types/mime-types-docs.factor +++ b/basis/mime-types/mime-types-docs.factor @@ -11,7 +11,7 @@ HELP: mime-db HELP: mime-type { $values - { "path" "a pathname string" } + { "filename" "a filename" } { "mime-type" "a MIME type string" } } { $description "Outputs the MIME type associtated with a path by parsing the path's file extension and looking it up in the table returned by " { $link mime-types } "." } ; From 7ba28ac8d5c45a638cd8027097e476e99c998d98 Mon Sep 17 00:00:00 2001 From: Slava Pestov <slava@slava-pestovs-macbook-pro.local> Date: Sat, 13 Sep 2008 02:37:16 -0500 Subject: [PATCH 08/16] Clean up raytracer a bit --- extra/benchmark/raytracer/raytracer.factor | 60 +++++++++++----------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/extra/benchmark/raytracer/raytracer.factor b/extra/benchmark/raytracer/raytracer.factor index 69454505a5..34bac61292 100755 --- a/extra/benchmark/raytracer/raytracer.factor +++ b/extra/benchmark/raytracer/raytracer.factor @@ -3,7 +3,7 @@ USING: arrays accessors float-arrays io io.files io.encodings.binary kernel math math.functions math.vectors -math.parser make sequences sequences.private words ; +math.parser make sequences sequences.private words hints ; IN: benchmark.raytracer ! parameters @@ -38,34 +38,40 @@ TUPLE: sphere { center float-array read-only } { radius float read-only } ; C: <sphere> sphere : sphere-v ( sphere ray -- v ) - swap center>> swap orig>> v- ; inline + [ center>> ] [ orig>> ] bi* v- ; inline -: sphere-b ( ray v -- b ) swap dir>> v. ; inline +: sphere-b ( v ray -- b ) + dir>> v. ; inline -: sphere-disc ( sphere v b -- d ) - sq swap norm-sq - swap radius>> sq + ; inline +: sphere-d ( sphere b v -- d ) + [ radius>> sq ] [ sq ] [ norm-sq ] tri* - + ; inline -: -+ ( x y -- x-y x+y ) [ - ] 2keep + ; inline +: -+ ( x y -- x-y x+y ) + [ - ] [ + ] 2bi ; inline -: sphere-b/d ( b d -- t ) +: sphere-t ( b d -- t ) -+ dup 0.0 < [ 2drop 1.0/0.0 ] [ [ [ 0.0 > ] keep ] dip ? ] if ; inline -: ray-sphere ( sphere ray -- t ) - 2dup sphere-v tuck sphere-b [ sphere-disc ] keep - over 0.0 < [ 2drop 1.0/0.0 ] [ swap sqrt sphere-b/d ] if ; - inline +: sphere-b&v ( sphere ray -- b v ) + [ sphere-v ] [ nip ] 2bi + [ sphere-b ] [ drop ] 2bi ; inline -: sphere-n ( ray sphere l -- n ) - pick dir>> n*v swap center>> v- swap orig>> v+ ; - inline +: ray-sphere ( sphere ray -- t ) + [ drop ] [ sphere-b&v ] 2bi + [ drop ] [ sphere-d ] 3bi + dup 0.0 < [ 3drop 1/0. ] [ sqrt sphere-t nip ] if ; inline : if-ray-sphere ( hit ray sphere quot -- hit ) #! quot: hit ray sphere l -- hit [ - pick lambda>> [ 2dup swap ray-sphere dup ] dip >= - [ 3drop ] - ] dip if ; inline + [ ] [ swap ray-sphere nip ] [ 2drop lambda>> ] 3tri + [ drop ] [ < ] 2bi + ] dip [ 3drop ] if ; inline + +: sphere-n ( ray sphere l -- n ) + [ [ orig>> ] [ dir>> ] bi ] [ center>> ] [ ] tri* + swap [ v*n ] dip v- v+ ; inline M: sphere intersect-scene ( hit ray sphere -- hit ) [ [ sphere-n normalize ] keep <hit> nip ] if-ray-sphere ; @@ -79,21 +85,17 @@ TUPLE: group < sphere { objs array read-only } ; swap [ { } make ] dip <group> ; inline M: group intersect-scene ( hit ray group -- hit ) - [ - drop - objs>> [ [ tuck ] dip intersect-scene swap ] each - drop - ] if-ray-sphere ; + [ drop objs>> [ intersect-scene ] with each ] if-ray-sphere ; -: initial-hit T{ hit f F{ 0.0 0.0 0.0 } 1.0/0.0 } ; inline +: initial-hit T{ hit f F{ 0.0 0.0 0.0 } 1/0. } ; inline : initial-intersect ( ray scene -- hit ) - initial-hit -rot intersect-scene ; inline + [ initial-hit ] 2dip intersect-scene ; inline : ray-o ( ray hit -- o ) - over dir>> over lambda>> v*n - swap normal>> delta v*n v+ - swap orig>> v+ ; inline + [ [ orig>> ] [ normal>> delta v*n ] bi* ] + [ [ dir>> ] [ lambda>> ] bi* v*n ] + 2bi v+ v+ ; inline : sray-intersect ( ray scene hit -- ray ) swap [ ray-o light vneg <ray> ] dip initial-intersect ; inline @@ -101,10 +103,10 @@ M: group intersect-scene ( hit ray group -- hit ) : ray-g ( hit -- g ) normal>> light v. ; inline : cast-ray ( ray scene -- g ) - 2dup initial-intersect dup lambda>> 1.0/0.0 = [ + 2dup initial-intersect dup lambda>> 1/0. = [ 3drop 0.0 ] [ - [ sray-intersect lambda>> 1.0/0.0 = ] keep swap + [ sray-intersect lambda>> 1/0. = ] keep swap [ ray-g neg ] [ drop 0.0 ] if ] if ; inline From 2cc40052bfeffb82a31f76a005ace9c6e3e6249d Mon Sep 17 00:00:00 2001 From: Slava Pestov <slava@slava-pestovs-macbook-pro.local> Date: Sat, 13 Sep 2008 03:06:36 -0500 Subject: [PATCH 09/16] Rewrite locals-in-literals in idiomatic Factor, and fix a performance regression with locals in tuples --- basis/locals/locals-tests.factor | 4 +- basis/locals/locals.factor | 93 +++++++++++--------------------- 2 files changed, 35 insertions(+), 62 deletions(-) diff --git a/basis/locals/locals-tests.factor b/basis/locals/locals-tests.factor index 59ec325f39..eb06d05146 100755 --- a/basis/locals/locals-tests.factor +++ b/basis/locals/locals-tests.factor @@ -329,4 +329,6 @@ M:: sequence method-with-locals ( a -- y ) a reverse ; [ 10 20 30 [| a b c | H{ { a "a" } { b "b" } { c "c" } } ] call ] unit-test [ T{ slice f 0 3 "abc" } ] -[ 0 3 "abc" [| from to seq | T{ slice f from to seq } ] call ] unit-test \ No newline at end of file +[ 0 3 "abc" [| from to seq | T{ slice f from to seq } ] call ] unit-test + +{ 3 1 } [| from to seq | T{ slice f from to seq } ] must-infer-as \ No newline at end of file diff --git a/basis/locals/locals.factor b/basis/locals/locals.factor index bfc92ee9e2..05ea3cb524 100755 --- a/basis/locals/locals.factor +++ b/basis/locals/locals.factor @@ -6,7 +6,7 @@ quotations debugger macros arrays macros splitting combinators prettyprint.backend definitions prettyprint hashtables prettyprint.sections sets sequences.private effects effects.parser generic generic.parser compiler.units accessors -locals.backend memoize macros.expander lexer +locals.backend memoize macros.expander lexer classes stack-checker.known-words ; IN: locals @@ -195,70 +195,41 @@ M: block lambda-rewrite* swap point-free , ] keep length \ curry <repetition> % ; +GENERIC: rewrite-element ( obj -- ) + +: rewrite-elements ( seq -- ) + [ rewrite-element ] each ; + +: rewrite-sequence ( seq -- ) + [ rewrite-elements ] [ length , ] [ , ] tri \ nsequence , ; + +M: array rewrite-element rewrite-sequence ; + +M: vector rewrite-element rewrite-sequence ; + +M: hashtable rewrite-element >alist rewrite-sequence \ >hashtable , ; + +M: tuple rewrite-element + [ tuple-slots rewrite-elements ] [ class , ] bi \ boa , ; + +M: local rewrite-element , ; + +M: word rewrite-element literalize , ; + +M: object rewrite-element , ; + +M: array local-rewrite* rewrite-element ; + +M: vector local-rewrite* rewrite-element ; + +M: tuple local-rewrite* rewrite-element ; + +M: hashtable local-rewrite* rewrite-element ; + M: object lambda-rewrite* , ; M: object local-rewrite* , ; -! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -! Broil is used to support locals in literals - -DEFER: [broil] -DEFER: [broil-hashtable] -DEFER: [broil-tuple] - -: broil-element ( obj -- quot ) - { - { [ dup number? ] [ 1quotation ] } - { [ dup string? ] [ 1quotation ] } - { [ dup sequence? ] [ [broil] ] } - { [ dup hashtable? ] [ [broil-hashtable] ] } - { [ dup tuple? ] [ [broil-tuple] ] } - { [ dup local? ] [ 1quotation ] } - { [ dup word? ] [ literalize 1quotation ] } - { [ t ] [ 1quotation ] } - } - cond ; - -: [broil] ( seq -- quot ) - [ [ broil-element ] map concat >quotation ] - [ length ] - [ ] - tri - [ nsequence ] curry curry compose ; - -MACRO: broil ( seq -- quot ) [broil] ; - -: [broil-hashtable] ( hashtable -- quot ) - >alist - [ [ broil-element ] map concat >quotation ] - [ length ] - [ ] - tri - [ nsequence >hashtable ] curry curry compose ; - -MACRO: broil-hashtable ( hashtable -- quot ) [broil-hashtable] ; - -: [broil-tuple] ( tuple -- quot ) - tuple>array - [ [ broil-element ] map concat >quotation ] - [ length ] - [ ] - tri - [ nsequence >tuple ] curry curry compose ; - -MACRO: broil-tuple ( tuple -- quot ) [broil-tuple] ; - -! Engage broil on arrays and vectors. Can't do it on 'sequence' -! because that will pick up strings and integers. What do do... - -M: array local-rewrite* ( array -- ) [broil] % ; -M: vector local-rewrite* ( vector -- ) [broil] % ; -M: tuple local-rewrite* ( tuple -- ) [broil-tuple] % ; -M: hashtable local-rewrite* ( hashtable -- ) [broil-hashtable] % ; - -! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - : make-local ( name -- word ) "!" ?tail [ <local-reader> From 01129fb9bd9ad598bc2889125edb7d2ff681f230 Mon Sep 17 00:00:00 2001 From: Slava Pestov <slava@slava-pestovs-macbook-pro.local> Date: Sat, 13 Sep 2008 03:09:16 -0500 Subject: [PATCH 10/16] Add unit test for locals performance regresion --- basis/compiler/tree/propagation/propagation-tests.factor | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/basis/compiler/tree/propagation/propagation-tests.factor b/basis/compiler/tree/propagation/propagation-tests.factor index 6638951723..d73e8b7db1 100644 --- a/basis/compiler/tree/propagation/propagation-tests.factor +++ b/basis/compiler/tree/propagation/propagation-tests.factor @@ -7,7 +7,8 @@ byte-arrays classes.algebra classes.tuple.private math.functions math.private strings layouts compiler.tree.propagation.info compiler.tree.def-use compiler.tree.debugger compiler.tree.checker -slots.private words hashtables classes assocs ; +slots.private words hashtables classes assocs locals +float-arrays ; IN: compiler.tree.propagation.tests \ propagate must-infer @@ -587,6 +588,8 @@ MIXIN: empty-mixin [ { fixnum integer } declare bitand ] final-classes ] unit-test +[ V{ float-array } ] [ [| | F{ } ] final-classes ] unit-test + ! [ V{ string } ] [ ! [ dup string? t xor [ "A" throw ] [ ] if ] final-classes ! ] unit-test From 87797847987eb8c2252e2b3dc3956e78125fd970 Mon Sep 17 00:00:00 2001 From: Slava Pestov <slava@slava-pestovs-macbook-pro.local> Date: Sat, 13 Sep 2008 03:12:52 -0500 Subject: [PATCH 11/16] Support hints on methods --- basis/hints/hints-docs.factor | 21 ++++++++++++++++++--- basis/hints/hints.factor | 5 +++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/basis/hints/hints-docs.factor b/basis/hints/hints-docs.factor index 99c4a2ddfc..347cfd3ef4 100644 --- a/basis/hints/hints-docs.factor +++ b/basis/hints/hints-docs.factor @@ -20,9 +20,24 @@ HELP: specialized-def { $description "Outputs the definition of a word after it has been split into specialized branches. This is the definition which will actually be compiled by the compiler." } ; HELP: HINTS: -{ $values { "word" word } { "hints..." "a list of sequences of classes" } } -{ $description "Defines specialization hints for each words. Each sequence of classes in the list will cause a specialized version of the word to be compiled." } +{ $values { "defspec" "a definition specifier" } { "hints..." "a list of sequences of classes" } } +{ $description "Defines specialization hints for a word or a method." +$nl +"Each sequence of classes in the list will cause a specialized version of the word to be compiled." } { $examples "The " { $link append } " word has a specializer for the very common case where two strings or two arrays are appended:" -{ $code "HINTS: append { string string } { array array } ;" } } ; +{ $code "HINTS: append { string string } { array array } ;" } +"Specializers can also be defined on methods:" +{ $code + "GENERIC: count-occurrences ( elt obj -- n )" + "" + "M: sequence count-occurrences [ = ] with count ;" + "" + "M: assoc count-occurrences" + " swap [ = nip ] curry assoc-filter assoc-size ;" + "" + "HINTS: { sequence count-occurrences } { object array } ;" + "HINTS: { assoc count-occurrences } { object hashtable } ;" +} +} ; ABOUT: "hints" diff --git a/basis/hints/hints.factor b/basis/hints/hints.factor index 1138ad872a..a10588d730 100644 --- a/basis/hints/hints.factor +++ b/basis/hints/hints.factor @@ -42,11 +42,11 @@ IN: hints : specialized-def ( word -- quot ) dup def>> swap { - { [ dup standard-method? ] [ specialize-method ] } { [ dup "specializer" word-prop ] [ "specializer" word-prop specialize-quot ] } + { [ dup standard-method? ] [ specialize-method ] } [ drop ] } cond ; @@ -54,7 +54,8 @@ IN: hints dup [ array? ] all? [ first ] when length ; : HINTS: - scan-word + scan-object + dup method-spec? [ first2 method ] when [ redefined ] [ parse-definition "specializer" set-word-prop ] bi ; parsing From d2646cfe1bc7cba51179131d17adc399c47e6462 Mon Sep 17 00:00:00 2001 From: Eduardo Cavazos <dharmatech@finkelstein.stackeffects.info> Date: Sat, 13 Sep 2008 04:09:13 -0500 Subject: [PATCH 12/16] tools.annotations: Use fry in '(watch)' --- basis/tools/annotations/annotations.factor | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/basis/tools/annotations/annotations.factor b/basis/tools/annotations/annotations.factor index 96c2ec2fcc..6a7e33e615 100755 --- a/basis/tools/annotations/annotations.factor +++ b/basis/tools/annotations/annotations.factor @@ -3,7 +3,7 @@ USING: accessors kernel words parser io summary quotations sequences prettyprint continuations effects definitions compiler.units namespaces assocs tools.walker generic -inspector ; +inspector fry ; IN: tools.annotations GENERIC: reset ( word -- ) @@ -49,10 +49,7 @@ M: word reset .s ] if* "\\--" print flush ; -: (watch) ( word def -- def ) - over [ entering ] curry - rot [ leaving ] curry - swapd 3append ; +: (watch) ( word def -- def ) over '[ _ entering @ _ leaving ] ; : watch ( word -- ) dup [ (watch) ] annotate ; From a211e44bb9264a9e345c132541c462251c6fb5ea Mon Sep 17 00:00:00 2001 From: Slava Pestov <slava@slava-pestovs-macbook-pro.local> Date: Sat, 13 Sep 2008 04:43:29 -0500 Subject: [PATCH 13/16] Found a place to use the locals in literals feature --- basis/compiler/tree/dead-code/recursive/recursive.factor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basis/compiler/tree/dead-code/recursive/recursive.factor b/basis/compiler/tree/dead-code/recursive/recursive.factor index 03d4e919ee..02dc42f058 100644 --- a/basis/compiler/tree/dead-code/recursive/recursive.factor +++ b/basis/compiler/tree/dead-code/recursive/recursive.factor @@ -84,7 +84,7 @@ M:: #recursive remove-dead-code* ( node -- nodes ) drop-outputs [ node drop-recursive-outputs ] | node [ (remove-dead-code) ] change-child drop node label>> [ filter-live ] change-enter-out drop - drop-inputs node drop-outputs 3array + { drop-inputs node drop-outputs } ] ; M: #return-recursive remove-dead-code* ; From d47a76b69bc9881f74602d75baf6eb15e6f5eebc Mon Sep 17 00:00:00 2001 From: Slava Pestov <slava@slava-pestovs-macbook-pro.local> Date: Sat, 13 Sep 2008 06:13:49 -0500 Subject: [PATCH 14/16] 15% improvement --- extra/benchmark/spectral-norm/spectral-norm.factor | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extra/benchmark/spectral-norm/spectral-norm.factor b/extra/benchmark/spectral-norm/spectral-norm.factor index 3c20a1ceff..245027ef77 100644 --- a/extra/benchmark/spectral-norm/spectral-norm.factor +++ b/extra/benchmark/spectral-norm/spectral-norm.factor @@ -32,8 +32,10 @@ IN: benchmark.spectral-norm : eval-AtA-times-u ( u n -- seq ) [ eval-A-times-u ] [ eval-At-times-u ] bi ; inline +: ones ( n -- seq ) [ 1.0 ] F{ } replicate-as ; inline + :: u/v ( n -- u v ) - n 1.0 <repetition> >float-array dup + n ones dup 10 [ drop n eval-AtA-times-u From 1bf65e6dc5a91fd8bd2fa3ca22c5af53f5ea32f1 Mon Sep 17 00:00:00 2001 From: Eduardo Cavazos <dharmatech@finkelstein.stackeffects.info> Date: Sat, 13 Sep 2008 11:12:36 -0500 Subject: [PATCH 15/16] tools.annotations: Use fry in '(watch-vars)' --- basis/tools/annotations/annotations.factor | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/basis/tools/annotations/annotations.factor b/basis/tools/annotations/annotations.factor index 6a7e33e615..c836bfc2b6 100755 --- a/basis/tools/annotations/annotations.factor +++ b/basis/tools/annotations/annotations.factor @@ -55,11 +55,12 @@ M: word reset dup [ (watch) ] annotate ; : (watch-vars) ( quot word vars -- newquot ) - [ - "--- Entering: " write swap . - "--- Variable values:" print - [ dup get ] H{ } map>assoc describe - ] 2curry prepose ; + rot + '[ + "--- Entering: " write _ . + "--- Variable values:" print _ [ dup get ] H{ } map>assoc describe + @ + ] ; : watch-vars ( word vars -- ) dupd [ (watch-vars) ] 2curry annotate ; From 8b9784108e5d8b7d50fc0104ab745652b1cc1b37 Mon Sep 17 00:00:00 2001 From: Slava Pestov <slava@slava-pestovs-macbook-pro.local> Date: Sat, 13 Sep 2008 14:25:06 -0500 Subject: [PATCH 16/16] Don't clobber RBX --- basis/cpu/x86/32/32.factor | 4 ---- basis/cpu/x86/64/64.factor | 15 +++++---------- basis/cpu/x86/architecture/architecture.factor | 2 -- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/basis/cpu/x86/32/32.factor b/basis/cpu/x86/32/32.factor index 67a8ec8a2c..5328f2a263 100755 --- a/basis/cpu/x86/32/32.factor +++ b/basis/cpu/x86/32/32.factor @@ -62,10 +62,6 @@ M: float-regs store-return-reg load/store-float-return FSTP ; : with-aligned-stack ( n quot -- ) swap dup align-sub slip align-add ; inline -! On x86, we can always use an address as an operand -! directly. -M: x86.32 address-operand ; - M: x86.32 fixnum>slot@ 1 SHR ; M: x86.32 prepare-division CDQ ; diff --git a/basis/cpu/x86/64/64.factor b/basis/cpu/x86/64/64.factor index 4770c09a83..c135d0490d 100755 --- a/basis/cpu/x86/64/64.factor +++ b/basis/cpu/x86/64/64.factor @@ -33,13 +33,6 @@ M: float-regs vregs M: float-regs param-regs drop { XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 } ; -M: x86.64 address-operand ( address -- operand ) - #! On AMD64, we have to load 64-bit addresses into a - #! scratch register first. The usage of R11 here is a hack. - #! This word can only be called right before a subroutine - #! call, where all vregs have been flushed anyway. - temp-reg v>operand [ swap MOV ] keep ; - M: x86.64 fixnum>slot@ drop ; M: x86.64 prepare-division CQO ; @@ -49,8 +42,8 @@ M: x86.64 load-indirect ( literal reg -- ) M: stack-params %load-param-reg drop - >r temp-reg v>operand swap stack@ MOV - r> stack@ temp-reg v>operand MOV ; + >r R11 swap stack@ MOV + r> stack@ R11 MOV ; M: stack-params %save-param-reg >r stack-frame* + cell + swap r> %load-param-reg ; @@ -138,7 +131,9 @@ M: x86.64 %alien-global [ 0 MOV rc-absolute-cell rel-dlsym ] [ dup [] MOV ] bi ; M: x86.64 %alien-invoke - 0 address-operand >r rc-absolute-cell rel-dlsym r> CALL ; + R11 0 MOV + rc-absolute-cell rel-dlsym + R11 CALL ; M: x86.64 %prepare-alien-indirect ( -- ) "unbox_alien" f %alien-invoke diff --git a/basis/cpu/x86/architecture/architecture.factor b/basis/cpu/x86/architecture/architecture.factor index 171e67bcfb..04b496f12a 100755 --- a/basis/cpu/x86/architecture/architecture.factor +++ b/basis/cpu/x86/architecture/architecture.factor @@ -39,8 +39,6 @@ GENERIC: store-return-reg ( stack@ reg-class -- ) HOOK: temp-reg-1 cpu ( -- reg ) HOOK: temp-reg-2 cpu ( -- reg ) -HOOK: address-operand cpu ( address -- operand ) - HOOK: fixnum>slot@ cpu ( op -- ) HOOK: prepare-division cpu ( -- )