Skip to content

Commit 34b4f03

Browse files
Use SortedMap instead of BTreeMap for relocations in MIRI.
1 parent cd44d47 commit 34b4f03

File tree

3 files changed

+56
-26
lines changed

3 files changed

+56
-26
lines changed

src/librustc/mir/interpret/mod.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ pub use self::error::{EvalError, EvalResult, EvalErrorKind, AssertMessage};
1212

1313
pub use self::value::{PrimVal, PrimValKind, Value, Pointer, ConstValue};
1414

15-
use std::collections::BTreeMap;
1615
use std::fmt;
1716
use mir;
1817
use hir::def_id::DefId;
@@ -21,8 +20,10 @@ use ty::layout::{self, Align, HasDataLayout};
2120
use middle::region;
2221
use std::iter;
2322
use std::io;
23+
use std::ops::{Deref, DerefMut};
2424
use syntax::ast::Mutability;
2525
use rustc_serialize::{Encoder, Decoder, Decodable, Encodable};
26+
use rustc_data_structures::sorted_map::SortedMap;
2627
use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian, BigEndian};
2728

2829
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
@@ -244,7 +245,7 @@ pub struct Allocation {
244245
pub bytes: Vec<u8>,
245246
/// Maps from byte addresses to allocations.
246247
/// Only the first byte of a pointer is inserted into the map.
247-
pub relocations: BTreeMap<u64, AllocId>,
248+
pub relocations: Relocations,
248249
/// Denotes undefined memory. Reading from undefined memory is forbidden in miri
249250
pub undef_mask: UndefMask,
250251
/// The alignment of the allocation to detect unaligned reads.
@@ -261,7 +262,7 @@ impl Allocation {
261262
undef_mask.grow(slice.len() as u64, true);
262263
Self {
263264
bytes: slice.to_owned(),
264-
relocations: BTreeMap::new(),
265+
relocations: Relocations::new(),
265266
undef_mask,
266267
align,
267268
runtime_mutability: Mutability::Immutable,
@@ -276,7 +277,7 @@ impl Allocation {
276277
assert_eq!(size as usize as u64, size);
277278
Allocation {
278279
bytes: vec![0; size as usize],
279-
relocations: BTreeMap::new(),
280+
relocations: Relocations::new(),
280281
undef_mask: UndefMask::new(size),
281282
align,
282283
runtime_mutability: Mutability::Immutable,
@@ -286,6 +287,35 @@ impl Allocation {
286287

287288
impl<'tcx> ::serialize::UseSpecializedDecodable for &'tcx Allocation {}
288289

290+
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
291+
pub struct Relocations(SortedMap<u64, AllocId>);
292+
293+
impl Relocations {
294+
pub fn new() -> Relocations {
295+
Relocations(SortedMap::new())
296+
}
297+
298+
// The caller must guarantee that the given relocations are already sorted
299+
// by address and contain no duplicates.
300+
pub fn from_presorted(r: Vec<(u64, AllocId)>) -> Relocations {
301+
Relocations(SortedMap::from_presorted_elements(r))
302+
}
303+
}
304+
305+
impl Deref for Relocations {
306+
type Target = SortedMap<u64, AllocId>;
307+
308+
fn deref(&self) -> &Self::Target {
309+
&self.0
310+
}
311+
}
312+
313+
impl DerefMut for Relocations {
314+
fn deref_mut(&mut self) -> &mut Self::Target {
315+
&mut self.0
316+
}
317+
}
318+
289319
////////////////////////////////////////////////////////////////////////////////
290320
// Methods to access integers in the target endianness
291321
////////////////////////////////////////////////////////////////////////////////

src/librustc_codegen_llvm/mir/constant.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef {
130130
let pointer_size = layout.pointer_size.bytes() as usize;
131131

132132
let mut next_offset = 0;
133-
for (&offset, &alloc_id) in &alloc.relocations {
133+
for &(offset, alloc_id) in alloc.relocations.iter() {
134134
assert_eq!(offset as usize as u64, offset);
135135
let offset = offset as usize;
136136
if offset > next_offset {

src/librustc_mir/interpret/memory.rs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::{btree_map, VecDeque};
1+
use std::collections::VecDeque;
22
use std::ptr;
33

44
use rustc::hir::def_id::DefId;
@@ -515,7 +515,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
515515

516516
fn get_bytes(&self, ptr: MemoryPointer, size: u64, align: Align) -> EvalResult<'tcx, &[u8]> {
517517
assert_ne!(size, 0);
518-
if self.relocations(ptr, size)?.count() != 0 {
518+
if self.relocations(ptr, size)?.len() != 0 {
519519
return err!(ReadPointerAsBytes);
520520
}
521521
self.check_defined(ptr, size)?;
@@ -610,9 +610,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
610610
// first copy the relocations to a temporary buffer, because
611611
// `get_bytes_mut` will clear the relocations, which is correct,
612612
// since we don't want to keep any relocations at the target.
613-
614613
let relocations: Vec<_> = self.relocations(src, size)?
615-
.map(|(&offset, &alloc_id)| {
614+
.iter()
615+
.map(|&(offset, alloc_id)| {
616616
// Update relocation offsets for the new positions in the destination allocation.
617617
(offset + dest.offset - src.offset, alloc_id)
618618
})
@@ -644,7 +644,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
644644

645645
self.copy_undef_mask(src, dest, size)?;
646646
// copy back the relocations
647-
self.get_mut(dest.alloc_id)?.relocations.extend(relocations);
647+
self.get_mut(dest.alloc_id)?.relocations.insert_presorted(relocations);
648648

649649
Ok(())
650650
}
@@ -655,7 +655,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
655655
let offset = ptr.offset as usize;
656656
match alloc.bytes[offset..].iter().position(|&c| c == 0) {
657657
Some(size) => {
658-
if self.relocations(ptr, (size + 1) as u64)?.count() != 0 {
658+
if self.relocations(ptr, (size + 1) as u64)?.len() != 0 {
659659
return err!(ReadPointerAsBytes);
660660
}
661661
self.check_defined(ptr, (size + 1) as u64)?;
@@ -715,7 +715,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
715715
let bytes = read_target_uint(endianness, bytes).unwrap();
716716
// See if we got a pointer
717717
if size != self.pointer_size() {
718-
if self.relocations(ptr, size)?.count() != 0 {
718+
if self.relocations(ptr, size)?.len() != 0 {
719719
return err!(ReadPointerAsBytes);
720720
}
721721
} else {
@@ -803,24 +803,26 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
803803
&self,
804804
ptr: MemoryPointer,
805805
size: u64,
806-
) -> EvalResult<'tcx, btree_map::Range<u64, AllocId>> {
806+
) -> EvalResult<'tcx, &[(u64, AllocId)]> {
807807
let start = ptr.offset.saturating_sub(self.pointer_size() - 1);
808808
let end = ptr.offset + size;
809809
Ok(self.get(ptr.alloc_id)?.relocations.range(start..end))
810810
}
811811

812812
fn clear_relocations(&mut self, ptr: MemoryPointer, size: u64) -> EvalResult<'tcx> {
813-
// Find all relocations overlapping the given range.
814-
let keys: Vec<_> = self.relocations(ptr, size)?.map(|(&k, _)| k).collect();
815-
if keys.is_empty() {
816-
return Ok(());
817-
}
818-
819813
// Find the start and end of the given range and its outermost relocations.
814+
let (first, last) = {
815+
// Find all relocations overlapping the given range.
816+
let relocations = self.relocations(ptr, size)?;
817+
if relocations.is_empty() {
818+
return Ok(());
819+
}
820+
821+
(relocations.first().unwrap().0,
822+
relocations.last().unwrap().0 + self.pointer_size())
823+
};
820824
let start = ptr.offset;
821825
let end = start + size;
822-
let first = *keys.first().unwrap();
823-
let last = *keys.last().unwrap() + self.pointer_size();
824826

825827
let alloc = self.get_mut(ptr.alloc_id)?;
826828

@@ -834,16 +836,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
834836
}
835837

836838
// Forget all the relocations.
837-
for k in keys {
838-
alloc.relocations.remove(&k);
839-
}
839+
alloc.relocations.remove_range(first ..= last);
840840

841841
Ok(())
842842
}
843843

844844
fn check_relocation_edges(&self, ptr: MemoryPointer, size: u64) -> EvalResult<'tcx> {
845-
let overlapping_start = self.relocations(ptr, 0)?.count();
846-
let overlapping_end = self.relocations(ptr.offset(size, self)?, 0)?.count();
845+
let overlapping_start = self.relocations(ptr, 0)?.len();
846+
let overlapping_end = self.relocations(ptr.offset(size, self)?, 0)?.len();
847847
if overlapping_start + overlapping_end != 0 {
848848
return err!(ReadPointerAsBytes);
849849
}

0 commit comments

Comments
 (0)