Use math.bits in common math Safe* for performance (#556)

* Use math.bits in comoon math Safe* for performance (the compiler optimizes away  math.bits)

* Prettier code in opExp
This commit is contained in:
Andrew Ashikhmin 2020-05-20 14:31:23 +02:00 committed by GitHub
parent ff23652d50
commit 9c47df0a2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 14 additions and 15 deletions

View File

@ -18,6 +18,7 @@ package math
import ( import (
"fmt" "fmt"
"math/bits"
"strconv" "strconv"
) )
@ -78,22 +79,20 @@ func MustParseUint64(s string) uint64 {
return v return v
} }
// NOTE: The following methods need to be optimised using either bit checking or asm
// SafeSub returns subtraction result and whether overflow occurred. // SafeSub returns subtraction result and whether overflow occurred.
func SafeSub(x, y uint64) (uint64, bool) { func SafeSub(x, y uint64) (uint64, bool) {
return x - y, x < y diff, borrowOut := bits.Sub64(x, y, 0)
return diff, borrowOut != 0
} }
// SafeAdd returns the result and whether overflow occurred. // SafeAdd returns the result and whether overflow occurred.
func SafeAdd(x, y uint64) (uint64, bool) { func SafeAdd(x, y uint64) (uint64, bool) {
return x + y, y > MaxUint64-x sum, carryOut := bits.Add64(x, y, 0)
return sum, carryOut != 0
} }
// SafeMul returns multiplication result and whether overflow occurred. // SafeMul returns multiplication result and whether overflow occurred.
func SafeMul(x, y uint64) (uint64, bool) { func SafeMul(x, y uint64) (uint64, bool) {
if x == 0 || y == 0 { hi, lo := bits.Mul64(x, y)
return 0, false return lo, hi != 0
}
return x * y, y > MaxUint64/x
} }

View File

@ -69,20 +69,20 @@ func opSmod(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]by
func opExp(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) { func opExp(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byte, error) {
base, exponent := callContext.stack.pop(), callContext.stack.peek() base, exponent := callContext.stack.pop(), callContext.stack.peek()
// some shortcuts switch {
if exponent.IsZero() { case exponent.IsZero():
// x ^ 0 == 1 // x ^ 0 == 1
exponent.SetOne() exponent.SetOne()
} else if base.IsZero() { case base.IsZero():
// 0 ^ y, if y != 0, == 0 // 0 ^ y, if y != 0, == 0
exponent.Clear() exponent.Clear()
} else if exponent.LtUint64(2) { // exponent == 1 case exponent.LtUint64(2): // exponent == 1
// x ^ 1 == x // x ^ 1 == x
exponent.Set(&base) exponent.Set(&base)
} else if base.LtUint64(2) { // base == 1 case base.LtUint64(2): // base == 1
// 1 ^ y == 1 // 1 ^ y == 1
exponent.SetOne() exponent.SetOne()
} else if base.LtUint64(3) { // base == 2 case base.LtUint64(3): // base == 2
if exponent.LtUint64(256) { if exponent.LtUint64(256) {
n := uint(exponent.Uint64()) n := uint(exponent.Uint64())
exponent.SetOne() exponent.SetOne()
@ -90,7 +90,7 @@ func opExp(pc *uint64, interpreter *EVMInterpreter, callContext *callCtx) ([]byt
} else { } else {
exponent.Clear() exponent.Clear()
} }
} else { default:
exponent.Exp(&base, exponent) exponent.Exp(&base, exponent)
} }
return nil, nil return nil, nil