Skip to content

Commit f0e5545

Browse files
committed
another attempt at performance improvements
1 parent 2c15b3c commit f0e5545

File tree

1 file changed

+26
-23
lines changed

1 file changed

+26
-23
lines changed

compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs

+26-23
Original file line numberDiff line numberDiff line change
@@ -191,27 +191,24 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
191191
// # Pointer-sized provenances
192192
// Get the provenances that are entirely within this range.
193193
// (Different from `range_get_ptrs` which asks if they overlap the range.)
194-
let ptrs = if src.size < ptr_size {
195-
// This isn't even large enough to contain a pointer.
196-
&[]
197-
} else {
198-
let adjusted_end =
199-
Size::from_bytes(src.end().bytes().saturating_sub(ptr_size.bytes() - 1));
200-
self.ptrs.range(src.start..adjusted_end)
194+
// Only makes sense if we are copying at least one pointer worth of bytes.
195+
let mut dest_ptrs = Vec::new();
196+
if src.size >= ptr_size {
197+
let adjusted_end = Size::from_bytes(src.end().bytes() - (ptr_size.bytes() - 1));
198+
let ptrs = self.ptrs.range(src.start..adjusted_end);
199+
dest_ptrs.reserve_exact(ptrs.len() * (count as usize));
200+
// If `count` is large, this is rather wasteful -- we are allocating a big array here, which
201+
// is mostly filled with redundant information since it's just N copies of the same `Prov`s
202+
// at slightly adjusted offsets. The reason we do this is so that in `mark_provenance_range`
203+
// we can use `insert_presorted`. That wouldn't work with an `Iterator` that just produces
204+
// the right sequence of provenance for all N copies.
205+
// Basically, this large array would have to be created anyway in the target allocation.
206+
for i in 0..count {
207+
dest_ptrs
208+
.extend(ptrs.iter().map(|&(offset, reloc)| (shift_offset(i, offset), reloc)));
209+
}
201210
};
202211

203-
// Buffer for the new list.
204-
let mut dest_ptrs = Vec::with_capacity(ptrs.len() * (count as usize));
205-
// If `count` is large, this is rather wasteful -- we are allocating a big array here, which
206-
// is mostly filled with redundant information since it's just N copies of the same `Prov`s
207-
// at slightly adjusted offsets. The reason we do this is so that in `mark_provenance_range`
208-
// we can use `insert_presorted`. That wouldn't work with an `Iterator` that just produces
209-
// the right sequence of provenance for all N copies.
210-
// Basically, this large array would have to be created anyway in the target allocation.
211-
for i in 0..count {
212-
dest_ptrs.extend(ptrs.iter().map(|&(offset, reloc)| (shift_offset(i, offset), reloc)));
213-
}
214-
215212
// # Byte-sized provenances
216213
let mut bytes = Vec::new();
217214
// First, if there is a part of a pointer at the start, add that.
@@ -261,10 +258,16 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
261258
trace!("byte provenances: {bytes:?}");
262259

263260
// And again a buffer for the new list on the target side.
264-
let mut dest_bytes = Vec::with_capacity(bytes.len() * (count as usize));
265-
for i in 0..count {
266-
dest_bytes
267-
.extend(bytes.iter().map(|&(offset, reloc)| (shift_offset(i, offset), reloc)));
261+
let mut dest_bytes = Vec::new();
262+
if Prov::OFFSET_IS_ADDR {
263+
dest_bytes.reserve_exact(bytes.len() * (count as usize));
264+
for i in 0..count {
265+
dest_bytes
266+
.extend(bytes.iter().map(|&(offset, reloc)| (shift_offset(i, offset), reloc)));
267+
}
268+
} else {
269+
// There can't be any bytewise provenance when OFFSET_IS_ADDR is false.
270+
debug_assert!(bytes.is_empty());
268271
}
269272

270273
Ok(ProvenanceCopy { dest_ptrs, dest_bytes })

0 commit comments

Comments
 (0)