Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit d5b6ab2

Browse files
committed
Auto merge of rust-lang#15571 - Veykril:mir-alloc, r=Veykril
Remove allocation on mir eval memory write
2 parents 8edd81f + cd53bd6 commit d5b6ab2

File tree

1 file changed

+43
-3
lines changed

1 file changed

+43
-3
lines changed

crates/hir-ty/src/mir/eval.rs

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,7 @@ impl Interval {
215215
}
216216

217217
fn write_from_interval(&self, memory: &mut Evaluator<'_>, interval: Interval) -> Result<()> {
218-
// FIXME: this could be more efficient
219-
let bytes = &interval.get(memory)?.to_vec();
220-
memory.write_memory(self.addr, bytes)
218+
memory.copy_from_interval(self.addr, interval)
221219
}
222220

223221
fn slice(self, range: Range<usize>) -> Interval {
@@ -1760,6 +1758,48 @@ impl Evaluator<'_> {
17601758
Ok(())
17611759
}
17621760

1761+
fn copy_from_interval(&mut self, addr: Address, r: Interval) -> Result<()> {
1762+
if r.size == 0 {
1763+
return Ok(());
1764+
}
1765+
1766+
let oob = || MirEvalError::UndefinedBehavior("out of bounds memory write".to_string());
1767+
1768+
match (addr, r.addr) {
1769+
(Stack(dst), Stack(src)) => {
1770+
if self.stack.len() < src + r.size || self.stack.len() < dst + r.size {
1771+
return Err(oob());
1772+
}
1773+
self.stack.copy_within(src..src + r.size, dst)
1774+
}
1775+
(Heap(dst), Heap(src)) => {
1776+
if self.stack.len() < src + r.size || self.stack.len() < dst + r.size {
1777+
return Err(oob());
1778+
}
1779+
self.heap.copy_within(src..src + r.size, dst)
1780+
}
1781+
(Stack(dst), Heap(src)) => {
1782+
self.stack
1783+
.get_mut(dst..dst + r.size)
1784+
.ok_or_else(oob)?
1785+
.copy_from_slice(self.heap.get(src..src + r.size).ok_or_else(oob)?);
1786+
}
1787+
(Heap(dst), Stack(src)) => {
1788+
self.heap
1789+
.get_mut(dst..dst + r.size)
1790+
.ok_or_else(oob)?
1791+
.copy_from_slice(self.stack.get(src..src + r.size).ok_or_else(oob)?);
1792+
}
1793+
_ => {
1794+
return Err(MirEvalError::UndefinedBehavior(format!(
1795+
"invalid memory write at address {addr:?}"
1796+
)))
1797+
}
1798+
}
1799+
1800+
Ok(())
1801+
}
1802+
17631803
fn size_align_of(&self, ty: &Ty, locals: &Locals) -> Result<Option<(usize, usize)>> {
17641804
if let Some(layout) = self.layout_cache.borrow().get(ty) {
17651805
return Ok(layout

0 commit comments

Comments
 (0)