]> git.lizzy.rs Git - rust.git/commitdiff
rustc: map node ids through a table that ensures bitset indexes in dataflow are dense
authorGraydon Hoare <graydon@mozilla.com>
Thu, 13 Jun 2013 17:07:34 +0000 (10:07 -0700)
committerPatrick Walton <pcwalton@mimiga.net>
Mon, 17 Jun 2013 17:37:42 +0000 (10:37 -0700)
src/librustc/middle/borrowck/check_loans.rs
src/librustc/middle/borrowck/move_data.rs
src/librustc/middle/dataflow.rs

index e384d35373e63cff44e854c442eb8548b737b476..be87beba7784b25213d98f46f86c6d761fe81bdb 100644 (file)
@@ -82,7 +82,7 @@ pub fn each_issued_loan(&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 @@ pub fn loans_generated_by(&self, scope_id: ast::node_id) -> ~[uint] {
         //! 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;
index bd560fca9854a539a77b2e605afbb3e873999321..d19afd0f5fc982de76a834f3a9ba9fccc378870b 100644 (file)
@@ -504,7 +504,7 @@ pub fn each_move_of(&self,
 
         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 @@ pub fn each_assignment_of(&self,
             }
         };
 
-        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;
index 8037bacd3e72b8fc68419676993a656acf008a07..8403b1616f41e72648152f3c3fbc46bcd56eff23 100644 (file)
@@ -22,6 +22,7 @@
 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 @@ pub fn new(tcx: ty::ctxt,
         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 @@ pub fn add_kill(&mut self, id: ast::node_id, bit: uint) {
         }
     }
 
-    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 @@ fn apply_gen_kill(&self, id: ast::node_id, bits: &mut [uint]) {
                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 @@ fn apply_kill(&self, id: ast::node_id, bits: &mut [uint]) {
                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);
+    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)
+    }
 
-        let relative_id = absolute_id - self.id_range.min;
-        let start = (relative_id as uint) * self.words_per_id;
+    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;
+
+        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(&self,
+    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 @@ pub fn each_bit_on_entry(&self,
         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 @@ pub fn each_gen_bit(&self,
         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 @@ fn pretty_print_to(@self, wr: @io::Writer, blk: &ast::blk) {
                 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);