Skip to content

Commit c2933d1

Browse files
authored
Merge pull request #19 from neonlabsorg/25_optimize_stack_and_calldataload
#25 Optimize stack and calldataload
2 parents 324cc72 + b1c4832 commit c2933d1

File tree

4 files changed

+32
-18
lines changed

4 files changed

+32
-18
lines changed

core/src/eval/misc.rs

+5-11
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,11 @@ pub fn calldataload(state: &mut Machine) -> Control {
2828
pop_u256!(state, index);
2929
trace_op!("CallDataLoad: {}", index);
3030

31+
let index = as_usize_or_fail!(index);
32+
let len = if index > state.data.len() { 0 } else { min(32, state.data.len() - index) };
33+
3134
let mut load = [0u8; 32];
32-
for i in 0..32 {
33-
if let Some(p) = index.checked_add(U256::from(i)) {
34-
if p <= U256::from(usize::max_value()) {
35-
let p = p.as_usize();
36-
if p < state.data.len() {
37-
load[i] = state.data[p];
38-
}
39-
}
40-
}
41-
}
35+
load[0..len].copy_from_slice(&state.data[index..index + len]);
4236

4337
push!(state, H256::from(load));
4438
Control::Continue(1)
@@ -153,7 +147,7 @@ pub fn msize(state: &mut Machine) -> Control {
153147

154148
pub fn push(state: &mut Machine, n: usize, position: usize) -> Control {
155149
let end = min(position + 1 + n, state.code.len());
156-
let val = U256::from(&state.code[(position + 1)..end]);
150+
let val = U256::from_big_endian_fast(&state.code[(position + 1)..end]);
157151

158152
push_u256!(state, val);
159153
trace_op!("Push [@{}]: {}", state.stack.len() - 1, val);

core/src/primitive_types.rs

+22
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,26 @@ impl<'de> serde::Deserialize<'de> for U256 {
171171

172172
deserializer.deserialize_bytes(Visitor)
173173
}
174+
}
175+
176+
177+
impl U256 {
178+
pub fn into_big_endian_fast(self, buffer: &mut [u8]) {
179+
let data: [u8; 32] = unsafe { core::mem::transmute(self) };
180+
181+
let buffer = &mut buffer[0..32];
182+
buffer.copy_from_slice(&data[..]);
183+
buffer.reverse();
184+
}
185+
186+
pub fn from_big_endian_fast(buffer: &[u8]) -> U256 {
187+
assert!(32 >= buffer.len());
188+
189+
let mut data = [0u8; 32];
190+
191+
data[32 - buffer.len()..32].copy_from_slice(buffer);
192+
data.reverse();
193+
194+
unsafe { core::mem::transmute(data) }
195+
}
174196
}

core/src/stack.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ impl Stack {
8383
self.data.pop()
8484
.map(|d| {
8585
let mut value = H256::default();
86-
d.to_big_endian(&mut value[..]);
86+
d.into_big_endian_fast(&mut value[..]);
8787
value
8888
})
8989
.ok_or(ExitError::StackUnderflow)
@@ -95,7 +95,7 @@ impl Stack {
9595
if self.data.len() + 1 > self.limit {
9696
return Err(ExitError::StackOverflow)
9797
}
98-
self.data.push(U256::from_big_endian(&value[..]));
98+
self.data.push(U256::from_big_endian_fast(&value[..]));
9999
Ok(())
100100
}
101101

runtime/src/eval/macros.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ macro_rules! pop {
2121
macro_rules! pop_u256 {
2222
( $machine:expr, $( $x:ident ),* ) => (
2323
$(
24-
let $x = match $machine.machine.stack_mut().pop() {
25-
Ok(value) => U256::from_big_endian(&value[..]),
24+
let $x = match $machine.machine.stack_mut().pop_u256() {
25+
Ok(value) => value,
2626
Err(e) => return Control::Exit(e.into()),
2727
};
2828
)*
@@ -43,9 +43,7 @@ macro_rules! push {
4343
macro_rules! push_u256 {
4444
( $machine:expr, $( $x:expr ),* ) => (
4545
$(
46-
let mut value = H256::default();
47-
$x.to_big_endian(&mut value[..]);
48-
match $machine.machine.stack_mut().push(value) {
46+
match $machine.machine.stack_mut().push_u256($x) {
4947
Ok(()) => (),
5048
Err(e) => return Control::Exit(e.into()),
5149
}

0 commit comments

Comments
 (0)