From cd53bd6b8edb4e71954f9964f72d8126d83f4627 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 7 Sep 2023 18:40:53 +0200 Subject: [PATCH] Remove allocation on mir eval memory write --- crates/hir-ty/src/mir/eval.rs | 46 ++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index 3944feb128c..5b267641a3d 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) -> 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> { if let Some(layout) = self.layout_cache.borrow().get(ty) { return Ok(layout