]> gitweb.factorcode.org Git - factor.git/commitdiff
type check optimization is here
authorSlava Pestov <slava@factorcode.org>
Fri, 31 Dec 2004 07:17:45 +0000 (07:17 +0000)
committerSlava Pestov <slava@factorcode.org>
Fri, 31 Dec 2004 07:17:45 +0000 (07:17 +0000)
20 files changed:
TODO.FACTOR.txt
library/bootstrap/boot-stage2.factor
library/compiler/alien.factor
library/compiler/assembly-x86.factor
library/compiler/generator-x86.factor
library/compiler/generator.factor
library/generic/generic.factor
library/generic/predicate.factor
library/inference/branches.factor
library/inference/inference.factor
library/inference/types.factor
library/inference/words.factor
library/kernel.factor
library/math/complex.factor
library/math/ratio.factor
library/primitives.factor
library/strings.factor
library/test/dataflow.factor
library/test/inference.factor
library/words.factor

index aa43a2f9d4411c08842967e722284a11556d9d04..9bec611f5f5f6da1f1c7d24913355809626aab45 100644 (file)
@@ -5,13 +5,8 @@
 [error] AWT-EventQueue-0:  at factor.jedit.WordPreview.actionPerformed(WordPreview.java:79)\r
 [error] AWT-EventQueue-0:  at javax.swing.Timer.fireActionPerformed(Timer.java:271)\r
 \r
-+ inference/dataflow:\r
-\r
-- type inference\r
-\r
 + compiler:\r
 \r
-- slot compilation\r
 - optimize away dispatch\r
 - getenv/setenv: if literal arg, compile as a load/store\r
 - assembler opcodes dispatch on operand types\r
index a60881b94b939fc06e76f3d6f4d84bcf76206f71..b8b569c4750930580094ea60dbdb142d7a87a2fa 100644 (file)
@@ -117,6 +117,7 @@ USE: namespaces
     "/library/inference/branches.factor"\r
     "/library/inference/words.factor"\r
     "/library/inference/stack.factor"\r
+    "/library/inference/types.factor"\r
 \r
     "/library/compiler/assembler.factor"\r
     "/library/compiler/xt.factor"\r
index 89b9808bf01883181b632d5535e048c070f0f826..4e4328594579c5c3db417922b2b310df654485d7 100644 (file)
@@ -54,7 +54,7 @@ BUILTIN: dll   15
 BUILTIN: alien 16
 
 M: alien hashcode ( obj -- n )
-    alien-address ;
+    alien-address >fixnum ;
 
 M: alien = ( obj obj -- ? )
     over alien? [
index 5c4253d1b433c54267f0520edbc9d5fb06dc4cbd..c74a973a6f074f979e8c72ad00285037a45e197f 100644 (file)
@@ -121,6 +121,10 @@ USE: math
     #! MOV INDIRECT <reg> TO <reg>.
     HEX: 8b compile-byte  0 MOD-R/M ;
 
+: D[R]>R ( disp reg reg -- )
+    #! MOV INDIRECT DISPLACED <reg> TO <reg>.
+    HEX: 8b compile-byte  1 MOD-R/M  compile-byte ;
+
 : R>[R] ( reg reg -- )
     #! MOV <reg> TO INDIRECT <reg>.
     HEX: 89 compile-byte  swap 0 MOD-R/M ;
index 06cb3f1f4a0733a4c71e6e8814bbfb28fd557126..22712c37089c4475679d6cc0fb9f3d1da5dde8af 100644 (file)
@@ -82,7 +82,9 @@ USE: math
 
 #slot [
     PEEK-DS
-    
+    2unlist type-tag >r cell * r> - EAX EAX D[R]>R
+    DS ECX [I]>R  absolute-ds
+    EAX ECX R>[R]
 ] "generator" set-word-property
 
 #call [
index 75164c7031ea627bb7bd08e0a3864fe33c963fc6..72a7bd5b2adc6a8e5f16b244302c04ec6b550462 100644 (file)
@@ -105,3 +105,7 @@ SYMBOL: previous-offset
     ] catch ;
 
 #label [ save-xt ] "generator" set-word-property
+
+: type-tag ( type -- tag )
+    #! Given a type number, return the tag number.
+    dup 6 > [ drop 3 ] when ;
index ed57fda472f696ed6ecc0e9cf75dab19c3839b45..0dc345b5f27aa840b06cff1b6587fae0a056b168 100644 (file)
@@ -168,13 +168,10 @@ SYMBOL: classes
 SYMBOL: object
 
 : type-union ( list list -- list )
-    append prune [ > ] sort ;
-
-: type-intersection ( list list -- list )
-    intersection [ > ] sort ;
+    append prune ;
 
 : lookup-union ( typelist -- class )
-    classes get hash [ object ] unless* ;
+    [ > ] sort classes get hash [ object ] unless* ;
 
 : class-or ( class class -- class )
     #! Return a class that both classes are subclasses of.
@@ -182,12 +179,19 @@ SYMBOL: object
     swap builtin-supertypes
     type-union lookup-union ;
 
+: class-or-list ( list -- class )
+    #! Return a class that every class in the list is a
+    #! subclass of.
+    [
+        [ builtin-supertypes [ unique, ] each ] each
+    ] make-list lookup-union ;
+
 : class-and ( class class -- class )
     #! Return a class that is a subclass of both, or raise an
     #! error if this is impossible.
     over builtin-supertypes
     over builtin-supertypes
-    type-intersection dup [
+    intersection dup [
         nip nip lookup-union
     ] [
         drop [
@@ -196,8 +200,18 @@ SYMBOL: object
         ] make-string throw
     ] ifte ;
 
+: define-promise ( class -- )
+    #! A promise is a word that has no effect during
+    #! interpretation, but instructs the compiler that the value
+    #! at the top of the stack is statically-known to be of the
+    #! given type. Promises should only be used by kernel code.
+    dup word-name "%" swap cat2 "in" get create
+    dup [ ] define-compound
+    swap "promise" set-word-property ;
+
 : define-class ( class metaclass -- )
     dupd "metaclass" set-word-property
+    dup define-promise
     dup builtin-supertypes [ > ] sort
     classes get set-hash ;
 
index 4137bc7c1d74ecb7d18e87face5b25db46b2e466..e6426b6cac91804d4a7456fc839ae1bb90fb0c70 100644 (file)
@@ -90,3 +90,6 @@ predicate [
 
 PREDICATE: compound generic ( word -- ? )
     "combination" word-property ;
+
+PREDICATE: compound promise ( obj -- ? )
+    "promise" word-property ;
index 87efa1eebfc97a58f5ee3ac5dcac9f681252a108..c584344102b112378de0d11240581297aa4f3285 100644 (file)
@@ -39,42 +39,41 @@ USE: words
 USE: hashtables
 USE: prettyprint
 
-: vector-length< ( vec1 vec2 -- ? )
-    swap vector-length swap vector-length < ;
-
-: unify-length ( vec1 vec2 -- vec1 )
-    2dup vector-length< [ swap ] unless [
-        vector-length over vector-length -
-        empty-vector [ swap vector-append ] keep
-    ] keep ;
-
-: unify-classes ( value value -- class )
-    #! If one of the values is f, it was added as a result of
-    #! length unification so we just replace it with a computed
-    #! object value.
-    2dup and [
-        value-class swap value-class class-or
+: longest-vector ( list -- length )
+    [ vector-length ] map [ > ] top ;
+
+: computed-value-vector ( n -- vector )
+    [ drop object <computed> ] vector-project ;
+
+: add-inputs ( count stack -- count stack )
+    #! Add this many inputs to the given stack.
+    [ vector-length - dup ] keep
+    >r computed-value-vector dup r> vector-append ;
+
+: unify-lengths ( list -- list )
+    #! Pad all vectors to the same length. If one vector is
+    #! shorter, pad it with unknown results at the bottom.
+    dup longest-vector swap [ dupd add-inputs nip ] map nip ;
+
+: unify-results ( list -- value )
+    #! If all values in list are equal, return the value.
+    #! Otherwise, unify types.
+    dup all=? [
+        car
     ] [
-        2drop object
+        [ value-class ] map class-or-list <computed>
     ] ifte ;
 
-: unify-results ( value value -- value )
-    #! Replace values with unknown result if they differ,
-    #! otherwise retain them.
-    2dup = [
-        drop
-    ] [
-        unify-classes <computed>
-    ] ifte ;
+: vector-transpose ( list -- vector )
+    #! Turn a list of same-length vectors into a vector of lists.
+    dup car vector-length [
+        over [ dupd vector-nth ] map nip
+    ] vector-project nip ;
 
 : unify-stacks ( list -- stack )
     #! Replace differing literals in stacks with unknown
     #! results.
-    uncons [
-        unify-length vector-zip [
-            uncons unify-results
-        ] vector-map
-    ] each ;
+    unify-lengths vector-transpose [ unify-results ] vector-map ;
 
 : balanced? ( list -- ? )
     #! Check if a list of [ instack | outstack ] pairs is
@@ -139,9 +138,16 @@ SYMBOL: cloned
         meta-d off meta-r off d-in off
     ] when ;
 
+: propagate-type ( [ value | class ] -- )
+    #! Type propagation is chained.
+    [
+        unswons 2dup set-value-class
+        [ type-propagations get ] bind assoc propagate-type
+    ] when* ;
+
 : infer-branch ( value -- namespace )
     <namespace> [
-        uncons [ unswons set-value-class ] when*
+        uncons propagate-type
         dup value-recursion recursive-state set
         copy-inference
         literal-value dup infer-quot
@@ -234,9 +240,8 @@ SYMBOL: cloned
     #! Infer effects for all branches, unify.
     [ object vector ] ensure-d
     dataflow-drop, pop-d vtable>list
-    [ f cons ] map
     >r 1 meta-d get vector-tail* #dispatch r>
-    pop-d drop ( n )
+    pop-d ( n ) num-types [ dupd cons ] project nip zip
     infer-branches ;
 
 USE: kernel-internals
index 162005fbe89dfa2f8adafeaab1ad4cf3b87da607..4d66760ebeb33b465c341fe9136e458c85b2567f 100644 (file)
@@ -56,18 +56,24 @@ SYMBOL: d-in
 ! Recursive state. An alist, mapping words to labels.
 SYMBOL: recursive-state
 
-! A value has the following slots:
 GENERIC: literal-value ( value -- obj )
 GENERIC: value= ( literal value -- ? )
 GENERIC: value-class ( value -- class )
 GENERIC: value-class-and ( class value -- )
 GENERIC: set-value-class ( class value -- )
 
+! A value has the following slots in addition to those relating
+! to generics above:
+
+! An association list mapping values to [ value | class ] pairs
+SYMBOL: type-propagations
+
 TRAITS: computed
 C: computed ( class -- value )
     [
         \ value-class set
         gensym \ literal-value set
+        type-propagations off
     ] extend ;
 M: computed literal-value ( value -- obj )
     "Cannot use a computed value literally." throw ;
@@ -82,7 +88,11 @@ M: computed set-value-class ( class value -- )
 
 TRAITS: literal
 C: literal ( obj rstate -- value )
-    [ recursive-state set \ literal-value set ] extend ;
+    [
+        recursive-state set
+        \ literal-value set
+        type-propagations off
+    ] extend ;
 M: literal literal-value ( value -- obj )
     [ \ literal-value get ] bind ;
 M: literal value= ( literal value -- ? )
index fefe23651f90e35cbe983ed6061af1eebbe48e26..ea8557f604ad9e5b8ea381b3837ea240bb7fd1cb 100644 (file)
@@ -38,15 +38,14 @@ USE: strings
 USE: vectors
 USE: words
 USE: stdio
+USE: prettyprint
 
 ! Enhanced inference of primitives relating to data types.
 ! Optimizes type checks and slot access.
 
 : infer-check ( assert class -- )
     peek-d dup value-class pick = [
-        [
-            "Optimized out " , rot word-name , " check." ,
-        ] make-string print 2drop
+        3drop
     ] [
         value-class-and
         dup "infer-effect" word-property consume/produce
@@ -65,6 +64,7 @@ USE: stdio
 ] "infer" set-word-property
 
 \ slot [
+    [ object fixnum ] ensure-d
     dataflow-drop, pop-d literal-value
     peek-d value-class builtin-supertypes dup length 1 = [
         cons #slot dataflow, [
@@ -77,3 +77,26 @@ USE: stdio
         "slot called without static type knowledge" throw
     ] ifte
 ] "infer" set-word-property
+
+: type-value-map ( value -- )
+    [
+        num-types [
+            dup builtin-type dup [
+                pick swons cons ,
+            ] [
+                2drop
+            ] ifte
+        ] times*
+    ] make-list nip ;
+
+\ type [
+    [ object ] ensure-d
+    \ type #call dataflow, [
+        peek-d type-value-map >r
+        1 0 node-inputs
+        [ object ] consume-d
+        [ fixnum ] produce-d
+        r> peek-d [ type-propagations set ] bind
+        1 0 node-outputs
+    ] bind
+] "infer" set-word-property
index 6a82eb5756ba20eca4fce947804648068cb84eaf..5f002a098f6a7467693e4983224065f12145fefe 100644 (file)
@@ -112,6 +112,9 @@ M: compound (apply-word) ( word -- )
         infer-compound
     ] ifte ;
 
+M: promise (apply-word) ( word -- )
+    "promise" word-property unit ensure-d ;
+
 M: symbol (apply-word) ( word -- )
     apply-literal ;
 
@@ -125,7 +128,7 @@ M: symbol (apply-word) ( word -- )
     #! diverging recursion. Note that this check is not done for
     #! mutually-recursive words. Generally they should be
     #! avoided.
-    recursive-state get car = [
+    current-word = [
         d-in get vector-length
         meta-d get vector-length > [
             current-word word-name " diverges." cat2 throw
@@ -183,6 +186,8 @@ M: symbol (apply-word) ( word -- )
 
 \ call [ infer-call ] "infer" set-word-property
 
+\ * [ [ number number ] [ number ] ] "infer-effect" set-word-property
+
 \ undefined-method t "terminator" set-word-property
 \ not-a-number t "terminator" set-word-property
 \ throw t "terminator" set-word-property
index 8785ff03aab192ad20bfa6baa205f4536aba59a3..516a671cfd1392ffdc6dfdb3f5a17e45383c4041 100644 (file)
@@ -31,6 +31,8 @@ USE: kernel
 USE: vectors
 
 : dispatch ( n vtable -- )
+    #! This word is unsafe in compiled code since n is not
+    #! bounds-checked. Do not call it directly.
     vector-nth call ;
 
 IN: kernel
index 21fe06539e89ecb9cc7f8b2154138f3657b1b141..5caf6b925484616cb5475b5e8a485cf4fa24c30d 100644 (file)
@@ -37,11 +37,11 @@ USE: math-internals
 
 GENERIC: real ( #{ re im } -- re )
 M: real real ;
-M: complex real 0 slot ;
+M: complex real 0 slot %real ;
 
 GENERIC: imaginary ( #{ re im } -- im )
 M: real imaginary drop 0 ;
-M: complex imaginary 1 slot ;
+M: complex imaginary 1 slot %real ;
 
 : rect> ( xr xi -- x )
     over real? over real? and [
index 2ab1ebd2248ced05ea16fc0d496941693ab7990d..3ba3151547ee46d782bba5fe75b7c9c5fc12b682 100644 (file)
@@ -34,11 +34,11 @@ USE: math-internals
 
 GENERIC: numerator ( a/b -- a )
 M: integer numerator ;
-M: ratio numerator 0 slot ;
+M: ratio numerator 0 slot %integer ;
 
 GENERIC: denominator ( a/b -- b )
 M: integer denominator drop 1 ;
-M: ratio denominator 1 slot ;
+M: ratio denominator 1 slot %integer ;
 
 IN: math-internals
 
index 3a66b98189497f23cf41650fe18509a495d05421..ad52311f9beed7795b35bc2433498115549c87c5 100644 (file)
@@ -72,7 +72,7 @@ USE: words
     [ sbuf-reverse           " sbuf -- "                          [ [ sbuf ] [ ] ] ]
     [ sbuf-clone             " sbuf -- sbuf "                     [ [ sbuf ] [ sbuf ] ] ]
     [ sbuf=                  " sbuf sbuf -- ? "                   [ [ sbuf sbuf ] [ boolean ] ] ]
-    [ sbuf-hashcode          " sbuf -- n "                        [ [ sbuf ] [ integer ] ] ]
+    [ sbuf-hashcode          " sbuf -- n "                        [ [ sbuf ] [ fixnum ] ] ]
     [ arithmetic-type        " n n -- type "                      [ [ number number ] [ number number fixnum ] ] ]
     [ >fixnum                " n -- fixnum "                      [ [ number ] [ fixnum ] ] ]
     [ >bignum                " n -- bignum "                      [ [ number ] [ bignum ] ] ]
index 27cf3b94693951afdc3b00c4dcf7b2ca2569cc7a..42e82b7ee4f670015077c0a373aae01ff628db18 100644 (file)
@@ -34,7 +34,7 @@ USE: math
 
 ! Define methods bound to primitives
 BUILTIN: string 12
-M: string hashcode 2 slot ;
+M: string hashcode 2 slot %fixnum ;
 M: string = str= ;
 
 : str-length ( str -- len ) >string 1 integer-slot ; inline
index 1de418a356e2b08c5a0b29ec30199ece63f8b987..07afb2df1edcb6e6c2772bbd44af455c5772030c 100644 (file)
@@ -36,9 +36,9 @@ USE: generic
 : inline-test
     car car ; inline
 
-[ t ] [
-    \ slot [ inline-test ] dataflow dataflow-contains-param? >boolean
-] unit-test
+[ t ] [
+    \ slot [ inline-test ] dataflow dataflow-contains-param? >boolean
+] unit-test
 
 [ t ] [
     #ifte [ [ drop ] [ + ] ifte ] dataflow dataflow-contains-op? >boolean
index fa519f7075224d12b741d4e9cfb8717d7f3a56a1..bd4534aca8af95d4fda2875da455545afcb364e1 100644 (file)
@@ -20,41 +20,18 @@ unit-test
     [ [ vector ] [ cons vector cons integer object cons ] ]
     [ [ vector ] [ cons vector cons ] ]
     decompose
-]
+] unit-test
 
 [ [ [ object ] [ object ] ] ]
 [
     [ [ object number ] [ object ] ]
     [ [ object number ] [ object ] ]
     decompose
-]
+] unit-test
 
 : old-effect ( [ in-types out-types ] -- [ in | out ] )
     uncons car length >r length r> cons ;
 
-[
-    [ 1 | 2 ]
-    [ 2 | 1 ]
-    [ 0 | 3 ]
-    [ 4 | 2 ]
-    [ 3 | 3 ]
-    [ 0 | 0 ]
-    [ 1 | 5 ]
-    [ 3 | 4 ]
-] "effects" set
-
-[ { f 1 2 } { 1 2 3 } ] [
-    { 1 2 } { 1 2 3 } unify-length
-] unit-test
-
-[ [ sq ] ] [
-    [ sq ] f <literal> [ sq ] f <literal> unify-results literal-value
-] unit-test
-
-[ fixnum ] [
-    5 f <literal> 6 f <literal> unify-results value-class
-] unit-test
-
 [ [ 0 | 2 ] ] [ [ 2 "Hello" ] infer old-effect ] unit-test
 [ [ 1 | 2 ] ] [ [ dup ] infer old-effect ] unit-test
 
@@ -109,10 +86,10 @@ unit-test
 
 [ [ 1 | 1 ] ] [ [ simple-recursion-2 ] infer old-effect ] unit-test
 
-: bad-recursion-1
-    dup [ drop bad-recursion-1 5 ] [ ] ifte ;
-
-[ [ bad-recursion-1 ] infer old-effect ] unit-test-fails
+: bad-recursion-1
+    dup [ drop bad-recursion-1 5 ] [ ] ifte ;
+! 
+[ [ bad-recursion-1 ] infer old-effect ] unit-test-fails
 
 : bad-recursion-2
     dup [ uncons bad-recursion-2 ] [ ] ifte ;
@@ -236,11 +213,12 @@ SYMBOL: sym-test
 
 ! Type inference
 
-[ [ [ object ] [ ] ] ] [ [ drop ] infer ] unit-test
-[ [ [ object ] [ object object ] ] ] [ [ dup ] infer ] unit-test
-[ [ [ object object ] [ cons ] ] ] [ [ cons ] infer ] unit-test
-[ [ [ cons ] [ cons ] ] ] [ [ uncons cons ] infer ] unit-test
-! [ [ [ object ] [ object ] ] ] [ [ dup [ car ] when ] infer ] unit-test
-[ [ [ vector ] [ vector ] ] ] [ [ vector-clone ] infer ] unit-test
+[ [ [ object ] [ ] ] ] [ [ drop ] infer ] unit-test
+[ [ [ object ] [ object object ] ] ] [ [ dup ] infer ] unit-test
+[ [ [ object object ] [ cons ] ] ] [ [ cons ] infer ] unit-test
+[ [ [ cons ] [ cons ] ] ] [ [ uncons cons ] infer ] unit-test
+[ [ [ general-list ] [ object ] ] ] [ [ dup [ car ] when ] infer ] unit-test
+[ [ [ vector ] [ vector ] ] ] [ [ vector-clone ] infer ] unit-test
 ! [ [ [ number ] [ number ] ] ] [ [ dup + ] infer ] unit-test
 ! [ [ [ number number number ] [ number ] ] ] [ [ digit+ ] infer ] unit-test
+[ [ [ number ] [ real real ] ] ] [ [ >rect ] infer ] unit-test
index 35c2d61dcbad1988971fdcf1df92044d9b28df81..3500233bc3e1f5959a9ab6d5a4734e0c4240ac68 100644 (file)
@@ -37,7 +37,7 @@ USE: strings
 
 BUILTIN: word 1
 
-M: word hashcode 1 slot ;
+M: word hashcode 1 slot %fixnum ;
 
 : word-xt     ( w -- xt ) >word 2 integer-slot ; inline
 : set-word-xt ( xt w -- ) >word 2 set-integer-slot ; inline
@@ -84,7 +84,11 @@ PREDICATE: word undefined ( obj -- ? ) word-primitive 0 = ;
 : intern-symbol ( word -- )
     dup undefined? [ define-symbol ] [ drop ] ifte ;
 
-: word-name       ( word -- str ) "name" word-property ;
+#! The type declaration is for the benefit of stack effect
+#! inference.
+: word-name ( word -- str )
+    "name" word-property >string ;
+
 : word-vocabulary ( word -- str ) "vocabulary" word-property ;
 : stack-effect    ( word -- str ) "stack-effect" word-property ;
 : documentation   ( word -- str ) "documentation" word-property ;