Get rid of literal_alloc_cache

This commit is contained in:
John Kåre Alsaker 2018-05-01 12:18:53 +02:00
parent 56e541ddf1
commit aace842a08
6 changed files with 63 additions and 28 deletions

View File

@ -960,10 +960,6 @@ struct InterpretInternerInner<'tcx> {
/// Inverse map of `statics`
/// Used so we don't allocate a new pointer every time we need one
static_cache: FxHashMap<DefId, interpret::AllocId>,
/// A cache for basic byte allocations keyed by their contents. This is used to deduplicate
/// allocations for string and bytestring literals.
literal_alloc_cache: FxHashMap<Vec<u8>, interpret::AllocId>,
}
impl<'tcx> InterpretInterner<'tcx> {
@ -1123,22 +1119,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
/// Allocates a byte or string literal for `mir::interpret`
pub fn allocate_cached(self, bytes: &[u8]) -> interpret::AllocId {
// check whether we already allocated this literal or a constant with the same memory
if let Some(&alloc_id) = self.interpret_interner.inner.borrow()
.literal_alloc_cache.get(bytes) {
return alloc_id;
}
pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId {
// create an allocation that just contains these bytes
let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes);
let alloc = self.intern_const_alloc(alloc);
// the next unique id
let id = self.interpret_interner.reserve();
// make the allocation identifiable
self.interpret_interner.inner.borrow_mut().alloc_by_id.insert(id, alloc);
// cache it for the future
self.interpret_interner.inner.borrow_mut().literal_alloc_cache.insert(bytes.to_owned(), id);
self.interpret_interner.intern_at_reserved(id, alloc);
id
}

View File

@ -1860,6 +1860,14 @@ impl<'tcx> Const<'tcx> {
}
}
#[inline]
pub fn to_byval_value(&self) -> Option<Value> {
match self.val {
ConstVal::Value(val) => val.to_byval_value(),
_ => None,
}
}
#[inline]
pub fn to_primval(&self) -> Option<PrimVal> {
match self.val {

View File

@ -181,7 +181,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
let lit = match *lit {
LitKind::Str(ref s, _) => {
let s = s.as_str();
let id = self.tcx.allocate_cached(s.as_bytes());
let id = self.tcx.allocate_bytes(s.as_bytes());
let ptr = MemoryPointer::new(id, Size::from_bytes(0));
ConstValue::ByValPair(
PrimVal::Ptr(ptr),
@ -189,7 +189,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
)
},
LitKind::ByteStr(ref data) => {
let id = self.tcx.allocate_cached(data);
let id = self.tcx.allocate_bytes(data);
let ptr = MemoryPointer::new(id, Size::from_bytes(0));
ConstValue::ByVal(PrimVal::Ptr(ptr))
},

View File

@ -20,7 +20,7 @@ use interpret::{const_val_field, const_variant_index, self};
use rustc::middle::const_val::ConstVal;
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
use rustc::mir::interpret::{PrimVal, GlobalId, ConstValue};
use rustc::mir::interpret::{PrimVal, GlobalId, ConstValue, Value};
use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
use rustc::ty::layout::Size;
use rustc::ty::subst::{Substs, Kind};
@ -1040,11 +1040,27 @@ pub fn compare_const_vals<'a, 'tcx>(
ty: Ty<'tcx>,
) -> Option<Ordering> {
trace!("compare_const_vals: {:?}, {:?}", a, b);
let from_bool = |v: bool| {
if v {
Some(Ordering::Equal)
} else {
None
}
};
let fallback = || from_bool(a == b);
// Use the fallback if any type differs
if a.ty != b.ty || a.ty != ty {
return fallback();
}
// FIXME: This should use assert_bits(ty) instead of use_bits
// but triggers possibly bugs due to mismatching of arrays and slices
if let (Some(a), Some(b)) = (a.to_bits(ty), b.to_bits(ty)) {
use ::rustc_apfloat::Float;
match ty.sty {
return match ty.sty {
ty::TyFloat(ast::FloatTy::F32) => {
let l = ::rustc_apfloat::ieee::Single::from_bits(a);
let r = ::rustc_apfloat::ieee::Single::from_bits(b);
@ -1062,13 +1078,36 @@ pub fn compare_const_vals<'a, 'tcx>(
},
_ => Some(a.cmp(&b)),
}
} else {
if a == b {
Some(Ordering::Equal)
} else {
None
}
if let ty::TyRef(_, rty, _) = ty.sty {
if let ty::TyStr = rty.sty {
match (a.to_byval_value(), b.to_byval_value()) {
(
Some(Value::ByValPair(
PrimVal::Ptr(ptr_a),
PrimVal::Bytes(size_a))
),
Some(Value::ByValPair(
PrimVal::Ptr(ptr_b),
PrimVal::Bytes(size_b))
)
) if size_a == size_b => {
if ptr_a.offset == Size::from_bytes(0) && ptr_b.offset == Size::from_bytes(0) {
let map = tcx.alloc_map.lock();
let alloc_a = map.unwrap_memory(ptr_a.alloc_id);
let alloc_b = map.unwrap_memory(ptr_b.alloc_id);
if alloc_a.bytes.len() as u64 == size_a as u64 {
return from_bool(alloc_a == alloc_b);
}
}
}
_ => (),
}
}
}
fallback()
}
// FIXME: Combine with rustc_mir::hair::cx::const_eval_literal
@ -1083,7 +1122,7 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
let lit = match *lit {
LitKind::Str(ref s, _) => {
let s = s.as_str();
let id = tcx.allocate_cached(s.as_bytes());
let id = tcx.allocate_bytes(s.as_bytes());
let ptr = MemoryPointer::new(id, Size::from_bytes(0));
ConstValue::ByValPair(
PrimVal::Ptr(ptr),
@ -1091,7 +1130,7 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
)
},
LitKind::ByteStr(ref data) => {
let id = tcx.allocate_cached(data);
let id = tcx.allocate_bytes(data);
let ptr = MemoryPointer::new(id, Size::from_bytes(0));
ConstValue::ByVal(PrimVal::Ptr(ptr))
},

View File

@ -229,7 +229,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
}
pub fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> {
let ptr = self.memory.allocate_cached(s.as_bytes());
let ptr = self.memory.allocate_bytes(s.as_bytes());
Ok(Value::ByValPair(
PrimVal::Ptr(ptr),
PrimVal::from_u128(s.len() as u128),

View File

@ -76,8 +76,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
MemoryPointer::new(id, Size::from_bytes(0))
}
pub fn allocate_cached(&mut self, bytes: &[u8]) -> MemoryPointer {
let id = self.tcx.allocate_cached(bytes);
pub fn allocate_bytes(&mut self, bytes: &[u8]) -> MemoryPointer {
let id = self.tcx.allocate_bytes(bytes);
MemoryPointer::new(id, Size::from_bytes(0))
}