Skip to content

Commit d5a7993

Browse files
committed
core/vm: Use a bitmap instead of a map for jumpdest analysis
t push --force
1 parent 0424192 commit d5a7993

File tree

1 file changed

+12
-14
lines changed

1 file changed

+12
-14
lines changed

core/vm/analysis.go

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,41 +22,39 @@ import (
2222
"github.com/ethereum/go-ethereum/common"
2323
)
2424

25-
var bigMaxUint64 = new(big.Int).SetUint64(^uint64(0))
26-
2725
// destinations stores one map per contract (keyed by hash of code).
2826
// The maps contain an entry for each location of a JUMPDEST
2927
// instruction.
30-
type destinations map[common.Hash]map[uint64]struct{}
28+
type destinations map[common.Hash][]byte
3129

3230
// has checks whether code has a JUMPDEST at dest.
3331
func (d destinations) has(codehash common.Hash, code []byte, dest *big.Int) bool {
34-
// PC cannot go beyond len(code) and certainly can't be bigger than 64bits.
32+
// PC cannot go beyond len(code) and certainly can't be bigger than 63bits.
3533
// Don't bother checking for JUMPDEST in that case.
36-
if dest.Cmp(bigMaxUint64) > 0 {
34+
udest := dest.Uint64()
35+
if dest.BitLen() >= 63 || udest >= uint64(len(code)) {
3736
return false
3837
}
38+
3939
m, analysed := d[codehash]
4040
if !analysed {
4141
m = jumpdests(code)
4242
d[codehash] = m
4343
}
44-
_, ok := m[dest.Uint64()]
45-
return ok
44+
return (m[udest/8] & (1 << (udest % 8))) != 0
4645
}
4746

4847
// jumpdests creates a map that contains an entry for each
4948
// PC location that is a JUMPDEST instruction.
50-
func jumpdests(code []byte) map[uint64]struct{} {
51-
m := make(map[uint64]struct{})
49+
func jumpdests(code []byte) []byte {
50+
m := make([]byte, len(code)/8+1)
5251
for pc := uint64(0); pc < uint64(len(code)); pc++ {
53-
var op OpCode = OpCode(code[pc])
54-
switch op {
55-
case PUSH1, PUSH2, PUSH3, PUSH4, PUSH5, PUSH6, PUSH7, PUSH8, PUSH9, PUSH10, PUSH11, PUSH12, PUSH13, PUSH14, PUSH15, PUSH16, PUSH17, PUSH18, PUSH19, PUSH20, PUSH21, PUSH22, PUSH23, PUSH24, PUSH25, PUSH26, PUSH27, PUSH28, PUSH29, PUSH30, PUSH31, PUSH32:
52+
op := OpCode(code[pc])
53+
if op == JUMPDEST {
54+
m[pc/8] |= 1 << (pc % 8)
55+
} else if op >= PUSH1 && op <= PUSH32 {
5656
a := uint64(op) - uint64(PUSH1) + 1
5757
pc += a
58-
case JUMPDEST:
59-
m[pc] = struct{}{}
6058
}
6159
}
6260
return m

0 commit comments

Comments
 (0)