Skip to content

Conversation

@gakonst
Copy link
Collaborator

@gakonst gakonst commented Jan 30, 2026

Summary

Adds an alternative dispatch mechanism for the EVM interpreter that uses a giant match statement instead of indirect function pointer table lookup. This is inspired by evmone's computed goto dispatch approach.

Motivation

The current dispatch uses an indirect function call through a table:

let instruction = unsafe { instruction_table.get_unchecked(opcode as usize) };
instruction.execute(context);

Indirect calls can hurt branch prediction on modern CPUs. A match-based dispatch allows the compiler to potentially generate better code (jump tables, better branch prediction hints).

Changes

  • crates/interpreter/src/match_dispatch.rs: New module with:
    • static_gas(opcode: u8) -> u64: Const fn for compile-time gas cost lookup
    • step_match(): Single-step execution using match dispatch
    • run_match(): Main interpreter loop using match dispatch
    • Cold path annotations (#[cold], #[inline(never)]) for CREATE/CALL/SELFDESTRUCT
  • crates/interpreter/Cargo.toml: Add match-dispatch feature flag
  • crates/interpreter/src/lib.rs: Conditionally include the module

Usage

Enable with:

revm-interpreter = { version = "...", features = ["match-dispatch"] }

Then use:

interpreter.run_match(&mut host)

Testing

The feature is behind a flag and does not affect existing behavior. Added a basic test to verify the dispatch works correctly.

Thread Context

https://ampcode.com/threads/T-019c0f71-79a8-72b9-8c8d-bb4290bb9294

gakonst and others added 2 commits January 30, 2026 15:27
This adds an alternative dispatch mechanism using a match statement instead
of indirect function pointer table lookup. Inspired by evmone's computed goto
dispatch approach.

Key changes:
- Add match_dispatch.rs with step_match() and run_match() methods
- Add match-dispatch feature flag (disabled by default)
- Const fn static_gas() table for compile-time gas lookups
- Cold path annotations for CREATE/CALL/SELFDESTRUCT opcodes

The match-based dispatch can improve branch prediction on modern CPUs by
allowing the compiler to generate better jump tables vs indirect calls.

Amp-Thread-ID: https://ampcode.com/threads/T-019c0f71-79a8-72b9-8c8d-bb4290bb9294
Co-authored-by: Amp <[email protected]>
…td for match-dispatch

- Remove interpreter_pool module that was incorrectly merged (from separate PR)
- Add missing documentation for step_match and run_match methods
- Require std feature for match-dispatch module (uses std::vec::Vec)

Amp-Thread-ID: https://ampcode.com/threads/T-019c0f71-79a8-72b9-8c8d-bb4290bb9294
Co-authored-by: Amp <[email protected]>
@codspeed-hq
Copy link

codspeed-hq bot commented Jan 30, 2026

Merging this PR will degrade performance by 34.34%

❌ 136 regressed benchmarks
✅ 37 untouched benchmarks

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
ADDMOD_50 27.5 µs 31.6 µs -13.01%
ADDRESS_50 18.1 µs 20.1 µs -9.63%
ADD_50 23.3 µs 27.4 µs -15.12%
AND_50 23.3 µs 27.5 µs -15.37%
BYTE_50 23.6 µs 27.8 µs -14.93%
CALLVALUE_50 18.1 µs 19.8 µs -8.81%
CALLDATALOAD_50 57.7 µs 62.1 µs -6.98%
CALLDATACOPY_50 57.4 µs 60.4 µs -4.84%
CALLER_50 18.1 µs 20 µs -9.65%
CALLDATASIZE_50 18.1 µs 20 µs -9.39%
PUSH11_50 18.5 µs 20.5 µs -9.47%
CHAINID_50 18.1 µs 20 µs -9.67%
PUSH12_50 18.5 µs 20.4 µs -9.25%
PUSH13_50 18.5 µs 20.5 µs -9.6%
CALL_50 90.2 µs 99.9 µs -9.73%
PUSH14_50 18.6 µs 20.5 µs -9.45%
PUSH15_50 18.7 µs 20.6 µs -9.28%
PUSH16_50 18.5 µs 20.5 µs -9.61%
CLZ_50 23.6 µs 27.9 µs -15.2%
CODESIZE_50 18.2 µs 20.1 µs -9.49%
... ... ... ... ...

ℹ️ Only the first 20 benchmarks are displayed. Go to the app to view all benchmarks.


Comparing dragan/match-dispatch (2e11c22) with main (fc750ca)

Open in CodSpeed

gakonst and others added 3 commits January 30, 2026 15:58
The match-based dispatch provides better branch prediction compared to
function pointer table lookup. Enabling by default for better out-of-box
performance.

Amp-Thread-ID: https://ampcode.com/threads/T-019c0f71-79a8-72b9-8c8d-bb4290bb9294
Co-authored-by: Amp <[email protected]>
…n_plain

- Remove match-dispatch feature flag
- Remove separate match_dispatch.rs module
- Integrate static_gas() and execute_instruction() directly into interpreter.rs
- step() now uses match-based dispatch by default for better branch prediction
- Keeps backward compatibility with instruction_table parameter (now unused)

This provides the performance benefits of match-based dispatch without
requiring a feature flag, inspired by evmone's computed goto approach.

Amp-Thread-ID: https://ampcode.com/threads/T-019c0f71-79a8-72b9-8c8d-bb4290bb9294
Co-authored-by: Amp <[email protected]>
…ters

- Rename imports: host -> host_instructions, stack -> stack_instructions
- Avoids conflict between crate::instructions::host and 'host' parameter
- Avoids conflict between interpreter::stack module and instructions::stack

Amp-Thread-ID: https://ampcode.com/threads/T-019c0f71-79a8-72b9-8c8d-bb4290bb9294
Co-authored-by: Amp <[email protected]>
@rakita rakita closed this Jan 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants