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 ///
119134 pub 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