Skip to content

Commit cfa8f63

Browse files
committed
rustc: map node ids through a table that ensures bitset indexes in dataflow are dense
1 parent 38e0574 commit cfa8f63

File tree

3 files changed

+75
-24
lines changed

3 files changed

+75
-24
lines changed

src/librustc/middle/borrowck/check_loans.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ impl<'self> CheckLoanCtxt<'self> {
8383
//! are issued for future scopes and thus they may have been
8484
//! *issued* but not yet be in effect.
8585
86-
for self.dfcx_loans.each_bit_on_entry(scope_id) |loan_index| {
86+
for self.dfcx_loans.each_bit_on_entry_frozen(scope_id) |loan_index| {
8787
let loan = &self.all_loans[loan_index];
8888
if !op(loan) {
8989
return false;
@@ -135,7 +135,7 @@ impl<'self> CheckLoanCtxt<'self> {
135135
//! we encounter `scope_id`.
136136
137137
let mut result = ~[];
138-
for self.dfcx_loans.each_gen_bit(scope_id) |loan_index| {
138+
for self.dfcx_loans.each_gen_bit_frozen(scope_id) |loan_index| {
139139
result.push(loan_index);
140140
}
141141
return result;

src/librustc/middle/borrowck/move_data.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ impl FlowedMoveData {
505505

506506
let opt_loan_path_index = self.move_data.existing_move_path(loan_path);
507507

508-
for self.dfcx_moves.each_bit_on_entry(id) |index| {
508+
for self.dfcx_moves.each_bit_on_entry_frozen(id) |index| {
509509
let move = &self.move_data.moves[index];
510510
let moved_path = move.path;
511511
if base_indices.contains(&moved_path) {
@@ -561,7 +561,7 @@ impl FlowedMoveData {
561561
}
562562
};
563563

564-
for self.dfcx_assign.each_bit_on_entry(id) |index| {
564+
for self.dfcx_assign.each_bit_on_entry_frozen(id) |index| {
565565
let assignment = &self.move_data.var_assignments[index];
566566
if assignment.path == loan_path_index && !f(assignment) {
567567
return false;

src/librustc/middle/dataflow.rs

+71-20
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use core::cast;
2323
use core::io;
2424
use core::uint;
2525
use core::vec;
26+
use core::hashmap::HashMap;
2627
use syntax::ast;
2728
use syntax::ast_util;
2829
use syntax::ast_util::id_range;
@@ -38,16 +39,16 @@ pub struct DataFlowContext<O> {
3839
/// the data flow operator
3940
priv oper: O,
4041

41-
/// range of ids that appear within the item in question
42-
priv id_range: id_range,
43-
4442
/// number of bits to propagate per id
4543
priv bits_per_id: uint,
4644

4745
/// number of words we will use to store bits_per_id.
4846
/// equal to bits_per_id/uint::bits rounded up.
4947
priv words_per_id: uint,
5048

49+
// mapping from node to bitset index.
50+
priv nodeid_to_bitset: HashMap<ast::node_id,uint>,
51+
5152
// Bit sets per id. The following three fields (`gens`, `kills`,
5253
// and `on_entry`) all have the same structure. For each id in
5354
// `id_range`, there is a range of words equal to `words_per_id`.
@@ -109,19 +110,17 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
109110
debug!("DataFlowContext::new(id_range=%?, bits_per_id=%?, words_per_id=%?)",
110111
id_range, bits_per_id, words_per_id);
111112

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 = ~[];
117116

118117
DataFlowContext {
119118
tcx: tcx,
120119
method_map: method_map,
121120
words_per_id: words_per_id,
121+
nodeid_to_bitset: HashMap::new(),
122122
bits_per_id: bits_per_id,
123123
oper: oper,
124-
id_range: id_range,
125124
gens: gens,
126125
kills: kills,
127126
on_entry: on_entry
@@ -150,7 +149,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
150149
}
151150
}
152151

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]) {
154153
//! Applies the gen and kill sets for `id` to `bits`
155154
156155
debug!("apply_gen_kill(id=%?, bits=%s) [before]",
@@ -165,7 +164,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
165164
id, mut_bits_to_str(bits));
166165
}
167166

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]) {
169168
debug!("apply_kill(id=%?, bits=%s) [before]",
170169
id, mut_bits_to_str(bits));
171170
let (start, end) = self.compute_id_range(id);
@@ -175,18 +174,56 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
175174
id, mut_bits_to_str(bits));
176175
}
177176

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+
}
181183

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;
184200
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+
185207
(start, end)
186208
}
187209

188210

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,
190227
id: ast::node_id,
191228
f: &fn(uint) -> bool) -> bool {
192229
//! Iterates through each bit that is set on entry to `id`.
@@ -199,7 +236,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
199236
self.each_bit(on_entry, f)
200237
}
201238

202-
pub fn each_gen_bit(&self,
239+
pub fn each_gen_bit(&mut self,
203240
id: ast::node_id,
204241
f: &fn(uint) -> bool) -> bool {
205242
//! Iterates through each bit in the gen set for `id`.
@@ -211,6 +248,20 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
211248
self.each_bit(gens, f)
212249
}
213250

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+
214265
fn each_bit(&self,
215266
words: &[uint],
216267
f: &fn(uint) -> bool) -> bool {
@@ -286,8 +337,8 @@ impl<O:DataFlowOperator+Copy+'static> DataFlowContext<O> {
286337
pprust::node_pat(ps, pat) => (ps, pat.id)
287338
};
288339

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);
291342
let on_entry = vec::slice(self.on_entry, start, end);
292343
let entry_str = bits_to_str(on_entry);
293344

0 commit comments

Comments
 (0)