Get rid of literal_alloc_cache
This commit is contained in:
parent
56e541ddf1
commit
aace842a08
6 changed files with 63 additions and 28 deletions
|
@ -960,10 +960,6 @@ struct InterpretInternerInner<'tcx> {
|
||||||
/// Inverse map of `statics`
|
/// Inverse map of `statics`
|
||||||
/// Used so we don't allocate a new pointer every time we need one
|
/// Used so we don't allocate a new pointer every time we need one
|
||||||
static_cache: FxHashMap<DefId, interpret::AllocId>,
|
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> {
|
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`
|
/// Allocates a byte or string literal for `mir::interpret`
|
||||||
pub fn allocate_cached(self, bytes: &[u8]) -> interpret::AllocId {
|
pub fn allocate_bytes(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;
|
|
||||||
}
|
|
||||||
// create an allocation that just contains these bytes
|
// create an allocation that just contains these bytes
|
||||||
let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes);
|
let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes);
|
||||||
let alloc = self.intern_const_alloc(alloc);
|
let alloc = self.intern_const_alloc(alloc);
|
||||||
|
|
||||||
// the next unique id
|
// the next unique id
|
||||||
let id = self.interpret_interner.reserve();
|
let id = self.interpret_interner.reserve();
|
||||||
// make the allocation identifiable
|
self.interpret_interner.intern_at_reserved(id, alloc);
|
||||||
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);
|
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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]
|
#[inline]
|
||||||
pub fn to_primval(&self) -> Option<PrimVal> {
|
pub fn to_primval(&self) -> Option<PrimVal> {
|
||||||
match self.val {
|
match self.val {
|
||||||
|
|
|
@ -181,7 +181,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||||
let lit = match *lit {
|
let lit = match *lit {
|
||||||
LitKind::Str(ref s, _) => {
|
LitKind::Str(ref s, _) => {
|
||||||
let s = s.as_str();
|
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));
|
let ptr = MemoryPointer::new(id, Size::from_bytes(0));
|
||||||
ConstValue::ByValPair(
|
ConstValue::ByValPair(
|
||||||
PrimVal::Ptr(ptr),
|
PrimVal::Ptr(ptr),
|
||||||
|
@ -189,7 +189,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
LitKind::ByteStr(ref data) => {
|
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));
|
let ptr = MemoryPointer::new(id, Size::from_bytes(0));
|
||||||
ConstValue::ByVal(PrimVal::Ptr(ptr))
|
ConstValue::ByVal(PrimVal::Ptr(ptr))
|
||||||
},
|
},
|
||||||
|
|
|
@ -20,7 +20,7 @@ use interpret::{const_val_field, const_variant_index, self};
|
||||||
|
|
||||||
use rustc::middle::const_val::ConstVal;
|
use rustc::middle::const_val::ConstVal;
|
||||||
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
|
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::{self, TyCtxt, AdtDef, Ty, Region};
|
||||||
use rustc::ty::layout::Size;
|
use rustc::ty::layout::Size;
|
||||||
use rustc::ty::subst::{Substs, Kind};
|
use rustc::ty::subst::{Substs, Kind};
|
||||||
|
@ -1040,11 +1040,27 @@ pub fn compare_const_vals<'a, 'tcx>(
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
) -> Option<Ordering> {
|
) -> Option<Ordering> {
|
||||||
trace!("compare_const_vals: {:?}, {:?}", a, b);
|
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
|
// FIXME: This should use assert_bits(ty) instead of use_bits
|
||||||
// but triggers possibly bugs due to mismatching of arrays and slices
|
// 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)) {
|
if let (Some(a), Some(b)) = (a.to_bits(ty), b.to_bits(ty)) {
|
||||||
use ::rustc_apfloat::Float;
|
use ::rustc_apfloat::Float;
|
||||||
match ty.sty {
|
return match ty.sty {
|
||||||
ty::TyFloat(ast::FloatTy::F32) => {
|
ty::TyFloat(ast::FloatTy::F32) => {
|
||||||
let l = ::rustc_apfloat::ieee::Single::from_bits(a);
|
let l = ::rustc_apfloat::ieee::Single::from_bits(a);
|
||||||
let r = ::rustc_apfloat::ieee::Single::from_bits(b);
|
let r = ::rustc_apfloat::ieee::Single::from_bits(b);
|
||||||
|
@ -1062,13 +1078,36 @@ pub fn compare_const_vals<'a, 'tcx>(
|
||||||
},
|
},
|
||||||
_ => Some(a.cmp(&b)),
|
_ => Some(a.cmp(&b)),
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
if a == b {
|
|
||||||
Some(Ordering::Equal)
|
if let ty::TyRef(_, rty, _) = ty.sty {
|
||||||
} else {
|
if let ty::TyStr = rty.sty {
|
||||||
None
|
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
|
// 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 {
|
let lit = match *lit {
|
||||||
LitKind::Str(ref s, _) => {
|
LitKind::Str(ref s, _) => {
|
||||||
let s = s.as_str();
|
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));
|
let ptr = MemoryPointer::new(id, Size::from_bytes(0));
|
||||||
ConstValue::ByValPair(
|
ConstValue::ByValPair(
|
||||||
PrimVal::Ptr(ptr),
|
PrimVal::Ptr(ptr),
|
||||||
|
@ -1091,7 +1130,7 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
LitKind::ByteStr(ref data) => {
|
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));
|
let ptr = MemoryPointer::new(id, Size::from_bytes(0));
|
||||||
ConstValue::ByVal(PrimVal::Ptr(ptr))
|
ConstValue::ByVal(PrimVal::Ptr(ptr))
|
||||||
},
|
},
|
||||||
|
|
|
@ -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> {
|
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(
|
Ok(Value::ByValPair(
|
||||||
PrimVal::Ptr(ptr),
|
PrimVal::Ptr(ptr),
|
||||||
PrimVal::from_u128(s.len() as u128),
|
PrimVal::from_u128(s.len() as u128),
|
||||||
|
|
|
@ -76,8 +76,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
|
||||||
MemoryPointer::new(id, Size::from_bytes(0))
|
MemoryPointer::new(id, Size::from_bytes(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate_cached(&mut self, bytes: &[u8]) -> MemoryPointer {
|
pub fn allocate_bytes(&mut self, bytes: &[u8]) -> MemoryPointer {
|
||||||
let id = self.tcx.allocate_cached(bytes);
|
let id = self.tcx.allocate_bytes(bytes);
|
||||||
MemoryPointer::new(id, Size::from_bytes(0))
|
MemoryPointer::new(id, Size::from_bytes(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue