Skip to content

Commit 7968256

Browse files
committed
perf: use mem::swap in stack swap/exchange
1 parent db5d39c commit 7968256

File tree

2 files changed

+18
-18
lines changed

2 files changed

+18
-18
lines changed

Cargo.toml

-5
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,6 @@ default-members = ["crates/revm"]
1414
all-features = true
1515
rustdoc-args = ["--cfg", "docsrs"]
1616

17-
[profile.release]
18-
lto = true
19-
codegen-units = 1
20-
debug = true
21-
2217
[profile.ethtests]
2318
inherits = "test"
2419
opt-level = 3

crates/interpreter/src/interpreter/stack.rs

+18-13
Original file line numberDiff line numberDiff line change
@@ -251,30 +251,35 @@ impl Stack {
251251
/// # Panics
252252
///
253253
/// Panics if `n` is 0.
254-
#[inline]
254+
#[inline(always)]
255255
#[cfg_attr(debug_assertions, track_caller)]
256256
pub fn swap(&mut self, n: usize) -> Result<(), InstructionResult> {
257-
assume!(n > 0, "attempted to swap with 0");
258-
let len = self.data.len();
259-
if n >= len {
260-
return Err(InstructionResult::StackUnderflow);
261-
}
262-
let last_index = len - 1;
263-
self.data.swap(last_index, last_index - n);
264-
Ok(())
257+
self.exchange(0, n)
265258
}
266259

267-
/// Exchange two values on the stack. where `N` is first index and second index
268-
/// is calculated as N+M
260+
/// Exchange two values on the stack.
261+
///
262+
/// `n` is the first index, and the second index is calculated as `n + m`.
263+
///
264+
/// # Panics
265+
///
266+
/// Panics if `m` is zero.
269267
#[inline]
268+
#[cfg_attr(not(debug_assertions), track_caller)]
270269
pub fn exchange(&mut self, n: usize, m: usize) -> Result<(), InstructionResult> {
270+
assume!(m > 0, "overlapping exchange");
271271
let len = self.data.len();
272272
let n_m_index = n + m;
273273
if n_m_index >= len {
274274
return Err(InstructionResult::StackUnderflow);
275275
}
276-
let last_index = len - 1;
277-
self.data.swap(last_index - n, last_index - n_m_index);
276+
// SAFETY: `n` and `n_m` are checked to be within bounds, and they don't overlap.
277+
unsafe {
278+
// NOTE: `mem::swap` performs better than `slice::swap`/`ptr::swap`, as they cannot
279+
// assume that the pointers are non-overlapping when we know they are not.
280+
let top = self.data.as_mut_ptr().add(len - 1);
281+
core::mem::swap(&mut *top.sub(n), &mut *top.sub(n_m_index));
282+
}
278283
Ok(())
279284
}
280285

0 commit comments

Comments
 (0)