aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Holst Swende <martin@swende.se>2018-03-08 20:48:19 +0800
committerPéter Szilágyi <peterke@gmail.com>2018-03-08 20:48:19 +0800
commit4871e25f5fe8d58344f5267ef197662dde018d21 (patch)
treead4cb58d8506a9e93eb2240b53028e7f305bc09b
parent85d5f2c661cd9461e64d6a224076ebc627e14a55 (diff)
downloadgo-tangerine-4871e25f5fe8d58344f5267ef197662dde018d21.tar.gz
go-tangerine-4871e25f5fe8d58344f5267ef197662dde018d21.tar.zst
go-tangerine-4871e25f5fe8d58344f5267ef197662dde018d21.zip
core/vm: optimize eq, slt, sgt and iszero + tests (#16047)
* vm: optimize eq, slt, sgt and iszero + tests * core/vm: fix error in slt/sgt, found by vmtests. Added testcase * core/vm: make slt/sgt cleaner
-rw-r--r--core/vm/instructions.go71
-rw-r--r--core/vm/instructions_test.go15
2 files changed, 61 insertions, 25 deletions
diff --git a/core/vm/instructions.go b/core/vm/instructions.go
index 6daf4e10d..66e804fb7 100644
--- a/core/vm/instructions.go
+++ b/core/vm/instructions.go
@@ -30,6 +30,8 @@ import (
var (
bigZero = new(big.Int)
+ tt255 = math.BigPow(2, 255)
+ tt256 = math.BigPow(2, 256)
errWriteProtection = errors.New("evm: write protection")
errReturnDataOutOfBounds = errors.New("evm: return data out of bounds")
errExecutionReverted = errors.New("evm: execution reverted")
@@ -191,50 +193,71 @@ func opGt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack
}
func opSlt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := math.S256(stack.pop()), math.S256(stack.pop())
- if x.Cmp(math.S256(y)) < 0 {
- stack.push(evm.interpreter.intPool.get().SetUint64(1))
- } else {
- stack.push(new(big.Int))
- }
+ x, y := stack.pop(), stack.peek()
- evm.interpreter.intPool.put(x, y)
+ xSign := x.Cmp(tt255)
+ ySign := y.Cmp(tt255)
+
+ switch {
+ case xSign >= 0 && ySign < 0:
+ y.SetUint64(1)
+
+ case xSign < 0 && ySign >= 0:
+ y.SetUint64(0)
+
+ default:
+ if x.Cmp(y) < 0 {
+ y.SetUint64(1)
+ } else {
+ y.SetUint64(0)
+ }
+ }
+ evm.interpreter.intPool.put(x)
return nil, nil
}
func opSgt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := math.S256(stack.pop()), math.S256(stack.pop())
- if x.Cmp(y) > 0 {
- stack.push(evm.interpreter.intPool.get().SetUint64(1))
- } else {
- stack.push(new(big.Int))
- }
+ x, y := stack.pop(), stack.peek()
- evm.interpreter.intPool.put(x, y)
+ xSign := x.Cmp(tt255)
+ ySign := y.Cmp(tt255)
+
+ switch {
+ case xSign >= 0 && ySign < 0:
+ y.SetUint64(0)
+
+ case xSign < 0 && ySign >= 0:
+ y.SetUint64(1)
+
+ default:
+ if x.Cmp(y) > 0 {
+ y.SetUint64(1)
+ } else {
+ y.SetUint64(0)
+ }
+ }
+ evm.interpreter.intPool.put(x)
return nil, nil
}
func opEq(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x, y := stack.pop(), stack.pop()
+ x, y := stack.pop(), stack.peek()
if x.Cmp(y) == 0 {
- stack.push(evm.interpreter.intPool.get().SetUint64(1))
+ y.SetUint64(1)
} else {
- stack.push(new(big.Int))
+ y.SetUint64(0)
}
-
- evm.interpreter.intPool.put(x, y)
+ evm.interpreter.intPool.put(x)
return nil, nil
}
func opIszero(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
- x := stack.pop()
+ x := stack.peek()
if x.Sign() > 0 {
- stack.push(new(big.Int))
+ x.SetUint64(0)
} else {
- stack.push(evm.interpreter.intPool.get().SetUint64(1))
+ x.SetUint64(1)
}
-
- evm.interpreter.intPool.put(x)
return nil, nil
}
diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go
index eef4328bd..134363bb7 100644
--- a/core/vm/instructions_test.go
+++ b/core/vm/instructions_test.go
@@ -161,6 +161,7 @@ func TestSAR(t *testing.T) {
func TestSGT(t *testing.T) {
tests := []twoOperandTest{
+
{"0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
@@ -171,6 +172,8 @@ func TestSGT(t *testing.T) {
{"8000000000000000000000000000000000000000000000000000000000000001", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
{"8000000000000000000000000000000000000000000000000000000000000001", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000001"},
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
+ {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "0000000000000000000000000000000000000000000000000000000000000001"},
+ {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb", "0000000000000000000000000000000000000000000000000000000000000000"},
}
testTwoOperandOp(t, tests, opSgt)
}
@@ -187,6 +190,8 @@ func TestSLT(t *testing.T) {
{"8000000000000000000000000000000000000000000000000000000000000001", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
{"8000000000000000000000000000000000000000000000000000000000000001", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001"},
+ {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "0000000000000000000000000000000000000000000000000000000000000000"},
+ {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb", "0000000000000000000000000000000000000000000000000000000000000001"},
}
testTwoOperandOp(t, tests, opSlt)
}
@@ -349,7 +354,11 @@ func BenchmarkOpEq(b *testing.B) {
opBenchmark(b, opEq, x, y)
}
-
+func BenchmarkOpEq2(b *testing.B) {
+ x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
+ y := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201fffffffe"
+ opBenchmark(b, opEq, x, y)
+}
func BenchmarkOpAnd(b *testing.B) {
x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
@@ -412,3 +421,7 @@ func BenchmarkOpSAR(b *testing.B) {
opBenchmark(b, opSAR, x, y)
}
+func BenchmarkOpIsZero(b *testing.B) {
+ x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
+ opBenchmark(b, opIszero, x)
+}