auto merge of #7202 : pcwalton/rust/resolve-speed, r=pcwalton

I'm pretty sure this got adequately reviewed by a combination of @nikomatsakis and @graydon so I'm rubber stamping it because I really want this in (it makes it much less likely for me to swap, allowing me to get more work done).
This commit is contained in:
bors 2013-06-17 10:40:21 -07:00
commit 9a5bdd71ce
3 changed files with 76 additions and 25 deletions

View File

@ -82,7 +82,7 @@ impl<'self> CheckLoanCtxt<'self> {
//! are issued for future scopes and thus they may have been
//! *issued* but not yet be in effect.
for self.dfcx_loans.each_bit_on_entry(scope_id) |loan_index| {
for self.dfcx_loans.each_bit_on_entry_frozen(scope_id) |loan_index| {
let loan = &self.all_loans[loan_index];
if !op(loan) {
return false;
@ -134,7 +134,7 @@ impl<'self> CheckLoanCtxt<'self> {
//! we encounter `scope_id`.
let mut result = ~[];
for self.dfcx_loans.each_gen_bit(scope_id) |loan_index| {
for self.dfcx_loans.each_gen_bit_frozen(scope_id) |loan_index| {
result.push(loan_index);
}
return result;

View File

@ -504,7 +504,7 @@ impl FlowedMoveData {
let opt_loan_path_index = self.move_data.existing_move_path(loan_path);
for self.dfcx_moves.each_bit_on_entry(id) |index| {
for self.dfcx_moves.each_bit_on_entry_frozen(id) |index| {
let move = &self.move_data.moves[index];
let moved_path = move.path;
if base_indices.contains(&moved_path) {
@ -560,7 +560,7 @@ impl FlowedMoveData {
}
};
for self.dfcx_assign.each_bit_on_entry(id) |index| {
for self.dfcx_assign.each_bit_on_entry_frozen(id) |index| {
let assignment = &self.move_data.var_assignments[index];
if assignment.path == loan_path_index && !f(assignment) {
return false;

View File

@ -22,6 +22,7 @@ use core::cast;
use core::io;
use core::uint;
use core::vec;
use core::hashmap::HashMap;
use syntax::ast;
use syntax::ast_util;
use syntax::ast_util::id_range;
@ -37,9 +38,6 @@ pub struct DataFlowContext<O> {
/// the data flow operator
priv oper: O,
/// range of ids that appear within the item in question
priv id_range: id_range,
/// number of bits to propagate per id
priv bits_per_id: uint,
@ -47,6 +45,9 @@ pub struct DataFlowContext<O> {
/// equal to bits_per_id/uint::bits rounded up.
priv words_per_id: uint,
// mapping from node to bitset index.
priv nodeid_to_bitset: HashMap<ast::node_id,uint>,
// Bit sets per id. The following three fields (`gens`, `kills`,
// and `on_entry`) all have the same structure. For each id in
// `id_range`, there is a range of words equal to `words_per_id`.
@ -108,19 +109,17 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
debug!("DataFlowContext::new(id_range=%?, bits_per_id=%?, words_per_id=%?)",
id_range, bits_per_id, words_per_id);
let len = (id_range.max - id_range.min) as uint * words_per_id;
let gens = vec::from_elem(len, 0);
let kills = vec::from_elem(len, 0);
let elem = if oper.initial_value() {uint::max_value} else {0};
let on_entry = vec::from_elem(len, elem);
let gens = ~[];
let kills = ~[];
let on_entry = ~[];
DataFlowContext {
tcx: tcx,
method_map: method_map,
words_per_id: words_per_id,
nodeid_to_bitset: HashMap::new(),
bits_per_id: bits_per_id,
oper: oper,
id_range: id_range,
gens: gens,
kills: kills,
on_entry: on_entry
@ -149,7 +148,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
}
}
fn apply_gen_kill(&self, id: ast::node_id, bits: &mut [uint]) {
fn apply_gen_kill(&mut self, id: ast::node_id, bits: &mut [uint]) {
//! Applies the gen and kill sets for `id` to `bits`
debug!("apply_gen_kill(id=%?, bits=%s) [before]",
@ -164,7 +163,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
id, mut_bits_to_str(bits));
}
fn apply_kill(&self, id: ast::node_id, bits: &mut [uint]) {
fn apply_kill(&mut self, id: ast::node_id, bits: &mut [uint]) {
debug!("apply_kill(id=%?, bits=%s) [before]",
id, mut_bits_to_str(bits));
let (start, end) = self.compute_id_range(id);
@ -174,18 +173,56 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
id, mut_bits_to_str(bits));
}
fn compute_id_range(&self, absolute_id: ast::node_id) -> (uint, uint) {
assert!(absolute_id >= self.id_range.min);
assert!(absolute_id < self.id_range.max);
let relative_id = absolute_id - self.id_range.min;
let start = (relative_id as uint) * self.words_per_id;
fn compute_id_range_frozen(&self, id: ast::node_id) -> (uint, uint) {
let n = *self.nodeid_to_bitset.get(&id);
let start = n * self.words_per_id;
let end = start + self.words_per_id;
(start, end)
}
fn compute_id_range(&mut self, id: ast::node_id) -> (uint, uint) {
let mut expanded = false;
let len = self.nodeid_to_bitset.len();
let n = do self.nodeid_to_bitset.find_or_insert_with(id) |_| {
expanded = true;
len
};
if expanded {
let entry = if self.oper.initial_value() { uint::max_value } else {0};
for self.words_per_id.times {
self.gens.push(0);
self.kills.push(0);
self.on_entry.push(entry);
}
}
let start = *n * self.words_per_id;
let end = start + self.words_per_id;
pub fn each_bit_on_entry(&self,
assert!(start < self.gens.len());
assert!(end <= self.gens.len());
assert!(self.gens.len() == self.kills.len());
assert!(self.gens.len() == self.on_entry.len());
(start, end)
}
pub fn each_bit_on_entry_frozen(&self,
id: ast::node_id,
f: &fn(uint) -> bool) -> bool {
//! Iterates through each bit that is set on entry to `id`.
//! Only useful after `propagate()` has been called.
if !self.nodeid_to_bitset.contains_key(&id) {
return true;
}
let (start, end) = self.compute_id_range_frozen(id);
let on_entry = vec::slice(self.on_entry, start, end);
debug!("each_bit_on_entry_frozen(id=%?, on_entry=%s)",
id, bits_to_str(on_entry));
self.each_bit(on_entry, f)
}
pub fn each_bit_on_entry(&mut self,
id: ast::node_id,
f: &fn(uint) -> bool) -> bool {
//! Iterates through each bit that is set on entry to `id`.
@ -198,7 +235,7 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
self.each_bit(on_entry, f)
}
pub fn each_gen_bit(&self,
pub fn each_gen_bit(&mut self,
id: ast::node_id,
f: &fn(uint) -> bool) -> bool {
//! Iterates through each bit in the gen set for `id`.
@ -210,6 +247,20 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
self.each_bit(gens, f)
}
pub fn each_gen_bit_frozen(&self,
id: ast::node_id,
f: &fn(uint) -> bool) -> bool {
//! Iterates through each bit in the gen set for `id`.
if !self.nodeid_to_bitset.contains_key(&id) {
return true;
}
let (start, end) = self.compute_id_range_frozen(id);
let gens = vec::slice(self.gens, start, end);
debug!("each_gen_bit(id=%?, gens=%s)",
id, bits_to_str(gens));
self.each_bit(gens, f)
}
fn each_bit(&self,
words: &[uint],
f: &fn(uint) -> bool) -> bool {
@ -285,8 +336,8 @@ impl<O:DataFlowOperator+Copy+'static> DataFlowContext<O> {
pprust::node_pat(ps, pat) => (ps, pat.id)
};
if id >= self.id_range.min || id < self.id_range.max {
let (start, end) = self.compute_id_range(id);
if self.nodeid_to_bitset.contains_key(&id) {
let (start, end) = self.compute_id_range_frozen(id);
let on_entry = vec::slice(self.on_entry, start, end);
let entry_str = bits_to_str(on_entry);