forked from cerc-io/plugeth
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
This commit is contained in:
parent
85d5f2c661
commit
4871e25f5f
@ -30,6 +30,8 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
bigZero = new(big.Int)
|
bigZero = new(big.Int)
|
||||||
|
tt255 = math.BigPow(2, 255)
|
||||||
|
tt256 = math.BigPow(2, 256)
|
||||||
errWriteProtection = errors.New("evm: write protection")
|
errWriteProtection = errors.New("evm: write protection")
|
||||||
errReturnDataOutOfBounds = errors.New("evm: return data out of bounds")
|
errReturnDataOutOfBounds = errors.New("evm: return data out of bounds")
|
||||||
errExecutionReverted = errors.New("evm: execution reverted")
|
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) {
|
func opSlt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
x, y := math.S256(stack.pop()), math.S256(stack.pop())
|
x, y := stack.pop(), stack.peek()
|
||||||
if x.Cmp(math.S256(y)) < 0 {
|
|
||||||
stack.push(evm.interpreter.intPool.get().SetUint64(1))
|
|
||||||
} else {
|
|
||||||
stack.push(new(big.Int))
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func opSgt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
func opSgt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
x, y := math.S256(stack.pop()), math.S256(stack.pop())
|
x, y := stack.pop(), stack.peek()
|
||||||
if x.Cmp(y) > 0 {
|
|
||||||
stack.push(evm.interpreter.intPool.get().SetUint64(1))
|
|
||||||
} else {
|
|
||||||
stack.push(new(big.Int))
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func opEq(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
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 {
|
if x.Cmp(y) == 0 {
|
||||||
stack.push(evm.interpreter.intPool.get().SetUint64(1))
|
y.SetUint64(1)
|
||||||
} else {
|
} else {
|
||||||
stack.push(new(big.Int))
|
y.SetUint64(0)
|
||||||
}
|
}
|
||||||
|
evm.interpreter.intPool.put(x)
|
||||||
evm.interpreter.intPool.put(x, y)
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func opIszero(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
func opIszero(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
|
||||||
x := stack.pop()
|
x := stack.peek()
|
||||||
if x.Sign() > 0 {
|
if x.Sign() > 0 {
|
||||||
stack.push(new(big.Int))
|
x.SetUint64(0)
|
||||||
} else {
|
} else {
|
||||||
stack.push(evm.interpreter.intPool.get().SetUint64(1))
|
x.SetUint64(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
evm.interpreter.intPool.put(x)
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,6 +161,7 @@ func TestSAR(t *testing.T) {
|
|||||||
|
|
||||||
func TestSGT(t *testing.T) {
|
func TestSGT(t *testing.T) {
|
||||||
tests := []twoOperandTest{
|
tests := []twoOperandTest{
|
||||||
|
|
||||||
{"0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
|
{"0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
|
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
|
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
@ -171,6 +172,8 @@ func TestSGT(t *testing.T) {
|
|||||||
{"8000000000000000000000000000000000000000000000000000000000000001", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
|
{"8000000000000000000000000000000000000000000000000000000000000001", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
{"8000000000000000000000000000000000000000000000000000000000000001", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000001"},
|
{"8000000000000000000000000000000000000000000000000000000000000001", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000001"},
|
||||||
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
|
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "0000000000000000000000000000000000000000000000000000000000000001"},
|
||||||
|
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
}
|
}
|
||||||
testTwoOperandOp(t, tests, opSgt)
|
testTwoOperandOp(t, tests, opSgt)
|
||||||
}
|
}
|
||||||
@ -187,6 +190,8 @@ func TestSLT(t *testing.T) {
|
|||||||
{"8000000000000000000000000000000000000000000000000000000000000001", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
|
{"8000000000000000000000000000000000000000000000000000000000000001", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
{"8000000000000000000000000000000000000000000000000000000000000001", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
|
{"8000000000000000000000000000000000000000000000000000000000000001", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001"},
|
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001"},
|
||||||
|
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "0000000000000000000000000000000000000000000000000000000000000000"},
|
||||||
|
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb", "0000000000000000000000000000000000000000000000000000000000000001"},
|
||||||
}
|
}
|
||||||
testTwoOperandOp(t, tests, opSlt)
|
testTwoOperandOp(t, tests, opSlt)
|
||||||
}
|
}
|
||||||
@ -349,7 +354,11 @@ func BenchmarkOpEq(b *testing.B) {
|
|||||||
|
|
||||||
opBenchmark(b, opEq, x, y)
|
opBenchmark(b, opEq, x, y)
|
||||||
}
|
}
|
||||||
|
func BenchmarkOpEq2(b *testing.B) {
|
||||||
|
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
|
||||||
|
y := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201fffffffe"
|
||||||
|
opBenchmark(b, opEq, x, y)
|
||||||
|
}
|
||||||
func BenchmarkOpAnd(b *testing.B) {
|
func BenchmarkOpAnd(b *testing.B) {
|
||||||
x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
|
x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
|
||||||
y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
|
y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
|
||||||
@ -412,3 +421,7 @@ func BenchmarkOpSAR(b *testing.B) {
|
|||||||
|
|
||||||
opBenchmark(b, opSAR, x, y)
|
opBenchmark(b, opSAR, x, y)
|
||||||
}
|
}
|
||||||
|
func BenchmarkOpIsZero(b *testing.B) {
|
||||||
|
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
|
||||||
|
opBenchmark(b, opIszero, x)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user