]> gitweb.factorcode.org Git - factor.git/commitdiff
Working on method inlining optimization
authorslava <slava@factorcode.org>
Tue, 2 May 2006 18:16:59 +0000 (18:16 +0000)
committerslava <slava@factorcode.org>
Tue, 2 May 2006 18:16:59 +0000 (18:16 +0000)
13 files changed:
TODO.FACTOR.txt
library/bootstrap/primitives.factor
library/cocoa/utilities.factor
library/collections/lists.factor
library/collections/sequences.factor
library/compiler/optimizer/call-optimizers.factor
library/compiler/optimizer/class-infer.factor
library/compiler/optimizer/inline-methods.factor
library/compiler/ppc/intrinsics.factor
library/generic/generic.factor
library/generic/math-combination.factor
library/kernel.factor
library/test/generic.factor

index 579f039da7d065cb0a2e06ac89d9584158ca282a..d7acafcbb43d7b10f3b1b5338358d3cfe446967e 100644 (file)
@@ -1,6 +1,5 @@
 should fix in 0.82:
 
-- type inference busted for tuple constructors
 - constant branch folding
 - fast-slot stuff
 - 3 >n fep
index ac6724851f006796357d55351ac042b78b91af86..6e4911ea2c7d0e6cd3cd5a5e56713687dd2781c8 100644 (file)
@@ -258,12 +258,10 @@ num-types f <array> builtins set
 
 "fixnum?" "math" create t "inline" set-word-prop
 "fixnum" "math" create 0 "fixnum?" "math" create { } define-builtin
-"fixnum" "math" create 0 "math-priority" set-word-prop
 "fixnum" "math" create ">fixnum" "math" lookup unit "coercer" set-word-prop
 
 "bignum?" "math" create t "inline" set-word-prop
 "bignum" "math" create 1 "bignum?" "math" create { } define-builtin
-"bignum" "math" create 1 "math-priority" set-word-prop
 "bignum" "math" create ">bignum" "math" lookup unit "coercer" set-word-prop
 
 "cons?" "lists" create t "inline" set-word-prop
@@ -279,11 +277,9 @@ num-types f <array> builtins set
     { 0 integer { "numerator" "math" } f }
     { 1 integer { "denominator" "math" } f }
 } define-builtin
-"ratio" "math" create 2 "math-priority" set-word-prop
 
 "float?" "math" create t "inline" set-word-prop
 "float" "math" create 5 "float?" "math" create { } define-builtin
-"float" "math" create 3 "math-priority" set-word-prop
 "float" "math" create ">float" "math" lookup unit "coercer" set-word-prop
 
 "complex?" "math" create t "inline" set-word-prop
@@ -292,7 +288,6 @@ num-types f <array> builtins set
     { 0 real { "real" "math" } f }
     { 1 real { "imaginary" "math" } f }
 } define-builtin
-"complex" "math" create 4 "math-priority" set-word-prop
 
 "alien" "alien" create 7 "alien?" "alien" create
 { { 1 object { "underlying-alien" "alien" } f } } define-builtin
