diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index cfec67bf3a395..285c5203af2f1 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -172,7 +172,7 @@ impl<'a> CheckLoanCtxt<'a> { //! are issued for future scopes and thus they may have been //! *issued* but not yet be in effect. - self.dfcx_loans.each_bit_on_entry_frozen(scope_id, |loan_index| { + self.dfcx_loans.each_bit_on_entry(scope_id, |loan_index| { let loan = &self.all_loans[loan_index]; op(loan) }) @@ -271,7 +271,7 @@ impl<'a> CheckLoanCtxt<'a> { //! we encounter `scope_id`. let mut result = Vec::new(); - self.dfcx_loans.each_gen_bit_frozen(scope_id, |loan_index| { + self.dfcx_loans.each_gen_bit(scope_id, |loan_index| { result.push(loan_index); true }); diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs index a9c312fc0a455..6ec3f82ad68e7 100644 --- a/src/librustc/middle/borrowck/move_data.rs +++ b/src/librustc/middle/borrowck/move_data.rs @@ -576,7 +576,7 @@ impl<'a> FlowedMoveData<'a> { * Iterates through each path moved by `id` */ - self.dfcx_moves.each_gen_bit_frozen(id, |index| { + self.dfcx_moves.each_gen_bit(id, |index| { let move = self.move_data.moves.borrow(); let move = move.get(index); let moved_path = move.path; @@ -592,7 +592,7 @@ impl<'a> FlowedMoveData<'a> { let mut ret = None; for loan_path_index in self.move_data.path_map.borrow().find(&*loan_path).iter() { - self.dfcx_moves.each_gen_bit_frozen(id, |move_index| { + self.dfcx_moves.each_gen_bit(id, |move_index| { let move = self.move_data.moves.borrow(); let move = move.get(move_index); if move.path == **loan_path_index { @@ -637,7 +637,7 @@ impl<'a> FlowedMoveData<'a> { let mut ret = true; - self.dfcx_moves.each_bit_on_entry_frozen(id, |index| { + self.dfcx_moves.each_bit_on_entry(id, |index| { let move = self.move_data.moves.borrow(); let move = move.get(index); let moved_path = move.path; @@ -693,7 +693,7 @@ impl<'a> FlowedMoveData<'a> { } }; - self.dfcx_assign.each_bit_on_entry_frozen(id, |index| { + self.dfcx_assign.each_bit_on_entry(id, |index| { let assignment = self.move_data.var_assignments.borrow(); let assignment = assignment.get(index); if assignment.path == loan_path_index && !f(assignment) { diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index e9c7a1cccb3e0..7c5b001354dbb 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -48,9 +48,6 @@ pub struct DataFlowContext<'a, O> { /// equal to bits_per_id/uint::BITS rounded up. words_per_id: uint, - // mapping from cfg node index to bitset index. - index_to_bitset: Vec>, - // mapping from node to cfg node index // FIXME (#6298): Shouldn't this go with CFG? nodeid_to_index: NodeMap, @@ -98,58 +95,7 @@ fn to_cfgidx_or_die(id: ast::NodeId, index: &NodeMap) -> CFGIndex { impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> { fn has_bitset_for_nodeid(&self, n: ast::NodeId) -> bool { assert!(n != ast::DUMMY_NODE_ID); - match self.nodeid_to_index.find(&n) { - None => false, - Some(&cfgidx) => self.has_bitset_for_cfgidx(cfgidx), - } - } - fn has_bitset_for_cfgidx(&self, cfgidx: CFGIndex) -> bool { - let node_id = cfgidx.node_id(); - node_id < self.index_to_bitset.len() && - self.index_to_bitset.get(node_id).is_some() - } - fn get_bitset_index(&self, cfgidx: CFGIndex) -> uint { - let node_id = cfgidx.node_id(); - self.index_to_bitset.get(node_id).unwrap() - } - fn get_or_create_bitset_index(&mut self, cfgidx: CFGIndex) -> uint { - assert!(self.words_per_id > 0); - let len = self.gens.len() / self.words_per_id; - let expanded; - let n; - if self.index_to_bitset.len() <= cfgidx.node_id() { - self.index_to_bitset.grow_set(cfgidx.node_id(), &None, Some(len)); - expanded = true; - n = len; - } else { - let entry = self.index_to_bitset.get_mut(cfgidx.node_id()); - match *entry { - None => { - *entry = Some(len); - expanded = true; - n = len; - } - Some(bitidx) => { - expanded = false; - n = bitidx; - } - } - } - if expanded { - let entry = if self.oper.initial_value() { uint::MAX } else {0}; - for _ in range(0, self.words_per_id) { - 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; - let len = self.gens.len(); - assert!(start < len); - assert!(end <= len); - n + self.nodeid_to_index.contains_key(&n) } } @@ -165,8 +111,9 @@ impl<'a, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, O> { }; if self.has_bitset_for_nodeid(id) { + assert!(self.bits_per_id > 0); let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index); - let (start, end) = self.compute_id_range_frozen(cfgidx); + let (start, end) = self.compute_id_range(cfgidx); let on_entry = self.on_entry.slice(start, end); let entry_str = bits_to_string(on_entry); @@ -243,14 +190,19 @@ impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> { id_range: IdRange, bits_per_id: uint) -> DataFlowContext<'a, O> { let words_per_id = (bits_per_id + uint::BITS - 1) / uint::BITS; + let num_nodes = cfg.graph.all_nodes().len(); debug!("DataFlowContext::new(analysis_name: {:s}, id_range={:?}, \ - bits_per_id={:?}, words_per_id={:?})", - analysis_name, id_range, bits_per_id, words_per_id); + bits_per_id={:?}, words_per_id={:?}) \ + num_nodes: {}", + analysis_name, id_range, bits_per_id, words_per_id, + num_nodes); - let gens = Vec::new(); - let kills = Vec::new(); - let on_entry = Vec::new(); + let entry = if oper.initial_value() { uint::MAX } else {0}; + + let gens = Vec::from_elem(num_nodes * words_per_id, 0); + let kills = Vec::from_elem(num_nodes * words_per_id, 0); + let on_entry = Vec::from_elem(num_nodes * words_per_id, entry); let nodeid_to_index = build_nodeid_to_index(decl, cfg); @@ -258,7 +210,6 @@ impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> { tcx: tcx, analysis_name: analysis_name, words_per_id: words_per_id, - index_to_bitset: Vec::new(), nodeid_to_index: nodeid_to_index, bits_per_id: bits_per_id, oper: oper, @@ -273,6 +224,8 @@ impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> { debug!("{:s} add_gen(id={:?}, bit={:?})", self.analysis_name, id, bit); assert!(self.nodeid_to_index.contains_key(&id)); + assert!(self.bits_per_id > 0); + let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index); let (start, end) = self.compute_id_range(cfgidx); let gens = self.gens.mut_slice(start, end); @@ -284,32 +237,21 @@ impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> { debug!("{:s} add_kill(id={:?}, bit={:?})", self.analysis_name, id, bit); assert!(self.nodeid_to_index.contains_key(&id)); + assert!(self.bits_per_id > 0); + let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index); let (start, end) = self.compute_id_range(cfgidx); let kills = self.kills.mut_slice(start, end); set_bit(kills, bit); } - fn apply_gen_kill(&mut self, cfgidx: CFGIndex, bits: &mut [uint]) { + fn apply_gen_kill(&self, cfgidx: CFGIndex, bits: &mut [uint]) { //! Applies the gen and kill sets for `cfgidx` to `bits` debug!("{:s} apply_gen_kill(cfgidx={}, bits={}) [before]", self.analysis_name, cfgidx, mut_bits_to_string(bits)); - let (start, end) = self.compute_id_range(cfgidx); - let gens = self.gens.slice(start, end); - bitwise(bits, gens, &Union); - let kills = self.kills.slice(start, end); - bitwise(bits, kills, &Subtract); - - debug!("{:s} apply_gen_kill(cfgidx={}, bits={}) [after]", - self.analysis_name, cfgidx, mut_bits_to_string(bits)); - } + assert!(self.bits_per_id > 0); - fn apply_gen_kill_frozen(&self, cfgidx: CFGIndex, bits: &mut [uint]) { - //! Applies the gen and kill sets for `cfgidx` to `bits` - //! Only useful after `propagate()` has been called. - debug!("{:s} apply_gen_kill(cfgidx={}, bits={}) [before]", - self.analysis_name, cfgidx, mut_bits_to_string(bits)); - let (start, end) = self.compute_id_range_frozen(cfgidx); + let (start, end) = self.compute_id_range(cfgidx); let gens = self.gens.slice(start, end); bitwise(bits, gens, &Union); let kills = self.kills.slice(start, end); @@ -319,15 +261,8 @@ impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> { self.analysis_name, cfgidx, mut_bits_to_string(bits)); } - fn compute_id_range_frozen(&self, cfgidx: CFGIndex) -> (uint, uint) { - let n = self.get_bitset_index(cfgidx); - let start = n * self.words_per_id; - let end = start + self.words_per_id; - (start, end) - } - - fn compute_id_range(&mut self, cfgidx: CFGIndex) -> (uint, uint) { - let n = self.get_or_create_bitset_index(cfgidx); + fn compute_id_range(&self, cfgidx: CFGIndex) -> (uint, uint) { + let n = cfgidx.node_id(); let start = n * self.words_per_id; let end = start + self.words_per_id; @@ -340,10 +275,10 @@ impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> { } - pub fn each_bit_on_entry_frozen(&self, - id: ast::NodeId, - f: |uint| -> bool) - -> bool { + pub fn each_bit_on_entry(&self, + id: ast::NodeId, + f: |uint| -> bool) + -> bool { //! Iterates through each bit that is set on entry to `id`. //! Only useful after `propagate()` has been called. if !self.has_bitset_for_nodeid(id) { @@ -360,17 +295,21 @@ impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> { -> bool { //! Iterates through each bit that is set on entry/exit to `cfgidx`. //! Only useful after `propagate()` has been called. - if !self.has_bitset_for_cfgidx(cfgidx) { + + if self.bits_per_id == 0 { + // Skip the surprisingly common degenerate case. (Note + // compute_id_range requires self.words_per_id > 0.) return true; } - let (start, end) = self.compute_id_range_frozen(cfgidx); + + let (start, end) = self.compute_id_range(cfgidx); let on_entry = self.on_entry.slice(start, end); let temp_bits; let slice = match e { Entry => on_entry, Exit => { let mut t = on_entry.to_vec(); - self.apply_gen_kill_frozen(cfgidx, t.as_mut_slice()); + self.apply_gen_kill(cfgidx, t.as_mut_slice()); temp_bits = t; temp_bits.as_slice() } @@ -380,15 +319,21 @@ impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> { self.each_bit(slice, f) } - pub fn each_gen_bit_frozen(&self, id: ast::NodeId, f: |uint| -> bool) - -> bool { + pub fn each_gen_bit(&self, id: ast::NodeId, f: |uint| -> bool) + -> bool { //! Iterates through each bit in the gen set for `id`. - //! Only useful after `propagate()` has been called. if !self.has_bitset_for_nodeid(id) { return true; } + + if self.bits_per_id == 0 { + // Skip the surprisingly common degenerate case. (Note + // compute_id_range requires self.words_per_id > 0.) + return true; + } + let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index); - let (start, end) = self.compute_id_range_frozen(cfgidx); + let (start, end) = self.compute_id_range(cfgidx); let gens = self.gens.slice(start, end); debug!("{:s} each_gen_bit(id={:?}, gens={})", self.analysis_name, id, bits_to_string(gens)); @@ -397,6 +342,8 @@ impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> { fn each_bit(&self, words: &[uint], f: |uint| -> bool) -> bool { //! Helper for iterating over the bits in a bit set. + //! Returns false on the first call to `f` that returns false; + //! if all calls to `f` return true, then returns true. for (word_index, &word) in words.iter().enumerate() { if word != 0 { @@ -527,6 +474,8 @@ impl<'a, 'b, O:DataFlowOperator> PropagationContext<'a, 'b, O> { in_out: &mut [uint]) { debug!("DataFlowContext::walk_cfg(in_out={}) {:s}", bits_to_string(in_out), self.dfcx.analysis_name); + assert!(self.dfcx.bits_per_id > 0); + cfg.graph.each_node(|node_index, node| { debug!("DataFlowContext::walk_cfg idx={} id={} begin in_out={}", node_index, node.data.id, bits_to_string(in_out)); @@ -570,6 +519,8 @@ impl<'a, 'b, O:DataFlowOperator> PropagationContext<'a, 'b, O> { let cfgidx = edge.target(); debug!("{:s} propagate_bits_into_entry_set_for(pred_bits={}, {} to {})", self.dfcx.analysis_name, bits_to_string(pred_bits), source, cfgidx); + assert!(self.dfcx.bits_per_id > 0); + let (start, end) = self.dfcx.compute_id_range(cfgidx); let changed = { // (scoping mutable borrow of self.dfcx.on_entry)