Merge PR: Cache codeanalysis (#5)

* op bitmap cache

* op bitmap cache

* remove useless code

* add verify code
This commit is contained in:
BananaLF 2022-03-16 00:39:45 +08:00 committed by GitHub
parent 034b2bf6ad
commit 520e90f237
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 2 deletions

View file

@ -16,6 +16,11 @@
package vm package vm
import (
"github.com/ethereum/go-ethereum/common"
lru "github.com/hashicorp/golang-lru"
)
const ( const (
set2BitsMask = uint16(0b1100_0000_0000_0000) set2BitsMask = uint16(0b1100_0000_0000_0000)
set3BitsMask = uint16(0b1110_0000_0000_0000) set3BitsMask = uint16(0b1110_0000_0000_0000)
@ -25,6 +30,10 @@ const (
set7BitsMask = uint16(0b1111_1110_0000_0000) set7BitsMask = uint16(0b1111_1110_0000_0000)
) )
const codeBitmapCacheSize = 10000
var codeBitmapCache, _ = lru.NewARC(codeBitmapCacheSize)
// bitvec is a bit vector which maps bytes in a program. // bitvec is a bit vector which maps bytes in a program.
// An unset bit means the byte is an opcode, a set bit means // An unset bit means the byte is an opcode, a set bit means
// it's data (i.e. argument of PUSHxx). // it's data (i.e. argument of PUSHxx).
@ -122,3 +131,17 @@ func codeBitmapInternal(code, bits bitvec) bitvec {
} }
return bits return bits
} }
func codeBitmapWithCache(code []byte, codeHash common.Hash) bitvec {
if (codeHash == emptyCodeHash || codeHash == common.Hash{}) {
return nil
}
if val, ok := codeBitmapCache.Get(codeHash); ok {
return val.(bitvec)
} else {
val := codeBitmap(code)
codeBitmapCache.Add(codeHash, val)
return val
}
}

View file

@ -106,13 +106,13 @@ func (c *Contract) isCode(udest uint64) bool {
// Do we have a contract hash already? // Do we have a contract hash already?
// If we do have a hash, that means it's a 'regular' contract. For regular // If we do have a hash, that means it's a 'regular' contract. For regular
// contracts ( not temporary initcode), we store the analysis in a map // contracts ( not temporary initcode), we store the analysis in a map
if c.CodeHash != (common.Hash{}) { if c.CodeHash != (common.Hash{}) && c.CodeHash != emptyCodeHash {
// Does parent context have the analysis? // Does parent context have the analysis?
analysis, exist := c.jumpdests[c.CodeHash] analysis, exist := c.jumpdests[c.CodeHash]
if !exist { if !exist {
// Do the analysis and save in parent context // Do the analysis and save in parent context
// We do not need to store it in c.analysis // We do not need to store it in c.analysis
analysis = codeBitmap(c.Code) analysis = codeBitmapWithCache(c.Code, c.CodeHash)
c.jumpdests[c.CodeHash] = analysis c.jumpdests[c.CodeHash] = analysis
} }
// Also stash it in current contract for faster access // Also stash it in current contract for faster access