@@ -22,6 +22,7 @@ use core::cast;
2222use core:: io;
2323use core:: uint;
2424use core:: vec;
25+ use core:: hashmap:: HashMap ;
2526use syntax:: ast;
2627use syntax:: ast_util;
2728use syntax:: ast_util:: id_range;
@@ -37,16 +38,16 @@ pub struct DataFlowContext<O> {
3738 /// the data flow operator
3839 priv oper : O ,
3940
40- /// range of ids that appear within the item in question
41- priv id_range : id_range ,
42-
4341 /// number of bits to propagate per id
4442 priv bits_per_id : uint ,
4543
4644 /// number of words we will use to store bits_per_id.
4745 /// equal to bits_per_id/uint::bits rounded up.
4846 priv words_per_id : uint ,
4947
48+ // mapping from node to bitset index.
49+ priv nodeid_to_bitset : HashMap < ast:: node_id , uint > ,
50+
5051 // Bit sets per id. The following three fields (`gens`, `kills`,
5152 // and `on_entry`) all have the same structure. For each id in
5253 // `id_range`, there is a range of words equal to `words_per_id`.
@@ -108,19 +109,17 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
108109 debug ! ( "DataFlowContext::new(id_range=%?, bits_per_id=%?, words_per_id=%?)" ,
109110 id_range, bits_per_id, words_per_id) ;
110111
111- let len = ( id_range. max - id_range. min ) as uint * words_per_id;
112- let gens = vec:: from_elem ( len, 0 ) ;
113- let kills = vec:: from_elem ( len, 0 ) ;
114- let elem = if oper. initial_value ( ) { uint:: max_value} else { 0 } ;
115- let on_entry = vec:: from_elem ( len, elem) ;
112+ let gens = ~[ ] ;
113+ let kills = ~[ ] ;
114+ let on_entry = ~[ ] ;
116115
117116 DataFlowContext {
118117 tcx : tcx,
119118 method_map : method_map,
120119 words_per_id : words_per_id,
120+ nodeid_to_bitset : HashMap :: new ( ) ,
121121 bits_per_id : bits_per_id,
122122 oper : oper,
123- id_range : id_range,
124123 gens : gens,
125124 kills : kills,
126125 on_entry : on_entry
@@ -149,7 +148,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
149148 }
150149 }
151150
152- fn apply_gen_kill ( & self , id : ast:: node_id , bits : & mut [ uint ] ) {
151+ fn apply_gen_kill ( & mut self , id : ast:: node_id , bits : & mut [ uint ] ) {
153152 //! Applies the gen and kill sets for `id` to `bits`
154153
155154 debug ! ( "apply_gen_kill(id=%?, bits=%s) [before]" ,
@@ -164,7 +163,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
164163 id, mut_bits_to_str( bits) ) ;
165164 }
166165
167- fn apply_kill ( & self , id : ast:: node_id , bits : & mut [ uint ] ) {
166+ fn apply_kill ( & mut self , id : ast:: node_id , bits : & mut [ uint ] ) {
168167 debug ! ( "apply_kill(id=%?, bits=%s) [before]" ,
169168 id, mut_bits_to_str( bits) ) ;
170169 let ( start, end) = self . compute_id_range ( id) ;
@@ -174,18 +173,56 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
174173 id, mut_bits_to_str( bits) ) ;
175174 }
176175
177- fn compute_id_range ( & self , absolute_id : ast:: node_id ) -> ( uint , uint ) {
178- assert ! ( absolute_id >= self . id_range. min) ;
179- assert ! ( absolute_id < self . id_range. max) ;
176+ fn compute_id_range_frozen ( & self , id : ast:: node_id ) -> ( uint , uint ) {
177+ let n = * self . nodeid_to_bitset . get ( & id) ;
178+ let start = n * self . words_per_id ;
179+ let end = start + self . words_per_id ;
180+ ( start, end)
181+ }
180182
181- let relative_id = absolute_id - self . id_range . min ;
182- let start = ( relative_id as uint ) * self . words_per_id ;
183+ fn compute_id_range ( & mut self , id : ast:: node_id ) -> ( uint , uint ) {
184+ let mut expanded = false ;
185+ let len = self . nodeid_to_bitset . len ( ) ;
186+ let n = do self . nodeid_to_bitset . find_or_insert_with ( id) |_| {
187+ expanded = true ;
188+ len
189+ } ;
190+ if expanded {
191+ let entry = if self . oper . initial_value ( ) { uint:: max_value } else { 0 } ;
192+ for self . words_per_id. times {
193+ self. gens. push( 0 ) ;
194+ self . kills . push ( 0 ) ;
195+ self . on_entry . push ( entry) ;
196+ }
197+ }
198+ let start = * n * self . words_per_id ;
183199 let end = start + self . words_per_id ;
200+
201+ assert ! ( start < self . gens. len( ) ) ;
202+ assert ! ( end <= self . gens. len( ) ) ;
203+ assert ! ( self . gens. len( ) == self . kills. len( ) ) ;
204+ assert ! ( self . gens. len( ) == self . on_entry. len( ) ) ;
205+
184206 ( start, end)
185207 }
186208
187209
188- pub fn each_bit_on_entry ( & self ,
210+ pub fn each_bit_on_entry_frozen ( & self ,
211+ id : ast:: node_id ,
212+ f : & fn ( uint ) -> bool ) -> bool {
213+ //! Iterates through each bit that is set on entry to `id`.
214+ //! Only useful after `propagate()` has been called.
215+ if !self . nodeid_to_bitset . contains_key ( & id) {
216+ return true ;
217+ }
218+ let ( start, end) = self . compute_id_range_frozen ( id) ;
219+ let on_entry = vec:: slice ( self . on_entry , start, end) ;
220+ debug ! ( "each_bit_on_entry_frozen(id=%?, on_entry=%s)" ,
221+ id, bits_to_str( on_entry) ) ;
222+ self . each_bit ( on_entry, f)
223+ }
224+
225+ pub fn each_bit_on_entry ( & mut self ,
189226 id : ast:: node_id ,
190227 f : & fn ( uint ) -> bool ) -> bool {
191228 //! Iterates through each bit that is set on entry to `id`.
@@ -198,7 +235,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
198235 self . each_bit ( on_entry, f)
199236 }
200237
201- pub fn each_gen_bit ( & self ,
238+ pub fn each_gen_bit ( & mut self ,
202239 id : ast:: node_id ,
203240 f : & fn ( uint ) -> bool ) -> bool {
204241 //! Iterates through each bit in the gen set for `id`.
@@ -210,6 +247,20 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
210247 self . each_bit ( gens, f)
211248 }
212249
250+ pub fn each_gen_bit_frozen ( & self ,
251+ id : ast:: node_id ,
252+ f : & fn ( uint ) -> bool ) -> bool {
253+ //! Iterates through each bit in the gen set for `id`.
254+ if !self . nodeid_to_bitset . contains_key ( & id) {
255+ return true ;
256+ }
257+ let ( start, end) = self . compute_id_range_frozen ( id) ;
258+ let gens = vec:: slice ( self . gens , start, end) ;
259+ debug ! ( "each_gen_bit(id=%?, gens=%s)" ,
260+ id, bits_to_str( gens) ) ;
261+ self . each_bit ( gens, f)
262+ }
263+
213264 fn each_bit ( & self ,
214265 words : & [ uint ] ,
215266 f : & fn ( uint ) -> bool ) -> bool {
@@ -285,8 +336,8 @@ impl<O:DataFlowOperator+Copy+'static> DataFlowContext<O> {
285336 pprust:: node_pat( ps, pat) => ( ps, pat. id )
286337 } ;
287338
288- if id >= self . id_range . min || id < self . id_range . max {
289- let ( start, end) = self . compute_id_range ( id) ;
339+ if self . nodeid_to_bitset . contains_key ( & id ) {
340+ let ( start, end) = self . compute_id_range_frozen ( id) ;
290341 let on_entry = vec:: slice ( self . on_entry , start, end) ;
291342 let entry_str = bits_to_str ( on_entry) ;
292343
0 commit comments