From 301d5a8b27581ca7f351475984c24e82613b5662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20IRMAK?= Date: Fri, 20 Jun 2025 14:41:54 +0300 Subject: [PATCH 1/2] core/vm: hoist jumptable nil-check out of the interpreter loop --- core/vm/interpreter.go | 12 +++++++----- core/vm/interpreter_test.go | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index d0e5967e6e77..1321888512d9 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -181,10 +181,11 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( } var ( - op OpCode // current opcode - mem = NewMemory() // bound memory - stack = newstack() // local stack - callContext = &ScopeContext{ + op OpCode // current opcode + jumpTable *JumpTable = in.table + mem = NewMemory() // bound memory + stack = newstack() // local stack + callContext = &ScopeContext{ Memory: mem, Stack: stack, Contract: contract, @@ -227,6 +228,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( // explicit STOP, RETURN or SELFDESTRUCT is executed, an error occurred during // the execution of one of the operations or until the done flag is set by the // parent context. + _ = jumpTable[0] // nil-check the jumpTable out of the loop for { if debug { // Capture pre-execution values for tracing. @@ -247,7 +249,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) ( // Get the operation from the jump table and validate the stack to ensure there are // enough stack items available to perform the operation. op = contract.GetOp(pc) - operation := in.table[op] + operation := jumpTable[op] cost = operation.constantGas // For tracing // Validate stack if sLen := stack.len(); sLen < operation.minStack { diff --git a/core/vm/interpreter_test.go b/core/vm/interpreter_test.go index 0b93dd59e7e0..386795bd6fab 100644 --- a/core/vm/interpreter_test.go +++ b/core/vm/interpreter_test.go @@ -26,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" + "github.com/stretchr/testify/require" ) var loopInterruptTests = []string{ @@ -74,3 +75,20 @@ func TestLoopInterrupt(t *testing.T) { } } } + +func BenchmarkLoop(b *testing.B) { + address := common.BytesToAddress([]byte("contract")) + vmctx := BlockContext{ + Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {}, + } + + statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) + statedb.CreateAccount(address) + statedb.SetCode(address, common.Hex2Bytes(loopInterruptTests[0])) + statedb.Finalise(true) + + evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{}) + b.ResetTimer() + _, _, err := evm.Call(common.Address{}, address, nil, uint64(b.N*100), new(uint256.Int)) + require.EqualError(b, err, ErrOutOfGas.Error()) +} From 3fc9d0ea0eeaec6618b8e66b6326012c18242c20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20IRMAK?= Date: Thu, 26 Jun 2025 12:15:07 +0300 Subject: [PATCH 2/2] remove bench --- core/vm/interpreter_test.go | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/core/vm/interpreter_test.go b/core/vm/interpreter_test.go index 386795bd6fab..0b93dd59e7e0 100644 --- a/core/vm/interpreter_test.go +++ b/core/vm/interpreter_test.go @@ -26,7 +26,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" - "github.com/stretchr/testify/require" ) var loopInterruptTests = []string{ @@ -75,20 +74,3 @@ func TestLoopInterrupt(t *testing.T) { } } } - -func BenchmarkLoop(b *testing.B) { - address := common.BytesToAddress([]byte("contract")) - vmctx := BlockContext{ - Transfer: func(StateDB, common.Address, common.Address, *uint256.Int) {}, - } - - statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) - statedb.CreateAccount(address) - statedb.SetCode(address, common.Hex2Bytes(loopInterruptTests[0])) - statedb.Finalise(true) - - evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{}) - b.ResetTimer() - _, _, err := evm.Call(common.Address{}, address, nil, uint64(b.N*100), new(uint256.Int)) - require.EqualError(b, err, ErrOutOfGas.Error()) -}