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

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