Skip to content

Commit 3ed23a4

Browse files
Use SortedMap instead of BTreeMap for relocations in MIRI.
1 parent 879eb97 commit 3ed23a4

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,9 +20,11 @@ use ty::layout::{self, Align, HasDataLayout, Size};
2120
use middle::region;
2221
use std::iter;
2322
use std::io;
23+
use std::ops::{Deref, DerefMut};
2424
use std::hash::Hash;
2525
use syntax::ast::Mutability;
2626
use rustc_serialize::{Encoder, Decoder, Decodable, Encodable};
27+
use rustc_data_structures::sorted_map::SortedMap;
2728
use rustc_data_structures::fx::FxHashMap;
2829
use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian, BigEndian};
2930

@@ -341,7 +342,7 @@ pub struct Allocation {
341342
pub bytes: Vec<u8>,
342343
/// Maps from byte addresses to allocations.
343344
/// Only the first byte of a pointer is inserted into the map.
344-
pub relocations: BTreeMap<Size, AllocId>,
345+
pub relocations: Relocations,
345346
/// Denotes undefined memory. Reading from undefined memory is forbidden in miri
346347
pub undef_mask: UndefMask,
347348
/// The alignment of the allocation to detect unaligned reads.
@@ -358,7 +359,7 @@ impl Allocation {
358359
undef_mask.grow(Size::from_bytes(slice.len() as u64), true);
359360
Self {
360361
bytes: slice.to_owned(),
361-
relocations: BTreeMap::new(),
362+
relocations: Relocations::new(),
362363
undef_mask,
363364
align,
364365
runtime_mutability: Mutability::Immutable,
@@ -373,7 +374,7 @@ impl Allocation {
373374
assert_eq!(size.bytes() as usize as u64, size.bytes());
374375
Allocation {
375376
bytes: vec![0; size.bytes() as usize],
376-
relocations: BTreeMap::new(),
377+
relocations: Relocations::new(),
377378
undef_mask: UndefMask::new(size),
378379
align,
379380
runtime_mutability: Mutability::Immutable,
@@ -383,6 +384,35 @@ impl Allocation {
383384

384385
impl<'tcx> ::serialize::UseSpecializedDecodable for &'tcx Allocation {}
385386

387+
#[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
388+
pub struct Relocations(SortedMap<Size, AllocId>);
389+
390+
impl Relocations {
391+
pub fn new() -> Relocations {
392+
Relocations(SortedMap::new())
393+
}
394+
395+
// The caller must guarantee that the given relocations are already sorted
396+
// by address and contain no duplicates.
397+
pub fn from_presorted(r: Vec<(Size, AllocId)>) -> Relocations {
398+
Relocations(SortedMap::from_presorted_elements(r))
399+
}
400+
}
401+
402+
impl Deref for Relocations {
403+
type Target = SortedMap<Size, AllocId>;
404+
405+
fn deref(&self) -> &Self::Target {
406+
&self.0
407+
}
408+
}
409+
410+
impl DerefMut for Relocations {
411+
fn deref_mut(&mut self) -> &mut Self::Target {
412+
&mut self.0
413+
}
414+
}
415+
386416
////////////////////////////////////////////////////////////////////////////////
387417
// Methods to access integers in the target endianness
388418
////////////////////////////////////////////////////////////////////////////////

src/librustc_codegen_llvm/mir/constant.rs

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

8585
let mut next_offset = 0;
86-
for (&offset, &alloc_id) in &alloc.relocations {
86+
for &(offset, alloc_id) in alloc.relocations.iter() {
8787
let offset = offset.bytes();
8888
assert_eq!(offset as usize as u64, offset);
8989
let offset = offset as usize;

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;
@@ -519,7 +519,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
519519

520520
fn get_bytes(&self, ptr: MemoryPointer, size: Size, align: Align) -> EvalResult<'tcx, &[u8]> {
521521
assert_ne!(size.bytes(), 0);
522-
if self.relocations(ptr, size)?.count() != 0 {
522+
if self.relocations(ptr, size)?.len() != 0 {
523523
return err!(ReadPointerAsBytes);
524524
}
525525
self.check_defined(ptr, size)?;
@@ -614,9 +614,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
614614
// first copy the relocations to a temporary buffer, because
615615
// `get_bytes_mut` will clear the relocations, which is correct,
616616
// since we don't want to keep any relocations at the target.
617-
618617
let relocations: Vec<_> = self.relocations(src, size)?
619-
.map(|(&offset, &alloc_id)| {
618+
.iter()
619+
.map(|&(offset, alloc_id)| {
620620
// Update relocation offsets for the new positions in the destination allocation.
621621
(offset + dest.offset - src.offset, alloc_id)
622622
})
@@ -648,7 +648,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
648648

649649
self.copy_undef_mask(src, dest, size)?;
650650
// copy back the relocations
651-
self.get_mut(dest.alloc_id)?.relocations.extend(relocations);
651+
self.get_mut(dest.alloc_id)?.relocations.insert_presorted(relocations);
652652

653653
Ok(())
654654
}
@@ -660,7 +660,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
660660
match alloc.bytes[offset..].iter().position(|&c| c == 0) {
661661
Some(size) => {
662662
let p1 = Size::from_bytes((size + 1) as u64);
663-
if self.relocations(ptr, p1)?.count() != 0 {
663+
if self.relocations(ptr, p1)?.len() != 0 {
664664
return err!(ReadPointerAsBytes);
665665
}
666666
self.check_defined(ptr, p1)?;
@@ -720,7 +720,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
720720
let bytes = read_target_uint(endianness, bytes).unwrap();
721721
// See if we got a pointer
722722
if size != self.pointer_size() {
723-
if self.relocations(ptr, size)?.count() != 0 {
723+
if self.relocations(ptr, size)?.len() != 0 {
724724
return err!(ReadPointerAsBytes);
725725
}
726726
} else {
@@ -808,24 +808,26 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
808808
&self,
809809
ptr: MemoryPointer,
810810
size: Size,
811-
) -> EvalResult<'tcx, btree_map::Range<Size, AllocId>> {
811+
) -> EvalResult<'tcx, &[(Size, AllocId)]> {
812812
let start = ptr.offset.bytes().saturating_sub(self.pointer_size().bytes() - 1);
813813
let end = ptr.offset + size;
814814
Ok(self.get(ptr.alloc_id)?.relocations.range(Size::from_bytes(start)..end))
815815
}
816816

817817
fn clear_relocations(&mut self, ptr: MemoryPointer, size: Size) -> EvalResult<'tcx> {
818-
// Find all relocations overlapping the given range.
819-
let keys: Vec<_> = self.relocations(ptr, size)?.map(|(&k, _)| k).collect();
820-
if keys.is_empty() {
821-
return Ok(());
822-
}
823-
824818
// Find the start and end of the given range and its outermost relocations.
819+
let (first, last) = {
820+
// Find all relocations overlapping the given range.
821+
let relocations = self.relocations(ptr, size)?;
822+
if relocations.is_empty() {
823+
return Ok(());
824+
}
825+
826+
(relocations.first().unwrap().0,
827+
relocations.last().unwrap().0 + self.pointer_size())
828+
};
825829
let start = ptr.offset;
826830
let end = start + size;
827-
let first = *keys.first().unwrap();
828-
let last = *keys.last().unwrap() + self.pointer_size();
829831

830832
let alloc = self.get_mut(ptr.alloc_id)?;
831833

@@ -839,16 +841,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
839841
}
840842

841843
// Forget all the relocations.
842-
for k in keys {
843-
alloc.relocations.remove(&k);
844-
}
844+
alloc.relocations.remove_range(first ..= last);
845845

846846
Ok(())
847847
}
848848

849849
fn check_relocation_edges(&self, ptr: MemoryPointer, size: Size) -> EvalResult<'tcx> {
850-
let overlapping_start = self.relocations(ptr, Size::from_bytes(0))?.count();
851-
let overlapping_end = self.relocations(ptr.offset(size, self)?, Size::from_bytes(0))?.count();
850+
let overlapping_start = self.relocations(ptr, Size::from_bytes(0))?.len();
851+
let overlapping_end = self.relocations(ptr.offset(size, self)?, Size::from_bytes(0))?.len();
852852
if overlapping_start + overlapping_end != 0 {
853853
return err!(ReadPointerAsBytes);
854854
}

0 commit comments

Comments
 (0)