22//! representation for the common case where PTR_SIZE consecutive bytes have the same provenance. 
33
44use  std:: cmp; 
5+ use  std:: ops:: Range ; 
56
67use  rustc_abi:: { HasDataLayout ,  Size } ; 
78use  rustc_data_structures:: sorted_map:: SortedMap ; 
@@ -66,6 +67,15 @@ impl ProvenanceMap {
6667} 
6768
6869impl < Prov :  Provenance >  ProvenanceMap < Prov >  { 
70+     fn  adjusted_range ( range :  AllocRange ,  cx :  & impl  HasDataLayout )  -> Range < Size >  { 
71+         // We have to go back `pointer_size - 1` bytes, as that one would still overlap with 
72+         // the beginning of this range. 
73+         let  adjusted_start = Size :: from_bytes ( 
74+             range. start . bytes ( ) . saturating_sub ( cx. data_layout ( ) . pointer_size . bytes ( )  - 1 ) , 
75+         ) ; 
76+         adjusted_start..range. end ( ) 
77+     } 
78+ 
6979    /// Returns all ptr-sized provenance in the given range. 
7080/// If the range has length 0, returns provenance that crosses the edge between `start-1` and 
7181/// `start`. 
@@ -74,12 +84,17 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
7484        range :  AllocRange , 
7585        cx :  & impl  HasDataLayout , 
7686    )  -> & [ ( Size ,  Prov ) ]  { 
77-         // We have to go back `pointer_size - 1` bytes, as that one would still overlap with 
78-         // the beginning of this range. 
79-         let  adjusted_start = Size :: from_bytes ( 
80-             range. start . bytes ( ) . saturating_sub ( cx. data_layout ( ) . pointer_size . bytes ( )  - 1 ) , 
81-         ) ; 
82-         self . ptrs . range ( adjusted_start..range. end ( ) ) 
87+         self . ptrs . range ( Self :: adjusted_range ( range,  cx) ) 
88+     } 
89+ 
90+     /// `pm.range_get_ptrs_is_empty(r, cx)` == `pm.range_get_ptrs(r, cx).is_empty()`, but is 
91+ /// faster. 
92+ pub ( super )  fn  range_get_ptrs_is_empty ( 
93+         & self , 
94+         range :  AllocRange , 
95+         cx :  & impl  HasDataLayout , 
96+     )  -> bool  { 
97+         self . ptrs . range_is_empty ( Self :: adjusted_range ( range,  cx) ) 
8398    } 
8499
85100    /// Returns all byte-wise provenance in the given range. 
@@ -117,7 +132,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
117132/// limit access to provenance outside of the `Allocation` abstraction. 
118133/// 
119134pub  fn  range_empty ( & self ,  range :  AllocRange ,  cx :  & impl  HasDataLayout )  -> bool  { 
120-         self . range_get_ptrs ( range,  cx) . is_empty ( )  && self . range_get_bytes ( range) . is_empty ( ) 
135+         self . range_get_ptrs_is_empty ( range,  cx)  && self . range_get_bytes ( range) . is_empty ( ) 
121136    } 
122137
123138    /// Yields all the provenances stored in this map. 
@@ -149,12 +164,14 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
149164        // provenance that overlaps with the given range. 
150165        let  ( first,  last)  = { 
151166            // Find all provenance overlapping the given range. 
152-             let  provenance = self . range_get_ptrs ( range,  cx) ; 
153-             if  provenance. is_empty ( )  { 
154-                 // No provenance in this range, we are done. 
167+             if  self . range_get_ptrs_is_empty ( range,  cx)  { 
168+                 // No provenance in this range, we are done. This is the common case. 
155169                return  Ok ( ( ) ) ; 
156170            } 
157171
172+             // This redoes some of the work of `range_get_ptrs_is_empty`, but this path is much 
173+             // colder than the early return above, so it's worth it. 
174+             let  provenance = self . range_get_ptrs ( range,  cx) ; 
158175            ( 
159176                provenance. first ( ) . unwrap ( ) . 0 , 
160177                provenance. last ( ) . unwrap ( ) . 0  + cx. data_layout ( ) . pointer_size , 
0 commit comments