index f35555a915cacd2ab43614bf646c8b83dc0dde17..966e456f3ec5e219f40c9361fbb1b6af2ac9bd37 100644 (file)
@@ -119,9 +119,6 @@ H{
 : class-methods ( classname -- seq )
     objc-meta-class objc-methods ;
 
-: make-dip ( quot n -- quot )
-    dup \ >r <array> -rot \ r> <array> append3 ;
-
 : <super> ( receiver class -- super )
     "objc-super" <c-object>
     [ set-objc-super-class ] keep
index 79c6aa5ff81a33e6bece5145bb32e8e05519a880..da71c523b95d0ee8d9db187dabfc7ca939d8ae2d 100644 (file)
@@ -1,6 +1,6 @@
 ! Copyright (C) 2003, 2005 Slava Pestov.
 ! See http://factor.sf.net/license.txt for BSD license.
-IN: lists USING: errors generic kernel math sequences ;
+IN: lists USING: arrays errors generic kernel math sequences ;
 
 M: f car ;
 M: f cdr ;
@@ -79,6 +79,9 @@ M: cons = ( obj cons -- ? )
 
 : curry ( obj quot -- quot ) >r literalize r> cons ;
 
+: make-dip ( quot n -- quot )
+    dup \ >r <array> -rot \ r> <array> append3 >list ;
+
 : (>list) ( n i seq -- list )
     pick pick <= [
         3drop [ ]
index 6ce835d229195b1e08c682f7766d00e2d11efd51..fbcd04dfbbe7fbbc207b0dda53eb47cb628af660 100644 (file)
@@ -26,7 +26,7 @@ GENERIC: reverse-slice ( seq -- seq ) flushable
     [ 1 <vector> ] unless* [ push ] keep ;
 
 : bounds-check? ( n seq -- ? )
-    over 0 >= [ length < ] [ 2drop f ] if ;
+    over 0 >= [ length < ] [ 2drop f ] if ; inline
 
 : ?nth ( n seq/f -- elt/f )
     2dup bounds-check? [ nth ] [ 2drop f ] if ;
index 4d627d5d3ec48d96527e140f98da1d5fdda8b151..e74453ad0b2a90ee32e13dec0ee69a519404354b 100644 (file)
@@ -63,7 +63,7 @@ math math-internals sequences words ;
 } define-optimizers
 
 : useless-coerce? ( node -- )
-    dup node-in-d first over node-class
+    dup 0 node-class#
     swap node-param "infer-effect" word-prop second first eq? ;
 
 : call>no-op ( node -- node )
index 5a7d2cce4f741299bc51e55f6fc46a4d076b4383..04bb4877658e3f6a4e28f7db24cc43a11773e74f 100644 (file)
@@ -9,6 +9,9 @@ kernel-internals math namespaces sequences words ;
 : node-class ( value node -- class )
     node-classes ?hash [ object ] unless* ;
 
+: node-class# ( node n -- class )
+    swap [ node-in-d reverse-slice nth ] keep node-class ;
+
 ! Variables used by the class inferencer
 
 ! Current value --> class mapping
index 92ce37745e981466a08ba847a9ca75d623589ab5..de85a18be8d036e1aa6b336086df2e8d1e1b74fd 100644 (file)
@@ -1,37 +1,10 @@
 ! Copyright (C) 2004, 2006 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 IN: optimizer
-USING: arrays generic hashtables inference kernel lists math
-namespaces sequences words ;
-
-! Method inlining optimization
-: dispatch# ( #call -- n )
-    node-param "combination" word-prop first ;
-
-: dispatching-class ( node -- seq )
-    dup dispatch# over node-in-d reverse-slice nth
-    swap node-class ;
-
-: already-inlined? ( node -- ? )
-    #! Was this node inlined from definition of 'word'?
-    dup node-param swap node-history memq? ;
-
-: specific-method ( word class -- ? ) swap order min-class ;
-
-: inlining-class ( #call -- class )
-    #! If the generic dispatch can be eliminated, return the
-    #! class of the method that will always be invoked here.
-    dup node-param swap dispatching-class
-    specific-method ;
-
-: will-inline-method ( node -- quot/t )
-    #! t indicates failure
-    dup inlining-class dup [
-        swap node-param "methods" word-prop hash
-    ] [
-        2drop t
-    ] if ;
+USING: arrays generic hashtables inference kernel
+kernel-internals lists math namespaces sequences words ;
 
+! Some utilities for splicing in dataflow IR subtrees
 : post-inline ( #return/#values #call/#merge -- )
     dup [
         [
@@ -54,63 +27,71 @@ namespaces sequences words ;
     ] [
         over node-in-d dataflow-with
         [ >r node-param r> remember-node ] 2keep
-        [ subst-node ] keep
+        [ subst-node ] keep [ infer-classes ] keep
     ] if ;
 
-: inline-standard-method ( node -- node )
-    dup will-inline-method (inline-method) ;
+! Single dispatch method inlining optimization
+: dispatch# ( #call -- n )
+    node-param "combination" word-prop first ;
 
-: comparable? ( actual testing -- ? )
-    #! If actual is a subset of testing or if the two classes
-    #! are disjoint, return t.
-    2dup class< >r classes-intersect? not r> or ;
+: dispatching-class ( node -- seq ) dup dispatch# node-class# ;
 
-: optimize-predicate? ( #call -- ? )
-    dup node-param "predicating" word-prop dup [
-        >r dup node-in-d node-classes* first r> comparable?
+: already-inlined? ( node -- ? )
+    #! Was this node inlined from definition of 'word'?
+    dup node-param swap node-history memq? ;
+
+: specific-method ( word class -- ? ) swap order min-class ;
+
+: inlining-class ( #call -- class )
+    #! If the generic dispatch can be eliminated, return the
+    #! class of the method that will always be invoked here.
+    dup node-param swap dispatching-class
+    specific-method ;
+
+: will-inline-method ( node -- quot/t )
+    #! t indicates failure
+    dup inlining-class dup [
+        swap node-param "methods" word-prop hash
     ] [
-        2drop f
+        2drop t
     ] if ;
 
-: inline-literals ( node literals -- node )
-    #! Make #shuffle -> #push -> #return -> successor
-    over drop-inputs [
-        >r >list [ literalize ] map dataflow [ subst-node ] keep
-        r> set-node-successor
-    ] keep ;
+: inline-standard-method ( node -- node )
+    dup will-inline-method (inline-method) ;
 
-: optimize-predicate ( #call -- node )
-    dup node-param "predicating" word-prop >r
-    dup dup node-in-d node-classes* first r> class<
-    1array inline-literals ;
+: inline-standard-method? ( #call -- ? )
+    dup already-inlined? not swap node-param standard-generic?
+    and ;
 
+! Partial dispatch of 2generic words
 : math-both-known? ( word left right -- ? )
     math-class-max specific-method ;
-    
-: partial-math ( word class left/right -- vtable )
-    dup \ dup \ over ? [
-        ( word class left/right class )
-        >r 3dup r> swap [ swap ] unless math-method
-    ] math-vtable >r 3drop r> ;
+
+: max-tag ( class -- n ) types peek 1+ num-tags min ;
+
+: left-partial-math ( word left right -- quot/t )
+    #! The left type is known; dispatch on right
+    \ dup swap max-tag
+    [ >r 2dup r> math-method ] math-vtable* 2nip ;
+
+: right-partial-math ( word left right -- quot/t )
+    #! The right type is known; dispatch on left
+    \ over rot max-tag
+    [ >r 2dup r> swap math-method ] math-vtable* 2nip ;
 
 : will-inline-math-method ( word left right -- quot/t )
     #! t indicates failure
     {
         { [ 3dup math-both-known? ] [ math-method ] }
-        { [ 3dup drop specific-method ] [ drop t partial-math ] }
-        { [ 3dup nip specific-method ] [ nip f partial-math ] }
+        { [ 3dup drop specific-method ] [ left-partial-math ] }
+        { [ 3dup nip specific-method ] [ right-partial-math ] }
         { [ t ] [ 3drop t ] }
     } cond ;
 
 : inline-math-method ( #call -- node )
-    dup node-param
-    over dup node-in-d [ swap node-class ] map-with first2
+    dup node-param over 1 node-class# pick 0 node-class#
     will-inline-math-method (inline-method) ;
 
-: inline-standard-method? ( #call -- ? )
-    dup already-inlined? not swap node-param standard-generic?
-    and ;
-
 : inline-math-method? ( #call -- ? )
     dup node-history empty? swap node-param 2generic? and ;
 
@@ -120,3 +101,27 @@ namespaces sequences words ;
         { [ dup inline-math-method? ] [ inline-math-method ] }
         { [ t ] [ drop t ] }
     } cond ;
+
+! Resolve type checks at compile time where possible
+: comparable? ( actual testing -- ? )
+    #! If actual is a subset of testing or if the two classes
+    #! are disjoint, return t.
+    2dup class< >r classes-intersect? not r> or ;
+
+: optimize-predicate? ( #call -- ? )
+    dup node-param "predicating" word-prop dup [
+        >r dup 0 node-class# r> comparable?
+    ] [
+        2drop f
+    ] if ;
+
+: inline-literals ( node literals -- node )
+    #! Make #shuffle -> #push -> #return -> successor
+    over drop-inputs [
+        >r >list [ literalize ] map dataflow [ subst-node ] keep
+        r> set-node-successor
+    ] keep ;
+
+: optimize-predicate ( #call -- node )
+    dup node-param "predicating" word-prop >r
+    dup 0 node-class# r> class< 1array inline-literals ;
index 9c48ea384489ab42b8de24942421a237753fac65..9432aee2eb386582013a271bbbef236f22fc9c3a 100644 (file)
@@ -67,7 +67,7 @@ math-internals namespaces sequences words ;
 ] H{
     { +input { { f "val" } { f "obj" } { f "slot" } } }
     { +scratch { { f "x" } } }
-    { +clobber { "obj" } }
+    { +clobber { "obj" "slot" } }
 } define-intrinsic
 
 \ set-char-slot [
@@ -77,7 +77,7 @@ math-internals namespaces sequences words ;
 ] H{
     { +input { { f "val" } { f "slot" } { f "obj" } } }
     { +scratch { { f "x" } } }
-    { +clobber { "obj" } }
+    { +clobber { "val" "slot" "obj" } }
 } define-intrinsic
 
 : define-binary-op ( word op -- )
index f1c7fa994806cf55afc15abe5f28a874903141d0..50dd6536992b91b023b31d7fbad91abf0a2d087f 100644 (file)
@@ -39,7 +39,7 @@ SYMBOL: builtins
     ] hash-each ;
 
 : types ( class -- types )
-    [ (types) ] make-hash hash-keys ;
+    [ (types) ] make-hash hash-keys natural-sort ;
 
 DEFER: class<
 
index c7d2af088231a9639e917b346289c0dca8e27223..8f2a0a05a8eb438e246f242be51ec14a67768151 100644 (file)
@@ -1,35 +1,29 @@
 ! Copyright (C) 2005 Slava Pestov.
 ! See http://factor.sf.net/license.txt for BSD license.
 IN: generic
-USING: errors generic hashtables kernel kernel-internals lists
-math namespaces sequences words ;
+USING: arrays errors generic hashtables kernel kernel-internals
+lists math namespaces sequences words ;
 
 ! Math combination for generic dyadic upgrading arithmetic.
 
-: math-priority ( class -- n )
-    dup "members" word-prop [
-        0 [ math-priority max ] reduce
-    ] [
-        "math-priority" word-prop [ 100 ] unless*
-    ] ?if ;
+: first/last ( seq -- pair ) dup first swap peek 2array ;
 
-: math-class< ( class class -- ? )
-    [ math-priority ] 2apply < ;
+: math-class-compare ( class class -- n )
+    [
+        dup number class<
+        [ types first/last ] [ drop { 100 100 } ] if
+    ] 2apply <=> ;
 
 : math-class-max ( class class -- class )
-    [ swap math-class< ] 2keep ? ;
+    [ math-class-compare 0 > ] 2keep ? ;
+
+: (math-upgrade) ( max class -- quot )
+    dupd = [ drop [ ] ] [ "coercer" word-prop ] if ;
 
 : math-upgrade ( left right -- quot )
-    2dup math-class< [
-        nip "coercer" word-prop
-        dup [ [ >r ] swap [ r> ] append3 ] when
-    ] [
-        2dup swap math-class< [
-            drop "coercer" word-prop
-        ] [
-            2drop [ ]
-        ] if
-    ] if ;
+    [ math-class-max ] 2keep
+    >r over r> (math-upgrade)
+    >r (math-upgrade) dup [ 1 make-dip ] when r> append ;
 
 TUPLE: no-math-method left right generic ;
 
@@ -52,13 +46,16 @@ TUPLE: no-math-method left right generic ;
         2drop object-method
     ] if ;
 
-: math-vtable ( picker quot -- quot )
+: math-vtable* ( picker max quot -- quot )
     [
-        swap , \ tag ,
-        [ num-tags [ type>class ] map swap map % ] { } make ,
+        rot , \ tag ,
+        [ >r [ type>class ] map r> map % ] { } make ,
         \ dispatch ,
     ] [ ] make ; inline
 
+: math-vtable ( picker quot -- quot )
+    num-tags swap math-vtable* ; inline
+
 : math-class? ( object -- ? )
     dup word? [ "math-priority" word-prop ] [ drop f ] if ;
 
index 871a0889b65473642fc7432740fe8b563ba4865b..c18ff92ce19dba00a10efac87ddffe43ba6b28b5 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2004, 2006 Slava Pestov.
-! See http://factor.sf.net/license.txt for BSD license.
+! See http://factorcode.org/license.txt for BSD license.
 IN: kernel
-USING: generic kernel-internals math-internals ;
+USING: generic kernel-internals math math-internals ;
 
 : 2swap ( x y z t -- z t x y ) rot >r rot r> ; inline
 
@@ -81,7 +81,7 @@ IN: kernel-internals
 ! These words are unsafe. Don't use them.
 : declare ( types -- ) drop ;
 
-: array-capacity 1 slot ; inline
+: array-capacity 1 slot { fixnum } declare ; inline
 : array-nth swap 2 fixnum+fast slot ; inline
 : set-array-nth swap 2 fixnum+fast set-slot ; inline
 
index 84f044a2e442935688bd6cd87fb3621be445444e..c1075377e2c0fb9ef265c59cc64c6338964ef8ad 100644 (file)
@@ -200,3 +200,11 @@ TUPLE: delegating ;
 [ t ] [ \ + 2generic? ] unit-test
 
 [ "SYMBOL: not-a-class C: not-a-class ;" parse ] unit-test-fails
+
+! Test math-combination
+[ [ >r >float r> ] ] [ \ real \ float math-upgrade ] unit-test
+[ [ >float ] ] [ \ float \ real math-upgrade ] unit-test
+[ [ >r >bignum r> ] ] [ \ fixnum \ bignum math-upgrade ] unit-test
+[ [ >float ] ] [ \ float \ integer math-upgrade ] unit-test
+[ number ] [ \ number \ float math-class-max ] unit-test
+[ float ] [ \ real \ float math-class-max ] unit-test