From aace842a08c241d5d68dae9ccf597d21ab72567c Mon Sep 17 00:00:00 2001 From: =?utf8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 1 May 2018 12:18:53 +0200 Subject: [PATCH] Get rid of literal_alloc_cache --- src/librustc/ty/context.rs | 16 +----- src/librustc/ty/sty.rs | 8 +++ src/librustc_mir/hair/cx/mod.rs | 4 +- src/librustc_mir/hair/pattern/mod.rs | 57 ++++++++++++++++++---- src/librustc_mir/interpret/eval_context.rs | 2 +- src/librustc_mir/interpret/memory.rs | 4 +- 6 files changed, 63 insertions(+), 28 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index a3d380c3e14..c7fe7ffd949 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -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, - - /// 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, interpret::AllocId>, } impl<'tcx> InterpretInterner<'tcx> { @@ -1123,22 +1119,14 @@ pub fn intern_const_alloc( } /// 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 } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 6bc0cb51a92..d9797bf4985 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1860,6 +1860,14 @@ pub fn to_ptr(&self) -> Option { } } + #[inline] + pub fn to_byval_value(&self) -> Option { + match self.val { + ConstVal::Value(val) => val.to_byval_value(), + _ => None, + } + } + #[inline] pub fn to_primval(&self) -> Option { match self.val { diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 71dd35c010d..390b82af48a 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -181,7 +181,7 @@ pub fn const_eval_literal( 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 @@ pub fn const_eval_literal( ) }, 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)) }, diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 0368e6595c1..95ff5c24ecc 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -20,7 +20,7 @@ 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 { 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)) }, diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 97ea90bb4bf..cc55f908831 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -229,7 +229,7 @@ pub fn cur_frame(&self) -> usize { } 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), diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 755eaa443b6..0b67e0621f6 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -76,8 +76,8 @@ pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> MemoryPointer { 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)) } -- 2.44.0