Cache string and bytestring literal allocs.
This commit is contained in:
parent
98d28b688c
commit
6ffd7005c1
2 changed files with 20 additions and 9 deletions
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue