347 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Factor
		
	
	
			
		
		
	
	
			347 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Factor
		
	
	
USING: compiler.tree.escape-analysis
 | 
						|
compiler.tree.escape-analysis.allocations compiler.tree.builder
 | 
						|
compiler.tree.recursive compiler.tree.normalization
 | 
						|
math.functions compiler.tree.propagation compiler.tree.cleanup
 | 
						|
compiler.tree.combinators compiler.tree sequences math
 | 
						|
math.private kernel tools.test accessors slots.private
 | 
						|
quotations.private prettyprint classes.tuple.private classes
 | 
						|
classes.tuple namespaces
 | 
						|
compiler.tree.propagation.info stack-checker.errors
 | 
						|
compiler.tree.checker compiler.tree.def-use compiler.tree.dead-code
 | 
						|
kernel.private vectors ;
 | 
						|
IN: compiler.tree.escape-analysis.tests
 | 
						|
 | 
						|
GENERIC: count-unboxed-allocations* ( m node -- n )
 | 
						|
 | 
						|
: (count-unboxed-allocations) ( m node -- n )
 | 
						|
    out-d>> first escaping-allocation? [ 1 + ] unless ;
 | 
						|
 | 
						|
M: #call count-unboxed-allocations*
 | 
						|
    dup immutable-tuple-boa?
 | 
						|
    [ (count-unboxed-allocations) ] [ drop ] if ;
 | 
						|
 | 
						|
M: #push count-unboxed-allocations*
 | 
						|
    dup literal>> class-of immutable-tuple-class?
 | 
						|
    [ (count-unboxed-allocations) ] [ drop ] if ;
 | 
						|
 | 
						|
M: #introduce count-unboxed-allocations*
 | 
						|
    out-d>> [ escaping-allocation? [ 1 + ] unless ] each ;
 | 
						|
 | 
						|
M: node count-unboxed-allocations* drop ;
 | 
						|
 | 
						|
: count-unboxed-allocations ( quot -- sizes )
 | 
						|
    build-tree
 | 
						|
    analyze-recursive
 | 
						|
    normalize
 | 
						|
    propagate
 | 
						|
    cleanup
 | 
						|
    escape-analysis
 | 
						|
    dup check-nodes
 | 
						|
    compute-def-use
 | 
						|
    remove-dead-code
 | 
						|
    0 swap [ count-unboxed-allocations* ] each-node ;
 | 
						|
 | 
						|
