@@ -22,6 +22,7 @@ use core::cast;
22
22
use core:: io;
23
23
use core:: uint;
24
24
use core:: vec;
25
+ use core:: hashmap:: HashMap ;
25
26
use syntax:: ast;
26
27
use syntax:: ast_util;
27
28
use syntax:: ast_util:: id_range;
@@ -37,16 +38,16 @@ pub struct DataFlowContext<O> {
37
38
/// the data flow operator
38
39
priv oper : O ,
39
40
40
- /// range of ids that appear within the item in question
41
- priv id_range : id_range ,
42
-
43
41
/// number of bits to propagate per id
44
42
priv bits_per_id : uint ,
45
43
46
44
/// number of words we will use to store bits_per_id.
47
45
/// equal to bits_per_id/uint::bits rounded up.
48
46
priv words_per_id : uint ,
49
47
48
+ // mapping from node to bitset index.
49
+ priv nodeid_to_bitset : HashMap < ast:: node_id , uint > ,
50
+
50
51
// Bit sets per id. The following three fields (`gens`, `kills`,
51
52
// and `on_entry`) all have the same structure. For each id in
52
53
// `id_range`, there is a range of words equal to `words_per_id`.
@@ -108,19 +109,17 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
108
109
debug ! ( "DataFlowContext::new(id_range=%?, bits_per_id=%?, words_per_id=%?)" ,
109
110
id_range, bits_per_id, words_per_id) ;
110
111
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 = ~[ ] ;
116
115
117
116
DataFlowContext {
118
117
tcx : tcx,
119
118
method_map : method_map,
120
119
words_per_id : words_per_id,
120
+ nodeid_to_bitset : HashMap :: new ( ) ,
121
121
bits_per_id : bits_per_id,
122
122
oper : oper,
123
- id_range : id_range,
124
123
gens : gens,
125
124
kills : kills,
126
125
on_entry : on_entry
@@ -149,7 +148,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
149
148
}
150
149
}
151
150
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 ] ) {
153
152
//! Applies the gen and kill sets for `id` to `bits`
154
153
155
154
debug ! ( "apply_gen_kill(id=%?, bits=%s) [before]" ,
@@ -164,7 +163,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
164
163
id, mut_bits_to_str( bits) ) ;
165
164
}
166
165
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 ] ) {
168
167
debug ! ( "apply_kill(id=%?, bits=%s) [before]" ,
169
168
id, mut_bits_to_str( bits) ) ;
170
169
let ( start, end) = self . compute_id_range ( id) ;
@@ -174,18 +173,56 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
174
173
id, mut_bits_to_str( bits) ) ;
175
174
}
176
175
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
+ }
180
182
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 ;
183
199
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
+
184
206
( start, end)
185
207
}
186
208
187
209
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 ,
189
226
id : ast:: node_id ,
190
227
f : & fn ( uint ) -> bool ) -> bool {
191
228
//! Iterates through each bit that is set on entry to `id`.
@@ -198,7 +235,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
198
235
self . each_bit ( on_entry, f)
199
236
}
200
237
201
- pub fn each_gen_bit ( & self ,
238
+ pub fn each_gen_bit ( & mut self ,
202
239
id : ast:: node_id ,
203
240
f : & fn ( uint ) -> bool ) -> bool {
204
241
//! Iterates through each bit in the gen set for `id`.
@@ -210,6 +247,20 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
210
247
self . each_bit ( gens, f)
211
248
}
212
249
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
+
213
264
fn each_bit ( & self ,
214
265
words : & [ uint ] ,
215
266
f : & fn ( uint ) -> bool ) -> bool {
@@ -285,8 +336,8 @@ impl<O:DataFlowOperator+Copy+'static> DataFlowContext<O> {
285
336
pprust:: node_pat( ps, pat) => ( ps, pat. id )
286
337
} ;
287
338
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) ;
290
341
let on_entry = vec:: slice ( self . on_entry , start, end) ;
291
342
let entry_str = bits_to_str ( on_entry) ;
292
343
0 commit comments