Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #15571 - Veykril:mir-alloc, r=Veykril
Remove allocation on mir eval memory write
bors 2023-09-08
parent 8edd81f · parent cd53bd6 · commit d5b6ab2
-rw-r--r--crates/hir-ty/src/mir/eval.rs46
1 files changed, 43 insertions, 3 deletions
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index 3944feb128..5b267641a3 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -215,9 +215,7 @@ impl Interval {
}
fn write_from_interval(&self, memory: &mut Evaluator<'_>, interval: Interval) -> Result<()> {
- // FIXME: this could be more efficient
- let bytes = &interval.get(memory)?.to_vec();
- memory.write_memory(self.addr, bytes)
+ memory.copy_from_interval(self.addr, interval)
}
fn slice(self, range: Range<usize>) -> Interval {
@@ -1760,6 +1758,48 @@ impl Evaluator<'_> {
Ok(())
}
+ fn copy_from_interval(&mut self, addr: Address, r: Interval) -> Result<()> {
+ if r.size == 0 {
+ return Ok(());
+ }
+
+ let oob = || MirEvalError::UndefinedBehavior("out of bounds memory write".to_string());
+
+ match (addr, r.addr) {
+ (Stack(dst), Stack(src)) => {
+ if self.stack.len() < src + r.size || self.stack.len() < dst + r.size {
+ return Err(oob());
+ }
+ self.stack.copy_within(src..src + r.size, dst)
+ }
+ (Heap(dst), Heap(src)) => {
+ if self.stack.len() < src + r.size || self.stack.len() < dst + r.size {
+ return Err(oob());
+ }
+ self.heap.copy_within(src..src + r.size, dst)
+ }
+ (Stack(dst), Heap(src)) => {
+ self.stack
+ .get_mut(dst..dst + r.size)
+ .ok_or_else(oob)?
+ .copy_from_slice(self.heap.get(src..src + r.size).ok_or_else(oob)?);
+ }
+ (Heap(dst), Stack(src)) => {
+ self.heap
+ .get_mut(dst..dst + r.size)
+ .ok_or_else(oob)?
+ .copy_from_slice(self.stack.get(src..src + r.size).ok_or_else(oob)?);
+ }
+ _ => {
+ return Err(MirEvalError::UndefinedBehavior(format!(
+ "invalid memory write at address {addr:?}"
+ )))
+ }
+ }
+
+ Ok(())
+ }
+
fn size_align_of(&self, ty: &Ty, locals: &Locals) -> Result<Option<(usize, usize)>> {
if let Some(layout) = self.layout_cache.borrow().get(ty) {
return Ok(layout