From 0cc0ce611ce32f054276a7cd7c07119c83e55a97 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Fri, 4 Aug 2023 14:33:16 +0200 Subject: [PATCH] perf: cast instruction functions to `fn` The compiler generates much more favorable assembly if all the functions are casted to a `fn(_, _)` pointer before calling them. See for more information. --- crates/interpreter/src/instructions/opcode.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/crates/interpreter/src/instructions/opcode.rs b/crates/interpreter/src/instructions/opcode.rs index 0692c28b87a..b9380b478bc 100644 --- a/crates/interpreter/src/instructions/opcode.rs +++ b/crates/interpreter/src/instructions/opcode.rs @@ -25,10 +25,12 @@ macro_rules! opcodes { map }; - // Requires `inline_const` and `const_mut_refs` unstable features + type Instruction = fn(&mut Interpreter, &mut dyn Host); + + // Requires `inline_const` and `const_mut_refs` unstable features, + // but provides ~+2% extra performance. // See: https://github.com/bluealloy/revm/issues/310#issuecomment-1664381513 /* - type Instruction = fn(&mut Interpreter, &mut dyn Host); type InstructionTable = [Instruction; 256]; const fn make_instruction_table() -> InstructionTable { @@ -51,10 +53,13 @@ macro_rules! opcodes { /// Evaluates the opcode in the given context. #[inline(always)] pub(crate) fn eval(opcode: u8, interpreter: &mut Interpreter, host: &mut dyn Host) { - match opcode { - $($name => $f(interpreter, host),)* - _ => control::not_found(interpreter, host), - } + // See https://github.com/bluealloy/revm/issues/310#issuecomment-1664381513 + // for previous efforts on optimizing this function. + let f: Instruction = match opcode { + $($name => $f as Instruction,)* + _ => control::not_found as Instruction, + }; + f(interpreter, host); } }; }