From d7d246dfd4cea3507eddfd35d74de65a787d6148 Mon Sep 17 00:00:00 2001 From: redhdx Date: Wed, 13 Mar 2024 14:04:59 +0800 Subject: [PATCH] feature(op-geth): optimize validJumpdest --- core/opcodeCompiler/compiler/OpCodeCache.go | 20 ++++++++++++++++++- .../compiler/opcodeProcessor.go | 15 ++++++++++++++ core/vm/contract.go | 14 +++++++++++-- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/core/opcodeCompiler/compiler/OpCodeCache.go b/core/opcodeCompiler/compiler/OpCodeCache.go index 349d9465ed..27a023bc9a 100644 --- a/core/opcodeCompiler/compiler/OpCodeCache.go +++ b/core/opcodeCompiler/compiler/OpCodeCache.go @@ -3,6 +3,7 @@ package compiler import ( "encoding/json" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/lru" "github.com/ethereum/go-ethereum/log" "os" "os/signal" @@ -20,6 +21,7 @@ type OptCode []byte type OpCodeCache struct { opcodesCache map[common.Address]OptCode + bitvecCache *lru.SizeConstrainedCache[common.Hash, []byte] codeCacheMutex sync.RWMutex codeCacheSize uint64 } @@ -47,6 +49,18 @@ func (c *OpCodeCache) GetCachedCode(address common.Address) OptCode { return processedCode } +func (c *OpCodeCache) GetBitvecCache(codeHash common.Hash) []byte { + bitvec, ok := c.bitvecCache.Get(codeHash) + if !ok { + bitvec = nil + } + return bitvec +} + +func (c *OpCodeCache) AddBitvecCache(codeHash common.Hash, bitvec []byte) { + c.bitvecCache.Add(codeHash, bitvec) +} + func (c *OpCodeCache) UpdateCodeCache(address common.Address, code OptCode) error { c.codeCacheMutex.Lock() @@ -70,11 +84,15 @@ func (c *OpCodeCache) UpdateCodeCache(address common.Address, code OptCode) erro var opcodeCache *OpCodeCache -const codeCacheFileName = "codecache.json" +const ( + codeCacheFileName = "codecache.json" + bitvecCacheSize = 64 * 1024 * 1024 +) func init() { opcodeCache = &OpCodeCache{ opcodesCache: make(map[common.Address]OptCode, CodeCacheGCThreshold>>10), + bitvecCache: lru.NewSizeConstrainedCache[common.Hash, []byte](bitvecCacheSize), codeCacheMutex: sync.RWMutex{}, } diff --git a/core/opcodeCompiler/compiler/opcodeProcessor.go b/core/opcodeCompiler/compiler/opcodeProcessor.go index 3f7256c703..849f71e570 100644 --- a/core/opcodeCompiler/compiler/opcodeProcessor.go +++ b/core/opcodeCompiler/compiler/opcodeProcessor.go @@ -83,6 +83,21 @@ func LoadOptimizedCode(address common.Address) OptCode { } +func LoadBitvec(codeHash common.Hash) []byte { + if !enabled { + return nil + } + bitvec := codeCache.GetBitvecCache(codeHash) + return bitvec +} + +func StoreBitvec(codeHash common.Hash, bitvec []byte) { + if !enabled { + return + } + codeCache.AddBitvecCache(codeHash, bitvec) +} + func GenOrLoadOptimizedCode(address common.Address, code []byte) { if !enabled { return diff --git a/core/vm/contract.go b/core/vm/contract.go index d53b5e69b1..c75556a4fc 100644 --- a/core/vm/contract.go +++ b/core/vm/contract.go @@ -18,6 +18,7 @@ package vm import ( "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/opcodeCompiler/compiler" "github.com/holiman/uint256" "math/big" ) @@ -115,8 +116,17 @@ func (c *Contract) isCode(udest uint64) bool { if !exist { // Do the analysis and save in parent context // We do not need to store it in c.analysis - analysis = codeBitmap(c.Code) - c.jumpdests[c.CodeHash] = analysis + if c.optimized { + analysis = compiler.LoadBitvec(c.CodeHash) + if analysis == nil { + analysis = codeBitmap(c.Code) + compiler.StoreBitvec(c.CodeHash, analysis) + } + c.jumpdests[c.CodeHash] = analysis + } else { + analysis = codeBitmap(c.Code) + c.jumpdests[c.CodeHash] = analysis + } } // Also stash it in current contract for faster access c.analysis = analysis