1 ! Copyright (C) 2008, 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors assocs namespaces sequences kernel math
4 combinators sets disjoint-sets fry stack-checker.values ;
5 FROM: namespaces => set ;
6 IN: compiler.tree.escape-analysis.allocations
8 ! A map from values to classes. Only for #introduce outputs
11 : value-class ( value -- class ) value-classes get at ;
13 : set-value-class ( class value -- ) value-classes get set-at ;
15 ! A map from values to one of the following:
16 ! - f -- initial status, assigned to values we have not seen yet;
17 ! may potentially become an allocation later
18 ! - a sequence of values -- potentially unboxed tuple allocations
19 ! - t -- not allocated in this procedure, can never be unboxed
22 : (allocation) ( value -- value' allocations )
23 allocations get ; inline
25 : allocation ( value -- allocation )
28 : record-allocation ( allocation value -- )
31 : record-allocations ( allocations values -- )
32 [ record-allocation ] 2each ;
34 ! We track slot access to connect constructor inputs with
38 TUPLE: slot-access slot# value ;
40 C: <slot-access> slot-access
42 : record-slot-access ( out slot# in -- )
43 <slot-access> swap slot-accesses get set-at ;
45 ! We track escaping values with a disjoint set.
46 SYMBOL: escaping-values
50 : <escaping-values> ( -- disjoint-set )
51 <disjoint-set> +escaping+ over add-atom ;
53 : init-escaping-values ( -- )
54 <escaping-values> escaping-values set ;
56 : introduce-value ( values -- )
58 2dup disjoint-set-member?
59 [ 2drop ] [ add-atom ] if ;
61 : introduce-values ( values -- )
62 [ introduce-value ] each ;
64 : <slot-value> ( -- value )
65 <value> dup introduce-value ;
67 : merge-values ( in-values out-value -- )
68 escaping-values get equate-all-with ;
70 : merge-slots ( values -- value )
71 <slot-value> [ merge-values ] keep ;
73 : equate-values ( value1 value2 -- )
74 escaping-values get equate ;
76 : add-escaping-value ( value -- )
79 { [ dup not ] [ drop ] }
80 { [ dup t eq? ] [ drop ] }
81 [ [ add-escaping-value ] each ]
84 [ +escaping+ equate-values ] bi ;
86 : add-escaping-values ( values -- )
87 [ add-escaping-value ] each ;
89 : unknown-allocation ( value -- )
90 [ add-escaping-value ]
91 [ t swap record-allocation ]
94 : unknown-allocations ( values -- )
95 [ unknown-allocation ] each ;
97 : escaping-value? ( value -- ? )
98 +escaping+ escaping-values get equiv? ;
102 : copy-allocation ( allocation -- allocation' )
105 { [ dup t eq? ] [ ] }
106 [ [ <value> [ introduce-value ] [ copy-value ] [ ] tri ] map ]
109 : copy-value ( from to -- )
111 [ [ allocation copy-allocation ] dip record-allocation ]
114 : copy-values ( from to -- )
115 [ copy-value ] 2each ;
117 : copy-slot-value ( out slot# in -- )
119 { [ dup not ] [ 3drop ] }
120 { [ dup t eq? ] [ 3drop ] }
121 [ nth swap copy-value ]
124 ! Compute which tuples escape
125 SYMBOL: escaping-allocations
127 : compute-escaping-allocations ( -- )
129 [ drop escaping-value? ] assoc-filter
130 escaping-allocations set ;
132 : escaping-allocation? ( value -- ? )
133 escaping-allocations get key? ;
135 : unboxed-allocation ( value -- allocation/f )
136 dup escaping-allocation? [ drop f ] [ allocation ] if ;
138 : unboxed-slot-access? ( value -- ? )
139 slot-accesses get at*
140 [ value>> unboxed-allocation >boolean ] when ;