Replace usage of alloc.bytes in interpret

There is now a dedicate `len` method which avoids the need to access the
bytes. Access the length as `Size` can also be done by a direct member.
The constructors guarantee that these representations are convertable.

Access which relies on the bytes, such as snapshot, can use direct raw
access by reference as it does not care about undef and relocations or
properly checks them seperately.
This commit is contained in:
Andreas Molzer 2019-07-30 23:10:51 +02:00
parent 98cff69289
commit d8c5bc7ec6
5 changed files with 37 additions and 14 deletions

View File

@ -13,6 +13,8 @@ use rustc_data_structures::sorted_map::SortedMap;
use rustc_target::abi::HasDataLayout;
use std::borrow::Cow;
// NOTE: When adding new fields, make sure to adjust the Snapshot impl in
// `src/librustc_mir/interpret/snapshot.rs`.
#[derive(
Clone,
Debug,

View File

@ -81,7 +81,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let alloc = alloc_type_name(self.tcx.tcx, substs.type_at(0));
let name_id = self.tcx.alloc_map.lock().create_memory_alloc(alloc);
let id_ptr = self.memory.tag_static_base_pointer(name_id.into());
let alloc_len = alloc.bytes.len() as u64;
let alloc_len = alloc.size.bytes();
let name_val = Immediate::new_slice(Scalar::Ptr(id_ptr), alloc_len, self);
self.write_immediate(name_val, dest)?;
}

View File

@ -221,7 +221,7 @@ pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx>
val: ConstValue::Slice {
data: alloc,
start: 0,
end: alloc.bytes.len(),
end: alloc.len(),
},
ty: tcx.mk_static_str(),
})

View File

@ -210,7 +210,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
let new_ptr = self.allocate(new_size, new_align, kind);
let old_size = match old_size_and_align {
Some((size, _align)) => size,
None => Size::from_bytes(self.get(ptr.alloc_id)?.bytes.len() as u64),
None => self.get(ptr.alloc_id)?.size,
};
self.copy(
ptr,
@ -271,20 +271,20 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
))
}
if let Some((size, align)) = old_size_and_align {
if size.bytes() != alloc.bytes.len() as u64 || align != alloc.align {
let bytes = Size::from_bytes(alloc.bytes.len() as u64);
if size != alloc.size || align != alloc.align {
let bytes = alloc.size;
throw_unsup!(IncorrectAllocationInformation(size, bytes, align, alloc.align))
}
}
// Let the machine take some extra action
let size = Size::from_bytes(alloc.bytes.len() as u64);
let size = alloc.size;
AllocationExtra::memory_deallocated(&mut alloc, ptr, size)?;
// Don't forget to remember size and align of this now-dead allocation
let old = self.dead_alloc_map.insert(
ptr.alloc_id,
(Size::from_bytes(alloc.bytes.len() as u64), alloc.align)
(alloc.size, alloc.align)
);
if old.is_some() {
bug!("Nothing can be deallocated twice");
@ -555,7 +555,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
// a) cause cycles in case `id` refers to a static
// b) duplicate a static's allocation in miri
if let Some((_, alloc)) = self.alloc_map.get(id) {
return Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align));
return Ok((alloc.size, alloc.align));
}
// # Function pointers
@ -583,7 +583,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
Some(GlobalAlloc::Memory(alloc)) =>
// Need to duplicate the logic here, because the global allocations have
// different associated types than the interpreter-local ones.
Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)),
Ok((alloc.size, alloc.align)),
Some(GlobalAlloc::Function(_)) =>
bug!("We already checked function pointers above"),
// The rest must be dead.
@ -645,7 +645,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
let prefix_len = msg.len();
let mut relocations = vec![];
for i in 0..(alloc.bytes.len() as u64) {
for i in 0..alloc.size.bytes() {
let i = Size::from_bytes(i);
if let Some(&(_, target_id)) = alloc.relocations.get(&i) {
if allocs_seen.insert(target_id) {
@ -655,7 +655,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
}
if alloc.undef_mask.is_range_defined(i, i + Size::from_bytes(1)).is_ok() {
// this `as usize` is fine, since `i` came from a `usize`
write!(msg, "{:02x} ", alloc.bytes[i.bytes() as usize]).unwrap();
let i = i.bytes() as usize;
// Checked definedness (and thus range) and relocations. This access also doesn't
// influence interpreter execution but is only for debugging.
let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(i..i+1);
write!(msg, "{:02x} ", bytes[0]).unwrap();
} else {
msg.push_str("__ ");
}
@ -664,7 +669,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
trace!(
"{}({} bytes, alignment {}){}",
msg,
alloc.bytes.len(),
alloc.size.bytes(),
alloc.align.bytes(),
extra
);

View File

@ -15,7 +15,7 @@ use rustc::mir::interpret::{
};
use rustc::ty::{self, TyCtxt};
use rustc::ty::layout::Align;
use rustc::ty::layout::{Align, Size};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@ -276,6 +276,7 @@ struct AllocationSnapshot<'a> {
relocations: Relocations<(), AllocIdSnapshot<'a>>,
undef_mask: &'a UndefMask,
align: &'a Align,
size: &'a Size,
mutability: &'a Mutability,
}
@ -285,12 +286,27 @@ impl<'a, Ctx> Snapshot<'a, Ctx> for &'a Allocation
type Item = AllocationSnapshot<'a>;
fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
let Allocation { bytes, relocations, undef_mask, align, mutability, extra: () } = self;
let Allocation {
relocations,
size,
align,
mutability,
extra: (),
..
} = self;
let all_bytes = 0..self.len();
// This 'inspect' is okay since following access respects undef and relocations. This does
// influence interpreter exeuction, but only to detect the error of cycles in evalution
// dependencies.
let bytes = self.inspect_with_undef_and_ptr_outside_interpreter(all_bytes);
let undef_mask = self.undef_mask();
AllocationSnapshot {
bytes,
undef_mask,
align,
size,
mutability,
relocations: relocations.snapshot(ctx),
}