Skip to content

Commit 22e18a6

Browse files
DaniPopesfubuloubu
authored andcommitted
perf(interpreter): use pop_top! where possible (bluealloy#1267)
1 parent be28729 commit 22e18a6

File tree

6 files changed

+53
-45
lines changed

6 files changed

+53
-45
lines changed

crates/interpreter/src/instructions/control.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,27 @@ use crate::{
66

77
pub fn jump<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
88
gas!(interpreter, gas::MID);
9-
pop!(interpreter, dest);
10-
jump_inner(interpreter, dest);
9+
pop!(interpreter, target);
10+
jump_inner(interpreter, target);
1111
}
1212

1313
pub fn jumpi<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
1414
gas!(interpreter, gas::HIGH);
15-
pop!(interpreter, dest, value);
16-
if value != U256::ZERO {
17-
jump_inner(interpreter, dest);
15+
pop!(interpreter, target, cond);
16+
if cond != U256::ZERO {
17+
jump_inner(interpreter, target);
1818
}
1919
}
2020

2121
#[inline(always)]
22-
fn jump_inner(interpreter: &mut Interpreter, dest: U256) {
23-
let dest = as_usize_or_fail!(interpreter, dest, InstructionResult::InvalidJump);
24-
if !interpreter.contract.is_valid_jump(dest) {
22+
fn jump_inner(interpreter: &mut Interpreter, target: U256) {
23+
let target = as_usize_or_fail!(interpreter, target, InstructionResult::InvalidJump);
24+
if !interpreter.contract.is_valid_jump(target) {
2525
interpreter.instruction_result = InstructionResult::InvalidJump;
2626
return;
2727
}
2828
// SAFETY: `is_valid_jump` ensures that `dest` is in bounds.
29-
interpreter.instruction_pointer = unsafe { interpreter.contract.bytecode.as_ptr().add(dest) };
29+
interpreter.instruction_pointer = unsafe { interpreter.contract.bytecode.as_ptr().add(target) };
3030
}
3131

3232
pub fn jumpdest<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {

crates/interpreter/src/instructions/host.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -140,14 +140,14 @@ pub fn blockhash<H: Host + ?Sized>(interpreter: &mut Interpreter, host: &mut H)
140140
}
141141

142142
pub fn sload<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
143-
pop!(interpreter, index);
143+
pop_top!(interpreter, index);
144144

145-
let Some((value, is_cold)) = host.sload(interpreter.contract.address, index) else {
145+
let Some((value, is_cold)) = host.sload(interpreter.contract.address, *index) else {
146146
interpreter.instruction_result = InstructionResult::FatalExternalError;
147147
return;
148148
};
149149
gas!(interpreter, gas::sload_cost(SPEC::SPEC_ID, is_cold));
150-
push!(interpreter, value);
150+
*index = value;
151151
}
152152

153153
pub fn sstore<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {

crates/interpreter/src/instructions/memory.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,26 @@ use core::cmp::max;
77

88
pub fn mload<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
99
gas!(interpreter, gas::VERYLOW);
10-
pop!(interpreter, index);
11-
let index = as_usize_or_fail!(interpreter, index);
12-
resize_memory!(interpreter, index, 32);
13-
push!(interpreter, interpreter.shared_memory.get_u256(index));
10+
pop_top!(interpreter, offset_ptr);
11+
let offset = as_usize_or_fail!(interpreter, offset_ptr);
12+
resize_memory!(interpreter, offset, 32);
13+
*offset_ptr = interpreter.shared_memory.get_u256(offset);
1414
}
1515

1616
pub fn mstore<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
1717
gas!(interpreter, gas::VERYLOW);
18-
pop!(interpreter, index, value);
19-
let index = as_usize_or_fail!(interpreter, index);
20-
resize_memory!(interpreter, index, 32);
21-
interpreter.shared_memory.set_u256(index, value);
18+
pop!(interpreter, offset, value);
19+
let offset = as_usize_or_fail!(interpreter, offset);
20+
resize_memory!(interpreter, offset, 32);
21+
interpreter.shared_memory.set_u256(offset, value);
2222
}
2323

2424
pub fn mstore8<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
2525
gas!(interpreter, gas::VERYLOW);
26-
pop!(interpreter, index, value);
27-
let index = as_usize_or_fail!(interpreter, index);
28-
resize_memory!(interpreter, index, 1);
29-
interpreter.shared_memory.set_byte(index, value.byte(0))
26+
pop!(interpreter, offset, value);
27+
let offset = as_usize_or_fail!(interpreter, offset);
28+
resize_memory!(interpreter, offset, 1);
29+
interpreter.shared_memory.set_byte(offset, value.byte(0))
3030
}
3131

3232
pub fn msize<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {

crates/interpreter/src/instructions/system.rs

+24-17
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@ use crate::{
33
primitives::{Spec, B256, KECCAK_EMPTY, U256},
44
Host, InstructionResult, Interpreter,
55
};
6+
use core::ptr;
67

78
pub fn keccak256<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
8-
pop!(interpreter, from, len);
9-
let len = as_usize_or_fail!(interpreter, len);
9+
pop_top!(interpreter, offset, len_ptr);
10+
let len = as_usize_or_fail!(interpreter, len_ptr);
1011
gas_or_fail!(interpreter, gas::keccak256_cost(len as u64));
1112
let hash = if len == 0 {
1213
KECCAK_EMPTY
1314
} else {
14-
let from = as_usize_or_fail!(interpreter, from);
15+
let from = as_usize_or_fail!(interpreter, offset);
1516
resize_memory!(interpreter, from, len);
1617
crate::primitives::keccak256(interpreter.shared_memory.slice(from, len))
1718
};
18-
19-
push_b256!(interpreter, hash);
19+
*len_ptr = hash.into();
2020
}
2121

2222
pub fn address<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
@@ -56,18 +56,25 @@ pub fn codecopy<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H)
5656

