Cache string and bytestring literal allocs.

This commit is contained in:
Scott Olson 2017-02-10 13:35:33 -08:00
parent 98d28b688c
commit 6ffd7005c1
2 changed files with 20 additions and 9 deletions

View file

@ -168,11 +168,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
&self.stack
}
pub(super) fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> {
// FIXME: cache these allocs
let ptr = self.memory.allocate(s.len() as u64, 1)?;
self.memory.write_bytes(ptr, s.as_bytes())?;
self.memory.mark_static_initalized(ptr.alloc_id, false)?;
pub(crate) fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> {
let ptr = self.memory.allocate_cached(s.as_bytes())?;
Ok(Value::ByValPair(PrimVal::Ptr(ptr), PrimVal::from_u128(s.len() as u128)))
}
@ -194,10 +191,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
Str(ref s) => return self.str_to_value(s),
ByteStr(ref bs) => {
// FIXME: cache these allocs
let ptr = self.memory.allocate(bs.len() as u64, 1)?;
self.memory.write_bytes(ptr, bs)?;
self.memory.mark_static_initalized(ptr.alloc_id, false)?;
let ptr = self.memory.allocate_cached(bs)?;
PrimVal::Ptr(ptr)
}

View file

@ -180,6 +180,10 @@ pub struct Memory<'a, 'tcx> {
/// the normal struct access will succeed even though it shouldn't.
/// But even with mir optimizations, that situation is hard/impossible to produce.
packed: BTreeSet<Entry>,
/// A cache for basic byte allocations keyed by their contents. This is used to deduplicate
/// allocations for string and bytestring literals.
literal_alloc_cache: HashMap<Vec<u8>, AllocId>,
}
const ZST_ALLOC_ID: AllocId = AllocId(0);
@ -197,6 +201,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
memory_usage: 0,
packed: BTreeSet::new(),
static_alloc: HashSet::new(),
literal_alloc_cache: HashMap::new(),
}
}
@ -263,6 +268,18 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
Pointer::new(id, 0)
}
pub fn allocate_cached(&mut self, bytes: &[u8]) -> EvalResult<'tcx, Pointer> {
if let Some(&alloc_id) = self.literal_alloc_cache.get(bytes) {
return Ok(Pointer::new(alloc_id, 0));
}
let ptr = self.allocate(bytes.len() as u64, 1)?;
self.write_bytes(ptr, bytes)?;
self.mark_static_initalized(ptr.alloc_id, false)?;
self.literal_alloc_cache.insert(bytes.to_vec(), ptr.alloc_id);
Ok(ptr)
}
pub fn allocate(&mut self, size: u64, align: u64) -> EvalResult<'tcx, Pointer> {
if size == 0 {
return Ok(Pointer::zst_ptr());