2
2
//! representation for the common case where PTR_SIZE consecutive bytes have the same provenance.
3
3
4
4
use std:: cmp;
5
+ use std:: ops:: Range ;
5
6
6
7
use rustc_abi:: { HasDataLayout , Size } ;
7
8
use rustc_data_structures:: sorted_map:: SortedMap ;
@@ -66,6 +67,15 @@ impl ProvenanceMap {
66
67
}
67
68
68
69
impl < 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
+
69
79
/// Returns all ptr-sized provenance in the given range.
70
80
/// If the range has length 0, returns provenance that crosses the edge between `start-1` and
71
81
/// `start`.
@@ -74,12 +84,17 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
74
84
range : AllocRange ,
75
85
cx : & impl HasDataLayout ,
76
86
) -> & [ ( 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) )
83
98
}
84
99
85
100
/// Returns all byte-wise provenance in the given range.
@@ -117,7 +132,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
117
132
/// limit access to provenance outside of the `Allocation` abstraction.
118
133
///
119
134
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 ( )
121
136
}
122
137
123
138
/// Yields all the provenances stored in this map.
@@ -149,12 +164,14 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
149
164
// provenance that overlaps with the given range.
150
165
let ( first, last) = {
151
166
// 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.
155
169
return Ok ( ( ) ) ;
156
170
}
157
171
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) ;
158
175
(
159
176
provenance. first ( ) . unwrap ( ) . 0 ,
160
177
provenance. last ( ) . unwrap ( ) . 0 + cx. data_layout ( ) . pointer_size ,
0 commit comments