@@ -23,6 +23,7 @@ use core::cast;
23
23
use core:: io;
24
24
use core:: uint;
25
25
use core:: vec;
26
+ use core:: hashmap:: HashMap ;
26
27
use syntax:: ast;
27
28
use syntax:: ast_util;
28
29
use syntax:: ast_util:: id_range;
@@ -38,16 +39,16 @@ pub struct DataFlowContext<O> {
38
39
/// the data flow operator
39
40
priv oper : O ,
40
41
41
- /// range of ids that appear within the item in question
42
- priv id_range : id_range ,
43
-
44
42
/// number of bits to propagate per id
45
43
priv bits_per_id : uint ,
46
44
47
45
/// number of words we will use to store bits_per_id.
48
46
/// equal to bits_per_id/uint::bits rounded up.
49
47
priv words_per_id : uint ,
50
48
49
+ // mapping from node to bitset index.
50
+ priv nodeid_to_bitset : HashMap < ast:: node_id , uint > ,
51
+
51
52
// Bit sets per id. The following three fields (`gens`, `kills`,
52
53
// and `on_entry`) all have the same structure. For each id in
53
54
// `id_range`, there is a range of words equal to `words_per_id`.
@@ -109,19 +110,17 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
109
110
debug ! ( "DataFlowContext::new(id_range=%?, bits_per_id=%?, words_per_id=%?)" ,
110
111
id_range, bits_per_id, words_per_id) ;
111
112
112
- let len = ( id_range. max - id_range. min ) as uint * words_per_id;
113
- let gens = vec:: from_elem ( len, 0 ) ;
114
- let kills = vec:: from_elem ( len, 0 ) ;
115
- let elem = if oper. initial_value ( ) { uint:: max_value} else { 0 } ;
116
- let on_entry = vec:: from_elem ( len, elem) ;
113
+ let gens = ~[ ] ;
114
+ let kills = ~[ ] ;
115
+ let on_entry = ~[ ] ;
117
116
118
117
DataFlowContext {
119
118
tcx : tcx,
120
119
method_map : method_map,
121
120
words_per_id : words_per_id,
121
+ nodeid_to_bitset : HashMap :: new ( ) ,
122
122
bits_per_id : bits_per_id,
123
123
oper : oper,
124
- id_range : id_range,
125
124
gens : gens,
126
125
kills : kills,
127
126
on_entry : on_entry
@@ -150,7 +149,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
150
149
}
151
150
}
152
151
153
- fn apply_gen_kill ( & self , id : ast:: node_id , bits : & mut [ uint ] ) {
152
+ fn apply_gen_kill ( & mut self , id : ast:: node_id , bits : & mut [ uint ] ) {
154
153
//! Applies the gen and kill sets for `id` to `bits`
155
154
156
155
debug ! ( "apply_gen_kill(id=%?, bits=%s) [before]" ,
@@ -165,7 +164,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
165
164
id, mut_bits_to_str( bits) ) ;
166
165
}
167
166
168
- fn apply_kill ( & self , id : ast:: node_id , bits : & mut [ uint ] ) {
167
+ fn apply_kill ( & mut self , id : ast:: node_id , bits : & mut [ uint ] ) {
169
168
debug ! ( "apply_kill(id=%?, bits=%s) [before]" ,
170
169
id, mut_bits_to_str( bits) ) ;
171
170
let ( start, end) = self . compute_id_range ( id) ;
@@ -175,18 +174,56 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
175
174
id, mut_bits_to_str( bits) ) ;
176
175
}
177
176
178
- fn compute_id_range ( & self , absolute_id : ast:: node_id ) -> ( uint , uint ) {
179
- assert ! ( absolute_id >= self . id_range. min) ;
180
- assert ! ( absolute_id < self . id_range. max) ;
177
+ fn compute_id_range_frozen ( & self , id : ast:: node_id ) -> ( uint , uint ) {
178
+ let n = * self . nodeid_to_bitset . get ( & id) ;
179
+ let start = n * self . words_per_id ;
180
+ let end = start + self . words_per_id ;
181
+ ( start, end)
182
+ }
181
183
182
- let relative_id = absolute_id - self . id_range . min ;
183
- let start = ( relative_id as uint ) * self . words_per_id ;
184
+ fn compute_id_range ( & mut self , id : ast:: node_id ) -> ( uint , uint ) {
185
+ let mut expanded = false ;
186
+ let len = self . nodeid_to_bitset . len ( ) ;
187
+ let n = do self . nodeid_to_bitset . find_or_insert_with ( id) |_| {
188
+ expanded = true ;
189
+ len
190
+ } ;
191
+ if expanded {
192
+ let entry = if self . oper . initial_value ( ) { uint:: max_value } else { 0 } ;
193
+ for self . words_per_id. times {
194
+ self. gens. push( 0 ) ;
195
+ self . kills . push ( 0 ) ;
196
+ self . on_entry . push ( entry) ;
197
+ }
198
+ }
199
+ let start = ( * n) * self . words_per_id ;
184
200
let end = start + self . words_per_id ;
201
+
202
+ assert ! ( start < self . gens. len( ) ) ;
203
+ assert ! ( end <= self . gens. len( ) ) ;
204
+ assert ! ( self . gens. len( ) == self . kills. len( ) ) ;
205
+ assert ! ( self . gens. len( ) == self . on_entry. len( ) ) ;
206
+
185
207
( start, end)
186
208
}
187
209
188
210
189
- pub fn each_bit_on_entry ( & self ,
211
+ pub fn each_bit_on_entry_frozen ( & self ,
212
+ id : ast:: node_id ,
213
+ f : & fn ( uint ) -> bool ) -> bool {
214
+ //! Iterates through each bit that is set on entry to `id`.
215
+ //! Only useful after `propagate()` has been called.
216
+ if !self . nodeid_to_bitset . contains_key ( & id) {
217
+ return true ;
218
+ }
219
+ let ( start, end) = self . compute_id_range_frozen ( id) ;
220
+ let on_entry = vec:: slice ( self . on_entry , start, end) ;
221
+ debug ! ( "each_bit_on_entry_frozen(id=%?, on_entry=%s)" ,
222
+ id, bits_to_str( on_entry) ) ;
223
+ self . each_bit ( on_entry, f)
224
+ }
225
+
226
+ pub fn each_bit_on_entry ( & mut self ,
190
227
id : ast:: node_id ,
191
228
f : & fn ( uint ) -> bool ) -> bool {
192
229
//! Iterates through each bit that is set on entry to `id`.
@@ -199,7 +236,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
199
236
self . each_bit ( on_entry, f)
200
237
}
201
238
202
- pub fn each_gen_bit ( & self ,
239
+ pub fn each_gen_bit ( & mut self ,
203
240
id : ast:: node_id ,
204
241
f : & fn ( uint ) -> bool ) -> bool {
205
242
//! Iterates through each bit in the gen set for `id`.
@@ -211,6 +248,20 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
211
248
self . each_bit ( gens, f)
212
249
}
213
250
251
+ pub fn each_gen_bit_frozen ( & self ,
252
+ id : ast:: node_id ,
253
+ f : & fn ( uint ) -> bool ) -> bool {
254
+ //! Iterates through each bit in the gen set for `id`.
255
+ if !self . nodeid_to_bitset . contains_key ( & id) {
256
+ return true ;
257
+ }
258
+ let ( start, end) = self . compute_id_range_frozen ( id) ;
259
+ let gens = vec:: slice ( self . gens , start, end) ;
260
+ debug ! ( "each_gen_bit(id=%?, gens=%s)" ,
261
+ id, bits_to_str( gens) ) ;
262
+ self . each_bit ( gens, f)
263
+ }
264
+
214
265
fn each_bit ( & self ,
215
266
words : & [ uint ] ,
216
267
f : & fn ( uint ) -> bool ) -> bool {
@@ -286,8 +337,8 @@ impl<O:DataFlowOperator+Copy+'static> DataFlowContext<O> {
286
337
pprust:: node_pat( ps, pat) => ( ps, pat. id )
287
338
} ;
288
339
289
- if id >= self . id_range . min || id < self . id_range . max {
290
- let ( start, end) = self . compute_id_range ( id) ;
340
+ if self . nodeid_to_bitset . contains_key ( & id ) {
341
+ let ( start, end) = self . compute_id_range_frozen ( id) ;
291
342
let on_entry = vec:: slice ( self . on_entry , start, end) ;
292
343
let entry_str = bits_to_str ( on_entry) ;
293
344
0 commit comments