Skip to content

Commit e24f1f8

Browse files
committed
use single allocation for vm stack
1 parent b3b636e commit e24f1f8

File tree

15 files changed

+471
-513
lines changed

15 files changed

+471
-513
lines changed

crates/vm/backends/levm/mod.rs

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use ethrex_common::{
1818
},
1919
};
2020
use ethrex_levm::EVMConfig;
21-
use ethrex_levm::call_frame::Stack;
2221
use ethrex_levm::constants::{SYS_CALL_GAS_LIMIT, TX_BASE_COST};
2322
use ethrex_levm::db::gen_db::GeneralizedDatabase;
2423
use ethrex_levm::errors::{InternalError, TxValidationError};
@@ -92,21 +91,18 @@ impl LEVM {
9291
) -> Result<BlockExecutionResult, EvmError> {
9392
Self::prepare_block(block, db, vm_type)?;
9493

95-
let mut shared_stack_pool = Vec::with_capacity(1024);
96-
9794
let mut receipts = Vec::new();
9895
let mut cumulative_gas_used = 0;
9996

10097
for (tx, tx_sender) in block.body.get_transactions_with_sender().map_err(|error| {
10198
EvmError::Transaction(format!("Couldn't recover addresses with error: {error}"))
10299
})? {
103-
let report = Self::execute_tx_in_block(
100+
let report = Self::execute_tx(
104101
tx,
105102
tx_sender,
106103
&block.header,
107104
db,
108-
vm_type,
109-
&mut shared_stack_pool,
105+
vm_type
110106
)?;
111107
LEVM::send_state_transitions_tx(&merkleizer, db, queue_length)?;
112108

@@ -225,26 +221,6 @@ impl LEVM {
225221
vm.execute().map_err(VMError::into)
226222
}
227223

228-
pub fn execute_tx_in_block(
229-
// The transaction to execute.
230-
tx: &Transaction,
231-
// The transactions recovered address
232-
tx_sender: Address,
233-
// The block header for the current block.
234-
block_header: &BlockHeader,
235-
db: &mut GeneralizedDatabase,
236-
vm_type: VMType,
237-
stack_pool: &mut Vec<Stack>,
238-
) -> Result<ExecutionReport, EvmError> {
239-
let env = Self::setup_env(tx, tx_sender, block_header, db, vm_type)?;
240-
let mut vm = VM::new(env, db, tx, LevmCallTracer::disabled(), vm_type)?;
241-
242-
std::mem::swap(&mut vm.stack_pool, stack_pool);
243-
let result = vm.execute().map_err(VMError::into);
244-
std::mem::swap(&mut vm.stack_pool, stack_pool);
245-
result
246-
}
247-
248224
pub fn undo_last_tx(db: &mut GeneralizedDatabase) -> Result<(), EvmError> {
249225
db.undo_last_transaction()?;
250226
Ok(())

crates/vm/levm/runner/src/main.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,8 @@ fn main() {
162162

163163
// Set initial stack and memory
164164
info!("Setting initial stack: {:?}", runner_input.initial_stack);
165-
let stack = &mut vm.current_call_frame.stack;
166165
for elem in runner_input.initial_stack {
167-
stack.push(&[elem]).expect("Stack Overflow");
166+
vm.current_stack().push(&[elem]).expect("Stack Overflow");
168167
}
169168
info!(
170169
"Setting initial memory: 0x{:x}",
@@ -186,15 +185,16 @@ fn main() {
186185
}
187186

188187
// Print final stack and memory
189-
let callframe = vm.current_call_frame;
188+
let stack_depth = vm.current_stack().offset;
190189
info!(
191190
"Final Stack (bottom to top): {:?}",
192-
&callframe.stack.values[callframe.stack.offset..]
191+
&vm.current_stack().values[stack_depth..]
193192
.iter()
194193
.rev()
195194
.map(|value| format!("0x{:x}", value))
196195
.collect::<Vec<_>>()
197196
);
197+
let callframe = vm.current_call_frame;
198198
let final_memory: Vec<u8> = callframe.memory.buffer.borrow()[0..callframe.memory.len].to_vec();
199199
info!("Final Memory: 0x{}", hex::encode(final_memory));
200200

crates/vm/levm/src/call_frame.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use std::{collections::HashMap, fmt};
2323
/// [`pop`](Self::pop) methods support working with multiple elements instead of a single one,
2424
/// reducing the number of checks performed on the stack.
2525
pub struct Stack {
26-
pub values: Box<[U256; STACK_LIMIT]>,
26+
pub values: [U256; STACK_LIMIT],
2727
pub offset: usize,
2828
}
2929

@@ -194,7 +194,7 @@ impl Stack {
194194
impl Default for Stack {
195195
fn default() -> Self {
196196
Self {
197-
values: Box::new([U256::zero(); STACK_LIMIT]),
197+
values: [U256::zero(); STACK_LIMIT],
198198
offset: STACK_LIMIT,
199199
}
200200
}
@@ -243,7 +243,6 @@ pub struct CallFrame {
243243
pub bytecode: Code,
244244
/// Value sent along the transaction
245245
pub msg_value: U256,
246-
pub stack: Stack,
247246
pub memory: Memory,
248247
/// Data sent along the transaction. Empty in CREATE transactions.
249248
pub calldata: Bytes,
@@ -323,7 +322,6 @@ impl CallFrame {
323322
is_create: bool,
324323
ret_offset: usize,
325324
ret_size: usize,
326-
stack: Stack,
327325
memory: Memory,
328326
) -> Self {
329327
// Note: Do not use ..Default::default() because it has runtime cost.
@@ -344,7 +342,6 @@ impl CallFrame {
344342
is_create,
345343
ret_offset,
346344
ret_size,
347-
stack,
348345
memory,
349346
call_frame_backup: CallFrameBackup::default(),
350347
output: Bytes::default(),

crates/vm/levm/src/opcode_handlers/arithmetic.rs

Lines changed: 52 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -11,63 +11,63 @@ use ethrex_common::{U256, U512};
1111
impl<'a> VM<'a> {
1212
// ADD operation
1313
pub fn op_add(&mut self) -> Result<OpcodeResult, VMError> {
14-
let current_call_frame = &mut self.current_call_frame;
15-
current_call_frame.increase_consumed_gas(gas_cost::ADD)?;
14+
self.current_call_frame
15+
.increase_consumed_gas(gas_cost::ADD)?;
1616

17-
let [augend, addend] = *current_call_frame.stack.pop()?;
17+
let [augend, addend] = *self.current_stack().pop()?;
1818
let sum = augend.overflowing_add(addend).0;
19-
current_call_frame.stack.push1(sum)?;
19+
self.current_stack().push1(sum)?;
2020

2121
Ok(OpcodeResult::Continue)
2222
}
2323

2424
// SUB operation
2525
pub fn op_sub(&mut self) -> Result<OpcodeResult, VMError> {
26-
let current_call_frame = &mut self.current_call_frame;
27-
current_call_frame.increase_consumed_gas(gas_cost::SUB)?;
26+
self.current_call_frame
27+
.increase_consumed_gas(gas_cost::SUB)?;
2828

29-
let [minuend, subtrahend] = *current_call_frame.stack.pop()?;
29+
let [minuend, subtrahend] = *self.current_stack().pop()?;
3030
let difference = minuend.overflowing_sub(subtrahend).0;
31-
current_call_frame.stack.push1(difference)?;
31+
self.current_stack().push1(difference)?;
3232

3333
Ok(OpcodeResult::Continue)
3434
}
3535

3636
// MUL operation
3737
pub fn op_mul(&mut self) -> Result<OpcodeResult, VMError> {
38-
let current_call_frame = &mut self.current_call_frame;
39-
current_call_frame.increase_consumed_gas(gas_cost::MUL)?;
38+
self.current_call_frame
39+
.increase_consumed_gas(gas_cost::MUL)?;
4040

41-
let [multiplicand, multiplier] = *current_call_frame.stack.pop()?;
41+
let [multiplicand, multiplier] = *self.current_stack().pop()?;
4242
let product = multiplicand.overflowing_mul(multiplier).0;
43-
current_call_frame.stack.push1(product)?;
43+
self.current_stack().push1(product)?;
4444

4545
Ok(OpcodeResult::Continue)
4646
}
4747

4848
// DIV operation
4949
pub fn op_div(&mut self) -> Result<OpcodeResult, VMError> {
50-
let current_call_frame = &mut self.current_call_frame;
51-
current_call_frame.increase_consumed_gas(gas_cost::DIV)?;
50+
self.current_call_frame
51+
.increase_consumed_gas(gas_cost::DIV)?;
5252

53-
let [dividend, divisor] = *current_call_frame.stack.pop()?;
53+
let [dividend, divisor] = *self.current_stack().pop()?;
5454
let Some(quotient) = dividend.checked_div(divisor) else {
55-
current_call_frame.stack.push_zero()?;
55+
self.current_stack().push_zero()?;
5656
return Ok(OpcodeResult::Continue);
5757
};
58-
current_call_frame.stack.push1(quotient)?;
58+
self.current_stack().push1(quotient)?;
5959

6060
Ok(OpcodeResult::Continue)
6161
}
6262

6363
// SDIV operation
6464
pub fn op_sdiv(&mut self) -> Result<OpcodeResult, VMError> {
65-
let current_call_frame = &mut self.current_call_frame;
66-
current_call_frame.increase_consumed_gas(gas_cost::SDIV)?;
65+
self.current_call_frame
66+
.increase_consumed_gas(gas_cost::SDIV)?;
6767

68-
let [dividend, divisor] = *current_call_frame.stack.pop()?;
68+
let [dividend, divisor] = *self.current_stack().pop()?;
6969
if divisor.is_zero() || dividend.is_zero() {
70-
current_call_frame.stack.push_zero()?;
70+
self.current_stack().push_zero()?;
7171
return Ok(OpcodeResult::Continue);
7272
}
7373

@@ -86,34 +86,34 @@ impl<'a> VM<'a> {
8686
None => U256::zero(),
8787
};
8888

89-
current_call_frame.stack.push1(quotient)?;
89+
self.current_stack().push1(quotient)?;
9090

9191
Ok(OpcodeResult::Continue)
9292
}
9393

9494
// MOD operation
9595
pub fn op_mod(&mut self) -> Result<OpcodeResult, VMError> {
96-
let current_call_frame = &mut self.current_call_frame;
97-
current_call_frame.increase_consumed_gas(gas_cost::MOD)?;
96+
self.current_call_frame
97+
.increase_consumed_gas(gas_cost::MOD)?;
9898

99-
let [dividend, divisor] = *current_call_frame.stack.pop()?;
99+
let [dividend, divisor] = *self.current_stack().pop()?;
100100

101101
let remainder = dividend.checked_rem(divisor).unwrap_or_default();
102102

103-
current_call_frame.stack.push1(remainder)?;
103+
self.current_stack().push1(remainder)?;
104104

105105
Ok(OpcodeResult::Continue)
106106
}
107107

108108
// SMOD operation
109109
pub fn op_smod(&mut self) -> Result<OpcodeResult, VMError> {
110-
let current_call_frame = &mut self.current_call_frame;
111-
current_call_frame.increase_consumed_gas(gas_cost::SMOD)?;
110+
self.current_call_frame
111+
.increase_consumed_gas(gas_cost::SMOD)?;
112112

113-
let [unchecked_dividend, unchecked_divisor] = *current_call_frame.stack.pop()?;
113+
let [unchecked_dividend, unchecked_divisor] = *self.current_stack().pop()?;
114114

115115
if unchecked_divisor.is_zero() || unchecked_dividend.is_zero() {
116-
current_call_frame.stack.push_zero()?;
116+
self.current_stack().push_zero()?;
117117
return Ok(OpcodeResult::Continue);
118118
}
119119

@@ -123,7 +123,7 @@ impl<'a> VM<'a> {
123123
let unchecked_remainder = match dividend.checked_rem(divisor) {
124124
Some(remainder) => remainder,
125125
None => {
126-
current_call_frame.stack.push_zero()?;
126+
self.current_stack().push_zero()?;
127127
return Ok(OpcodeResult::Continue);
128128
}
129129
};
@@ -134,20 +134,20 @@ impl<'a> VM<'a> {
134134
unchecked_remainder
135135
};
136136

137-
current_call_frame.stack.push1(remainder)?;
137+
self.current_stack().push1(remainder)?;
138138

139139
Ok(OpcodeResult::Continue)
140140
}
141141

142142
// ADDMOD operation
143143
pub fn op_addmod(&mut self) -> Result<OpcodeResult, VMError> {
144-
let current_call_frame = &mut self.current_call_frame;
145-
current_call_frame.increase_consumed_gas(gas_cost::ADDMOD)?;
144+
self.current_call_frame
145+
.increase_consumed_gas(gas_cost::ADDMOD)?;
146146

147-
let [augend, addend, modulus] = *current_call_frame.stack.pop()?;
147+
let [augend, addend, modulus] = *self.current_stack().pop()?;
148148

149149
if modulus.is_zero() {
150-
current_call_frame.stack.push_zero()?;
150+
self.current_stack().push_zero()?;
151151
return Ok(OpcodeResult::Continue);
152152
}
153153

@@ -170,20 +170,20 @@ impl<'a> VM<'a> {
170170
.try_into()
171171
.expect("can't fail because we applied % mod where mod is a U256 value");
172172

173-
current_call_frame.stack.push1(sum_mod)?;
173+
self.current_stack().push1(sum_mod)?;
174174

175175
Ok(OpcodeResult::Continue)
176176
}
177177

178178
// MULMOD operation
179179
pub fn op_mulmod(&mut self) -> Result<OpcodeResult, VMError> {
180-
let current_call_frame = &mut self.current_call_frame;
181-
current_call_frame.increase_consumed_gas(gas_cost::MULMOD)?;
180+
self.current_call_frame
181+
.increase_consumed_gas(gas_cost::MULMOD)?;
182182

183-
let [multiplicand, multiplier, modulus] = *current_call_frame.stack.pop()?;
183+
let [multiplicand, multiplier, modulus] = *self.current_stack().pop()?;
184184

185185
if modulus.is_zero() || multiplicand.is_zero() || multiplier.is_zero() {
186-
current_call_frame.stack.push_zero()?;
186+
self.current_stack().push_zero()?;
187187
return Ok(OpcodeResult::Continue);
188188
}
189189

@@ -203,35 +203,34 @@ impl<'a> VM<'a> {
203203
.try_into()
204204
.expect("can't fail because we applied % mod where mod is a U256 value");
205205

206-
current_call_frame.stack.push1(product_mod)?;
206+
self.current_stack().push1(product_mod)?;
207207

208208
Ok(OpcodeResult::Continue)
209209
}
210210

211211
// EXP operation
212212
pub fn op_exp(&mut self) -> Result<OpcodeResult, VMError> {
213-
let current_call_frame = &mut self.current_call_frame;
214-
let [base, exponent] = *current_call_frame.stack.pop()?;
213+
let [base, exponent] = *self.current_stack().pop()?;
215214

216215
let gas_cost = gas_cost::exp(exponent)?;
217216

218-
current_call_frame.increase_consumed_gas(gas_cost)?;
217+
self.current_call_frame.increase_consumed_gas(gas_cost)?;
219218

220219
let power = base.overflowing_pow(exponent).0;
221-
current_call_frame.stack.push1(power)?;
220+
self.current_stack().push1(power)?;
222221

223222
Ok(OpcodeResult::Continue)
224223
}
225224

226225
// SIGNEXTEND operation
227226
pub fn op_signextend(&mut self) -> Result<OpcodeResult, VMError> {
228-
let current_call_frame = &mut self.current_call_frame;
229-
current_call_frame.increase_consumed_gas(gas_cost::SIGNEXTEND)?;
227+
self.current_call_frame
228+
.increase_consumed_gas(gas_cost::SIGNEXTEND)?;
230229

231-
let [byte_size_minus_one, value_to_extend] = *current_call_frame.stack.pop()?;
230+
let [byte_size_minus_one, value_to_extend] = *self.current_stack().pop()?;
232231

233232
if byte_size_minus_one > U256::from(31) {
234-
current_call_frame.stack.push1(value_to_extend)?;
233+
self.current_stack().push1(value_to_extend)?;
235234
return Ok(OpcodeResult::Continue);
236235
}
237236

@@ -255,7 +254,7 @@ impl<'a> VM<'a> {
255254
value_to_extend | !mask
256255
};
257256

258-
current_call_frame.stack.push1(result)?;
257+
self.current_stack().push1(result)?;
259258

260259
Ok(OpcodeResult::Continue)
261260
}
@@ -265,10 +264,9 @@ impl<'a> VM<'a> {
265264
self.current_call_frame
266265
.increase_consumed_gas(gas_cost::CLZ)?;
267266

268-
let value = self.current_call_frame.stack.pop1()?;
267+
let value = self.current_stack().pop1()?;
269268

270-
self.current_call_frame
271-
.stack
269+
self.current_stack()
272270
.push1(U256::from(value.leading_zeros()))?;
273271

274272
Ok(OpcodeResult::Continue)

0 commit comments

Comments
 (0)