34
34
35
35
use std:: collections:: VecDeque ;
36
36
use std:: fmt:: { Debug , Formatter } ;
37
+ use std:: ops:: Range ;
37
38
38
39
use rustc_data_structures:: fx:: FxHashMap ;
39
40
use rustc_index:: bit_set:: BitSet ;
@@ -448,10 +449,8 @@ impl<V: Clone + HasTop + HasBottom> State<V> {
448
449
449
450
pub fn flood_with ( & mut self , place : PlaceRef < ' _ > , map : & Map , value : V ) {
450
451
let StateData :: Reachable ( values) = & mut self . 0 else { return } ;
451
- map. for_each_aliasing_place ( place, None , & mut |place| {
452
- if let Some ( vi) = map. places [ place] . value_index {
453
- values[ vi] = value. clone ( ) ;
454
- }
452
+ map. for_each_aliasing_place ( place, None , & mut |vi| {
453
+ values[ vi] = value. clone ( ) ;
455
454
} ) ;
456
455
}
457
456
@@ -461,10 +460,8 @@ impl<V: Clone + HasTop + HasBottom> State<V> {
461
460
462
461
pub fn flood_discr_with ( & mut self , place : PlaceRef < ' _ > , map : & Map , value : V ) {
463
462
let StateData :: Reachable ( values) = & mut self . 0 else { return } ;
464
- map. for_each_aliasing_place ( place, Some ( TrackElem :: Discriminant ) , & mut |place| {
465
- if let Some ( vi) = map. places [ place] . value_index {
466
- values[ vi] = value. clone ( ) ;
467
- }
463
+ map. for_each_aliasing_place ( place, Some ( TrackElem :: Discriminant ) , & mut |vi| {
464
+ values[ vi] = value. clone ( ) ;
468
465
} ) ;
469
466
}
470
467
@@ -589,6 +586,9 @@ pub struct Map {
589
586
projections : FxHashMap < ( PlaceIndex , TrackElem ) , PlaceIndex > ,
590
587
places : IndexVec < PlaceIndex , PlaceInfo > ,
591
588
value_count : usize ,
589
+ // The Range corresponds to a slice into `inner_values_buffer`.
590
+ inner_values : IndexVec < PlaceIndex , Range < usize > > ,
591
+ inner_values_buffer : Vec < ValueIndex > ,
592
592
}
593
593
594
594
impl Map {
@@ -598,6 +598,8 @@ impl Map {
598
598
projections : FxHashMap :: default ( ) ,
599
599
places : IndexVec :: new ( ) ,
600
600
value_count : 0 ,
601
+ inner_values : IndexVec :: new ( ) ,
602
+ inner_values_buffer : Vec :: new ( ) ,
601
603
}
602
604
}
603
605
@@ -665,6 +667,14 @@ impl Map {
665
667
// And push the eventual children places to the worklist.
666
668
self . register_children ( tcx, place, ty, & filter, & mut worklist) ;
667
669
}
670
+
671
+ self . inner_values_buffer = Vec :: with_capacity ( self . value_count ) ;
672
+ self . inner_values = IndexVec :: from_elem ( 0 ..0 , & self . places ) ;
673
+ for local in body. local_decls . indices ( ) {
674
+ if let Some ( place) = self . locals [ local] {
675
+ self . cache_preorder_invoke ( place) ;
676
+ }
677
+ }
668
678
}
669
679
670
680
/// Potentially register the (local, projection) place and its fields, recursively.
@@ -718,6 +728,25 @@ impl Map {
718
728
} ) ;
719
729
}
720
730
731
+ /// Precompute the list of values inside `root` and store it inside
732
+ /// as a slice within `inner_values_buffer`.
733
+ fn cache_preorder_invoke ( & mut self , root : PlaceIndex ) {
734
+ let start = self . inner_values_buffer . len ( ) ;
735
+ if let Some ( vi) = self . places [ root] . value_index {
736
+ self . inner_values_buffer . push ( vi) ;
737
+ }
738
+
739
+ // We manually iterate instead of using `children` as we need to mutate `self`.
740
+ let mut next_child = self . places [ root] . first_child ;
741
+ while let Some ( child) = next_child {
742
+ self . cache_preorder_invoke ( child) ;
743
+ next_child = self . places [ child] . next_sibling ;
744
+ }
745
+
746
+ let end = self . inner_values_buffer . len ( ) ;
747
+ self . inner_values [ root] = start..end;
748
+ }
749
+
721
750
/// Returns the number of tracked places, i.e., those for which a value can be stored.
722
751
pub fn tracked_places ( & self ) -> usize {
723
752
self . value_count
@@ -768,11 +797,11 @@ impl Map {
768
797
///
769
798
/// `tail_elem` allows to support discriminants that are not a place in MIR, but that we track
770
799
/// as such.
771
- pub fn for_each_aliasing_place (
800
+ fn for_each_aliasing_place (
772
801
& self ,
773
802
place : PlaceRef < ' _ > ,
774
803
tail_elem : Option < TrackElem > ,
775
- f : & mut impl FnMut ( PlaceIndex ) ,
804
+ f : & mut impl FnMut ( ValueIndex ) ,
776
805
) {
777
806
if place. is_indirect ( ) {
778
807
// We do not track indirect places.
@@ -789,7 +818,9 @@ impl Map {
789
818
. chain ( tail_elem. map ( Ok ) . into_iter ( ) ) ;
790
819
for elem in elems {
791
820
// A field aliases the parent place.
792
- f ( index) ;
821
+ if let Some ( vi) = self . places [ index] . value_index {
822
+ f ( vi) ;
823
+ }
793
824
794
825
let Ok ( elem) = elem else { return } ;
795
826
let sub = self . apply ( index, elem) ;
@@ -803,15 +834,15 @@ impl Map {
803
834
return ;
804
835
}
805
836
}
806
- self . preorder_invoke ( index, f) ;
837
+ self . for_each_value_inside ( index, f) ;
807
838
}
808
839
809
840
/// Invoke the given function on all the descendants of the given place, except one branch.
810
841
fn for_each_variant_sibling (
811
842
& self ,
812
843
parent : PlaceIndex ,
813
844
preserved_child : Option < PlaceIndex > ,
814
- f : & mut impl FnMut ( PlaceIndex ) ,
845
+ f : & mut impl FnMut ( ValueIndex ) ,
815
846
) {
816
847
for sibling in self . children ( parent) {
817
848
let elem = self . places [ sibling] . proj_elem ;
@@ -821,16 +852,17 @@ impl Map {
821
852
// Only invalidate the other variants, the current one is fine.
822
853
&& Some ( sibling) != preserved_child
823
854
{
824
- self . preorder_invoke ( sibling, f) ;
855
+ self . for_each_value_inside ( sibling, f) ;
825
856
}
826
857
}
827
858
}
828
859
829
- /// Invoke a function on the given place and all descendants.
830
- fn preorder_invoke ( & self , root : PlaceIndex , f : & mut impl FnMut ( PlaceIndex ) ) {
831
- f ( root) ;
832
- for child in self . children ( root) {
833
- self . preorder_invoke ( child, f) ;
860
+ /// Invoke a function on each value in the given place and all descendants.
861
+ fn for_each_value_inside ( & self , root : PlaceIndex , f : & mut impl FnMut ( ValueIndex ) ) {
862
+ let range = self . inner_values [ root] . clone ( ) ;
863
+ let values = & self . inner_values_buffer [ range] ;
864
+ for & v in values {
865
+ f ( v)
834
866
}
835
867
}
836
868
}
0 commit comments