1 ! Copyright (C) 2008, 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays assocs classes.tuple.private combinators
4 compiler.tree compiler.tree.builder compiler.tree.combinators
5 compiler.tree.escape-analysis.allocations
6 compiler.tree.escape-analysis.simple compiler.tree.propagation
7 compiler.utilities fry kernel kernel.private math namespaces
8 sequences slots.private stack-checker.branches
9 stack-checker.values vectors ;
10 IN: compiler.tree.tuple-unboxing
12 GENERIC: unbox-tuples* ( node -- node/nodes )
14 : unbox-output? ( node -- values )
15 out-d>> first unboxed-allocation ;
17 : (expand-#push) ( object value -- nodes )
18 dup unboxed-allocation dup [
19 [ object-slots ] [ drop ] [ ] tri*
20 [ (expand-#push) ] 2map-flat
25 : expand-#push ( #push -- nodes )
26 [ literal>> ] [ out-d>> first ] bi (expand-#push) ;
28 M: #push unbox-tuples* ( #push -- nodes )
29 dup unbox-output? [ expand-#push ] when ;
31 : unbox-<tuple-boa> ( #call -- nodes )
32 dup unbox-output? [ in-d>> 1 tail* <#drop> ] when ;
34 : (flatten-values) ( values accum -- )
36 dup unboxed-allocation
37 [ _ (flatten-values) ] [ _ push ] ?if
40 : flatten-values ( values -- values' )
42 10 <vector> [ (flatten-values) ] keep
45 : prepare-slot-access ( #call -- tuple-values outputs slot-values )
46 [ in-d>> flatten-values ]
47 [ out-d>> flatten-values ]
49 out-d>> first slot-accesses get at
50 [ slot#>> ] [ value>> ] bi allocation nth
54 : slot-access-shuffle ( tuple-values outputs slot-values -- #shuffle )
55 [ drop ] [ zip ] 2bi <#data-shuffle> ;
57 : unbox-slot-access ( #call -- nodes )
58 dup out-d>> first unboxed-slot-access? [
59 prepare-slot-access slot-access-shuffle
62 M: #call unbox-tuples*
64 { \ <tuple-boa> [ unbox-<tuple-boa> ] }
65 { \ slot [ unbox-slot-access ] }
69 M: #declare unbox-tuples*
70 ! We don't look at declarations after escape analysis anyway.
73 M: #copy unbox-tuples*
74 [ flatten-values ] change-in-d
75 [ flatten-values ] change-out-d ;
77 M: #shuffle unbox-tuples*
78 [ flatten-values ] change-in-d
79 [ flatten-values ] change-out-d
80 [ flatten-values ] change-in-r
81 [ flatten-values ] change-out-r
82 [ unzip [ flatten-values ] bi@ zip ] change-mapping ;
84 M: #terminate unbox-tuples*
85 [ flatten-values ] change-in-d
86 [ flatten-values ] change-in-r ;
89 ! pad-with-bottom is only needed if some branches are terminated,
90 ! which means all output values are bottom
91 [ [ flatten-values ] map pad-with-bottom ] change-phi-in-d
92 [ flatten-values ] change-out-d ;
94 M: #recursive unbox-tuples*
95 [ label>> [ flatten-values ] change-enter-out drop ]
96 [ [ flatten-values ] change-in-d ]
99 M: #enter-recursive unbox-tuples*
100 [ flatten-values ] change-in-d
101 [ flatten-values ] change-out-d ;
103 M: #call-recursive unbox-tuples*
104 [ flatten-values ] change-in-d
105 [ flatten-values ] change-out-d ;
107 M: #return-recursive unbox-tuples*
108 [ flatten-values ] change-in-d
109 [ flatten-values ] change-out-d ;
111 : value-declaration ( value -- quot )
112 value-class [ 1array '[ _ declare ] ] [ [ ] ] if* ;
114 : unbox-parameter-quot ( allocation -- quot )
115 dup unboxed-allocation {
116 { [ dup not ] [ 2drop [ ] ] }
118 [ value-declaration ] [
120 [ unbox-parameter-quot ] [ 2 + '[ _ slot ] ] bi*
123 ] bi* '[ @ _ cleave ]
127 : unbox-parameters-quot ( values -- quot )
128 [ unbox-parameter-quot ] map
129 dup [ [ ] = ] all? [ drop [ ] ] [ '[ _ spread ] ] if ;
131 : unbox-parameters-nodes ( new-values old-values -- nodes )
132 [ flatten-values ] [ unbox-parameters-quot ] bi build-sub-tree ;
134 : new-and-old-values ( values -- new-values old-values )
135 [ length [ <value> ] replicate ] keep ;
137 : unbox-hairy-introduce ( #introduce -- nodes )
138 dup out-d>> new-and-old-values
139 [ drop >>out-d ] [ unbox-parameters-nodes ] 2bi
140 swap prefix propagate ;
142 M: #introduce unbox-tuples*
143 ! For every output that is unboxed, insert slot accessors
144 ! to convert the stack value into its unboxed form
145 dup out-d>> [ unboxed-allocation ] any? [
146 unbox-hairy-introduce
149 ! These nodes never participate in unboxing
150 : assert-not-unboxed ( values -- )
152 [ [ unboxed-allocation ] any? ] [ unboxed-allocation ] if
153 [ "Unboxing wrong value" throw ] when ;
155 M: #branch unbox-tuples* dup in-d>> assert-not-unboxed ;
157 M: #return unbox-tuples* dup in-d>> assert-not-unboxed ;
159 M: #alien-node unbox-tuples* dup in-d>> assert-not-unboxed ;
161 M: #alien-callback unbox-tuples* ;
163 : unbox-tuples ( nodes -- nodes )
164 (allocation) escaping-allocations get
165 [ nip key? ] curry assoc-all?
166 [ [ unbox-tuples* ] map-nodes ] unless ;