From ec1c5e98df3ffce52296dd7a6e190599489af894 Mon Sep 17 00:00:00 2001 From: Valentin Mihov Date: Mon, 11 Sep 2023 18:52:04 +0300 Subject: [PATCH] Never inline the prepare functions (#712) These functions are used for keeping the stack memory clean on the host recursive code paths. EVM supports up to 1024 levels of recursion, so if one is not careful with the stack memory allocations, the stack memory can blow up. Benchmarks show dramatic stack memory improvements when ont inlining these functions. A recursive bomb uses around 1.1MB of stack when these functions are not inlined. If inlined the recursive bombs blow up the stack. --- bins/revme/src/statetest/runner.rs | 7 +------ crates/interpreter/src/instructions/host.rs | 2 ++ crates/revm/src/evm_impl.rs | 2 ++ 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/bins/revme/src/statetest/runner.rs b/bins/revme/src/statetest/runner.rs index de414f9ccb..08a9cf49e4 100644 --- a/bins/revme/src/statetest/runner.rs +++ b/bins/revme/src/statetest/runner.rs @@ -349,12 +349,7 @@ pub fn run( let console_bar = console_bar.clone(); let elapsed = elapsed.clone(); - let mut thread = std::thread::Builder::new(); - - // Allow bigger stack in debug mode to prevent stack overflow errors - //if cfg!(debug_assertions) { - thread = thread.stack_size(4 * 1024 * 1024); - //} + let thread: std::thread::Builder = std::thread::Builder::new(); joins.push( thread diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index b6378b37d4..faa89ca5e4 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -239,6 +239,7 @@ pub fn selfdestruct(interpreter: &mut Interpreter, host: &mut dyn Ho interpreter.instruction_result = InstructionResult::SelfDestruct; } +#[inline(never)] pub fn prepare_create_inputs( interpreter: &mut Interpreter, host: &mut dyn Host, @@ -368,6 +369,7 @@ pub fn static_call(interpreter: &mut Interpreter, host: &mut dyn Hos call_inner::(interpreter, CallScheme::StaticCall, host); } +#[inline(never)] fn prepare_call_inputs( interpreter: &mut Interpreter, scheme: CallScheme, diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index f033dce61f..76bc1f5cce 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -343,6 +343,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, (new_state, logs, gas_used, gas_refunded) } + #[inline(never)] fn prepare_create(&mut self, inputs: &CreateInputs) -> Result { let gas = Gas::new(inputs.gas_limit); @@ -632,6 +633,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, } } + #[inline(never)] fn prepare_call(&mut self, inputs: &CallInputs) -> Result { let gas = Gas::new(inputs.gas_limit); let account = match self