Skip to content

Commit 4871e25

Browse files
holimankaralabe
authored andcommitted
core/vm: optimize eq, slt, sgt and iszero + tests (ethereum#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
1 parent 85d5f2c commit 4871e25

File tree

2 files changed

+61
-25
lines changed

2 files changed

+61
-25
lines changed

core/vm/instructions.go

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import (
3030

3131
var (
3232
bigZero = new(big.Int)
33+
tt255 = math.BigPow(2, 255)
34+
tt256 = math.BigPow(2, 256)
3335
errWriteProtection = errors.New("evm: write protection")
3436
errReturnDataOutOfBounds = errors.New("evm: return data out of bounds")
3537
errExecutionReverted = errors.New("evm: execution reverted")
@@ -191,50 +193,71 @@ func opGt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack
191193
}
192194

193195
func opSlt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
194-
x, y := math.S256(stack.pop()), math.S256(stack.pop())
195-
if x.Cmp(math.S256(y)) < 0 {
196-
stack.push(evm.interpreter.intPool.get().SetUint64(1))
197-
} else {
198-
stack.push(new(big.Int))
199-
}
196+
x, y := stack.pop(), stack.peek()
200197

201-
evm.interpreter.intPool.put(x, y)
198+
xSign := x.Cmp(tt255)
199+
ySign := y.Cmp(tt255)
200+
201+
switch {
202+
case xSign >= 0 && ySign < 0:
203+
y.SetUint64(1)
204+
205+
case xSign < 0 && ySign >= 0:
206+
y.SetUint64(0)
207+
208+
default:
209+
if x.Cmp(y) < 0 {
210+
y.SetUint64(1)
211+
} else {
212+
y.SetUint64(0)
213+
}
214+
}
215+
evm.interpreter.intPool.put(x)
202216
return nil, nil
203217
}
204218

205219
func opSgt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
206-
x, y := math.S256(stack.pop()), math.S256(stack.pop())
207-
if x.Cmp(y) > 0 {
208-
stack.push(evm.interpreter.intPool.get().SetUint64(1))
209-
} else {
210-
stack.push(new(big.Int))
211-
}
220+
x, y := stack.pop(), stack.peek()
212221

213-
evm.interpreter.intPool.put(x, y)
222+
xSign := x.Cmp(tt255)
223+
ySign := y.Cmp(tt255)
224+
225+
switch {
226+
case xSign >= 0 && ySign < 0:
227+
y.SetUint64(0)
228+
229+
case xSign < 0 && ySign >= 0:
230+
y.SetUint64(1)
231+
232+
default:
233+
if x.Cmp(y) > 0 {
234+
y.SetUint64(1)
235+
} else {
236+
y.SetUint64(0)
237+
}
238+
}
239+
evm.interpreter.intPool.put(x)
214240
return nil, nil
215241
}
216242

217243
func opEq(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
218-
x, y := stack.pop(), stack.pop()
244+
x, y := stack.pop(), stack.peek()
219245
if x.Cmp(y) == 0 {
220-
stack.push(evm.interpreter.intPool.get().SetUint64(1))
246+
y.SetUint64(1)
221247
} else {
222-
stack.push(new(big.Int))
248+
y.SetUint64(0)
223249
}
224-
225-
evm.interpreter.intPool.put(x, y)
250+
evm.interpreter.intPool.put(x)
226251
return nil, nil
227252
}
228253

229254
func opIszero(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
230-
x := stack.pop()
255+
x := stack.peek()
231256
if x.Sign() > 0 {
232-
stack.push(new(big.Int))
257+
x.SetUint64(0)
233258
} else {
234-
stack.push(evm.interpreter.intPool.get().SetUint64(1))
259+
x.SetUint64(1)
235260
}
236-
237-
evm.interpreter.intPool.put(x)
238261
return nil, nil
239262
}
240263

core/vm/instructions_test.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ func TestSAR(t *testing.T) {
161161

162162
func TestSGT(t *testing.T) {
163163
tests := []twoOperandTest{
164+
164165
{"0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
165166
{"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
166167
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
@@ -171,6 +172,8 @@ func TestSGT(t *testing.T) {
171172
{"8000000000000000000000000000000000000000000000000000000000000001", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
172173
{"8000000000000000000000000000000000000000000000000000000000000001", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000001"},
173174
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
175+
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "0000000000000000000000000000000000000000000000000000000000000001"},
176+
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb", "0000000000000000000000000000000000000000000000000000000000000000"},
174177
}
175178
testTwoOperandOp(t, tests, opSgt)
176179
}
@@ -187,6 +190,8 @@ func TestSLT(t *testing.T) {
187190
{"8000000000000000000000000000000000000000000000000000000000000001", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000"},
188191
{"8000000000000000000000000000000000000000000000000000000000000001", "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0000000000000000000000000000000000000000000000000000000000000000"},
189192
{"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "8000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001"},
193+
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "0000000000000000000000000000000000000000000000000000000000000000"},
194+
{"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb", "0000000000000000000000000000000000000000000000000000000000000001"},
190195
}
191196
testTwoOperandOp(t, tests, opSlt)
192197
}
@@ -349,7 +354,11 @@ func BenchmarkOpEq(b *testing.B) {
349354

350355
opBenchmark(b, opEq, x, y)
351356
}
352-
357+
func BenchmarkOpEq2(b *testing.B) {
358+
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
359+
y := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201fffffffe"
360+
opBenchmark(b, opEq, x, y)
361+
}
353362
func BenchmarkOpAnd(b *testing.B) {
354363
x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
355364
y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff"
@@ -412,3 +421,7 @@ func BenchmarkOpSAR(b *testing.B) {
412421

413422
opBenchmark(b, opSAR, x, y)
414423
}
424+
func BenchmarkOpIsZero(b *testing.B) {
425+
x := "FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff"
426+
opBenchmark(b, opIszero, x)
427+
}

0 commit comments

Comments
 (0)