5757
pub fn calldataload<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {
5858
gas!(interpreter, gas::VERYLOW);
59-
pop!(interpreter, index);
60-
let index = as_usize_saturated!(index);
61-
let load = if index < interpreter.contract.input.len() {
62-
let have_bytes = 32.min(interpreter.contract.input.len() - index);
63-
let mut bytes = [0u8; 32];
64-
bytes[..have_bytes].copy_from_slice(&interpreter.contract.input[index..index + have_bytes]);
65-
B256::new(bytes)
66-
} else {
67-
B256::ZERO
68-
};
69-
70-
push_b256!(interpreter, load);
59+
pop_top!(interpreter, offset_ptr);
60+
let mut word = B256::ZERO;
61+
let offset = as_usize_saturated!(offset_ptr);
62+
if offset < interpreter.contract.input.len() {
63+
let count = 32.min(interpreter.contract.input.len() - offset);
64+
// SAFETY: count is bounded by the calldata length.
65+
// This is `word[..count].copy_from_slice(input[offset..offset + count])`, written using
66+
// raw pointers as apparently the compiler cannot optimize the slice version, and using
67+
// `get_unchecked` twice is uglier.
68+
debug_assert!(count <= 32 && offset + count <= interpreter.contract.input.len());
69+
unsafe {
70+
ptr::copy_nonoverlapping(
71+
interpreter.contract.input.as_ptr().add(offset),
72+
word.as_mut_ptr(),
73+
count,
74+
)
75+
};
76+
}
77+
*offset_ptr = word.into();
7178
}
7279

7380
pub fn calldatasize<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {

crates/interpreter/src/interpreter/stack.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ impl Stack {
184184
/// unchanged.
185185
#[inline]
186186
pub fn push(&mut self, value: U256) -> Result<(), InstructionResult> {
187-
// allows the compiler to optimize out the `Vec::push` capacity check
187+
// Allows the compiler to optimize out the `Vec::push` capacity check.
188188
assume!(self.data.capacity() == STACK_LIMIT);
189189
if self.data.len() == STACK_LIMIT {
190190
return Err(InstructionResult::StackOverflow);

crates/revm/src/evm.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -382,13 +382,14 @@ impl<EXT, DB: Database> Evm<'_, EXT, DB> {
382382
}
383383

384384
impl<EXT, DB: Database> Host for Evm<'_, EXT, DB> {
385-
fn env_mut(&mut self) -> &mut Env {
386-
&mut self.context.evm.env
387-
}
388385
fn env(&self) -> &Env {
389386
&self.context.evm.env
390387
}
391388

389+
fn env_mut(&mut self) -> &mut Env {
390+
&mut self.context.evm.env
391+
}
392+
392393
fn block_hash(&mut self, number: U256) -> Option<B256> {
393394
self.context
394395
.evm

0 commit comments

Comments
 (0)