diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 1785ffc139..bfc2cef511 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -17,6 +17,7 @@ package vm import ( + "encoding/binary" "math" "github.com/ethereum/go-ethereum/common" @@ -971,6 +972,23 @@ func opPush1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]by return nil, nil } +// opPush1 is a specialized version of pushN +func opPush2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { + var ( + codeLen = uint64(len(scope.Contract.Code)) + integer = new(uint256.Int) + ) + if *pc+2 < codeLen { + scope.Stack.push(integer.SetUint64(uint64(binary.BigEndian.Uint16(scope.Contract.Code[*pc : *pc+2])))) + } else if *pc+1 < codeLen { + scope.Stack.push(integer.SetUint64(uint64(scope.Contract.Code[*pc]) << 8)) + } else { + scope.Stack.push(integer.Clear()) + } + *pc += 2 + return nil, nil +} + // make push instruction function func makePush(size uint64, pushByteSize int) executionFunc { return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index 0902d17c54..43c5e9cda3 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -972,3 +972,32 @@ func TestPush(t *testing.T) { } } } + +func BenchmarkPush(b *testing.B) { + var ( + code = common.FromHex("0011223344556677889900aabbccddeeff0102030405060708090a0b0c0d0e0ff1e1d1c1b1a19181716151413121") + push32 = makePush(2, 2) + scope = &ScopeContext{ + Memory: nil, + Stack: newstack(), + Contract: &Contract{ + Code: code, + }, + } + pc = new(uint64) + ) + + b.Run("makePush", func(b *testing.B) { + for i := 0; i < b.N; i++ { + push32(pc, nil, scope) + scope.Stack.pop() + } + }) + + b.Run("push", func(b *testing.B) { + for i := 0; i < b.N; i++ { + opPush2(pc, nil, scope) + scope.Stack.pop() + } + }) +}