[ 0 ] [ [ [ + ] curry ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
[ 1 ] [ [ [ + ] curry drop ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
[ 1 ] [ [ [ + ] curry 3 slot ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
[ 1 ] [ [ [ + ] curry 3 slot drop ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
[ 1 ] [ [ [ + ] curry uncurry ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
[ 1 ] [ [ [ + ] curry call ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
[ 1 ] [ [ [ + ] curry call ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
[ 0 ] [ [ [ [ + ] curry ] [ drop [ ] ] if ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
[ 2 ] [
 | 
						|
    [ [ [ + ] curry ] [ [ * ] curry ] if uncurry ] count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
[ 0 ] [
 | 
						|
    [ [ [ + ] curry ] [ [ * ] curry ] if ] count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
[ 3 ] [
 | 
						|
    [ [ [ + ] curry ] [ dup [ [ * ] curry ] [ [ / ] curry ] if ] if uncurry ] count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
[ 2 ] [
 | 
						|
    [ [ [ + ] curry 4 ] [ dup [ [ * ] curry ] [ [ / ] curry ] if uncurry ] if ] count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
[ 0 ] [
 | 
						|
    [ [ [ + ] curry ] [ dup [ [ * ] curry ] [ [ / ] curry ] if ] if ] count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
TUPLE: cons { car read-only } { cdr read-only } ;
 | 
						|
 | 
						|
[ 0 ] [
 | 
						|
    [
 | 
						|
        dup 0 = [
 | 
						|
            2 cons boa
 | 
						|
        ] [
 | 
						|
            dup 1 = [
 | 
						|
                3 cons boa
 | 
						|
            ] when
 | 
						|
        ] if car>>
 | 
						|
    ] count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
[ 3 ] [
 | 
						|
    [
 | 
						|
        dup 0 = [
 | 
						|
            2 cons boa
 | 
						|
        ] [
 | 
						|
            dup 1 = [
 | 
						|
                3 cons boa
 | 
						|
            ] [
 | 
						|
                4 cons boa
 | 
						|
            ] if
 | 
						|
        ] if car>>
 | 
						|
    ] count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
[ 0 ] [
 | 
						|
    [
 | 
						|
        dup 0 = [
 | 
						|
            dup 1 = [
 | 
						|
                3 cons boa
 | 
						|
            ] [
 | 
						|
                4 cons boa
 | 
						|
            ] if
 | 
						|
        ] unless car>>
 | 
						|
    ] count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
[ 2 ] [
 | 
						|
    [
 | 
						|
        dup 0 = [
 | 
						|
            2 cons boa
 | 
						|
        ] [
 | 
						|
            dup 1 = [
 | 
						|
                3 cons boa
 | 
						|
            ] [
 | 
						|
                4 cons boa
 | 
						|
            ] if car>>
 | 
						|
        ] if
 | 
						|
    ] count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
[ 0 ] [
 | 
						|
    [
 | 
						|
        dup 0 = [
 | 
						|
            2 cons boa
 | 
						|
        ] [
 | 
						|
            dup 1 = [
 | 
						|
                3 cons boa dup .
 | 
						|
            ] [
 | 
						|
                4 cons boa
 | 
						|
            ] if
 | 
						|
        ] if drop
 | 
						|
    ] count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
[ 2 ] [
 | 
						|
    [
 | 
						|
        [ dup cons boa ] [ drop 1 2 cons boa ] if car>>
 | 
						|
    ] count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
[ 2 ] [
 | 
						|
    [
 | 
						|
        3dup
 | 
						|
        [ cons boa ] [ cons boa 3 cons boa ] if
 | 
						|
        [ car>> ] [ cdr>> ] bi
 | 
						|
    ] count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
[ 2 ] [
 | 
						|
    [
 | 
						|
        3dup [ cons boa ] [ cons boa . 1 2 cons boa ] if
 | 
						|
        [ car>> ] [ cdr>> ] bi
 | 
						|
    ] count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
[ 1 ] [
 | 
						|
    [ [ 3 cons boa ] [ "A" throw ] if car>> ]
 | 
						|
    count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
[ 0 ] [
 | 
						|
    [ 10 [ drop ] each-integer ] count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
[ 0 ] [
 | 
						|
    [
 | 
						|
        1 2 cons boa 10 [ drop 2 cons boa ] each-integer car>>
 | 
						|
    ] count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
: infinite-cons-loop ( a -- b ) 2 cons boa infinite-cons-loop ; inline recursive
 | 
						|
 | 
						|
[ 0 ] [
 | 
						|
    [
 | 
						|
        1 2 cons boa infinite-cons-loop
 | 
						|
    ] count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
TUPLE: rw-box i ;
 | 
						|
 | 
						|
C: <rw-box> rw-box
 | 
						|
 | 
						|
[ 0 ] [ [ <rw-box> i>> ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
: fake-fib ( m -- n )
 | 
						|
    dup i>> 1 <= [ drop 1 <rw-box> ] when ; inline recursive
 | 
						|
 | 
						|
[ 0 ] [ [ <rw-box> fake-fib i>> ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
TUPLE: ro-box { i read-only } ;
 | 
						|
 | 
						|
C: <ro-box> ro-box
 | 
						|
 | 
						|
: tuple-fib ( m -- n )
 | 
						|
    dup i>> 1 <= [
 | 
						|
        drop 1 <ro-box>
 | 
						|
    ] [
 | 
						|
        i>> 1 - <ro-box>
 | 
						|
        dup tuple-fib
 | 
						|
        swap
 | 
						|
        i>> 1 - <ro-box>
 | 
						|
        tuple-fib
 | 
						|
        swap i>> swap i>> + <ro-box>
 | 
						|
    ] if ; inline recursive
 | 
						|
 | 
						|
[ 5 ] [ [ <ro-box> tuple-fib i>> ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
[ 3 ] [ [ <ro-box> tuple-fib ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
: tuple-fib' ( m -- n )
 | 
						|
    dup 1 <= [ 1 - tuple-fib' i>> ] when <ro-box> ; inline recursive
 | 
						|
 | 
						|
[ 0 ] [ [ tuple-fib' ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
: bad-tuple-fib-1 ( m -- n )
 | 
						|
    dup i>> 1 <= [
 | 
						|
        drop 1 <ro-box>
 | 
						|
    ] [
 | 
						|
        i>> 1 - <ro-box>
 | 
						|
        dup bad-tuple-fib-1
 | 
						|
        swap
 | 
						|
        i>> 1 - <ro-box>
 | 
						|
        bad-tuple-fib-1 dup .
 | 
						|
        swap i>> swap i>> + <ro-box>
 | 
						|
    ] if ; inline recursive
 | 
						|
 | 
						|
[ 3 ] [ [ <ro-box> bad-tuple-fib-1 i>> ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
: bad-tuple-fib-2 ( m -- n )
 | 
						|
    dup .
 | 
						|
    dup i>> 1 <= [
 | 
						|
        drop 1 <ro-box>
 | 
						|
    ] [
 | 
						|
        i>> 1 - <ro-box>
 | 
						|
        dup bad-tuple-fib-2
 | 
						|
        swap
 | 
						|
        i>> 1 - <ro-box>
 | 
						|
        bad-tuple-fib-2
 | 
						|
        swap i>> swap i>> + <ro-box>
 | 
						|
    ] if ; inline recursive
 | 
						|
 | 
						|
[ 2 ] [ [ <ro-box> bad-tuple-fib-2 i>> ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
: tuple-fib-2 ( m -- n )
 | 
						|
    dup 1 <= [
 | 
						|
        drop 1 <ro-box>
 | 
						|
    ] [
 | 
						|
        1 - dup tuple-fib-2
 | 
						|
        swap
 | 
						|
        1 - tuple-fib-2
 | 
						|
        swap i>> swap i>> + <ro-box>
 | 
						|
    ] if ; inline recursive
 | 
						|
 | 
						|
[ 2 ] [ [ tuple-fib-2 i>> ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
: tuple-fib-3 ( m -- n )
 | 
						|
    dup 1 <= [
 | 
						|
        drop 1 <ro-box>
 | 
						|
    ] [
 | 
						|
        1 - dup tuple-fib-3
 | 
						|
        swap
 | 
						|
        1 - tuple-fib-3 dup .
 | 
						|
        swap i>> swap i>> + <ro-box>
 | 
						|
    ] if ; inline recursive
 | 
						|
 | 
						|
[ 0 ] [ [ tuple-fib-3 i>> ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
: bad-tuple-fib-3 ( m -- n )
 | 
						|
    dup 1 <= [
 | 
						|
        drop 1 <ro-box>
 | 
						|
    ] [
 | 
						|
        1 - dup bad-tuple-fib-3
 | 
						|
        swap
 | 
						|
        1 - bad-tuple-fib-3
 | 
						|
        2drop f
 | 
						|
    ] if ; inline recursive
 | 
						|
 | 
						|
[ 0 ] [ [ bad-tuple-fib-3 i>> ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
[ 1 ] [ [ complex boa >rect ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
[ 0 ] [ [ 1 cons boa 2 cons boa ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
[ 1 ] [ [ 1 cons boa 2 cons boa car>> ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
[ 0 ] [ [ 1 cons boa 2 cons boa dup . car>> ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
[ 0 ] [ [ 1 cons boa "x" get slot ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
[ 0 ] [
 | 
						|
    [ dup -1 over >= [ 0 >= [ "A" throw ] unless ] [ drop ] if ]
 | 
						|
    count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
[ 0 ] [
 | 
						|
    [ \ too-many->r boa f f \ inference-error boa ]
 | 
						|
    count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
! Doug found a regression
 | 
						|
 | 
						|
TUPLE: empty-tuple ;
 | 
						|
 | 
						|
[ ] [ [ empty-tuple boa layout-of ] count-unboxed-allocations drop ] unit-test
 | 
						|
 | 
						|
! New feature!
 | 
						|
 | 
						|
[ 1 ] [ [ { complex } declare real>> ] count-unboxed-allocations ] unit-test
 | 
						|
 | 
						|
[ 1 ] [
 | 
						|
    [ { complex } declare [ real>> ] [ imaginary>> ] bi ]
 | 
						|
    count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
[ 0 ] [
 | 
						|
    [ { vector } declare length>> ]
 | 
						|
    count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
! Bug found while tweaking benchmark.raytracer-simd
 | 
						|
 | 
						|
TUPLE: point-2d { x read-only } { y read-only } ;
 | 
						|
TUPLE: point-3d < point-2d { z read-only } ;
 | 
						|
 | 
						|
[ 0 ] [
 | 
						|
    [ { point-2d } declare dup point-3d? [ z>> ] [ x>> ] if ]
 | 
						|
    count-unboxed-allocations
 | 
						|
] unit-test
 | 
						|
 | 
						|
[ 0 ] [
 | 
						|
    [ point-2d boa dup point-3d? [ z>> ] [ x>> ] if ]
 | 
						|
    count-unboxed-allocations
 | 
						|
] unit-test
 |