Skip to content

Commit

Permalink
remove once
Browse files Browse the repository at this point in the history
  • Loading branch information
sunny2022da committed Mar 11, 2024
1 parent e2695a3 commit e6584c3
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 105 deletions.
4 changes: 2 additions & 2 deletions cmd/evm/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"github.com/ethereum/go-ethereum/cmd/evm/internal/compiler"
compiler2 "github.com/ethereum/go-ethereum/core/opcodeCompiler/compiler"
"io"
"math/big"
Expand All @@ -29,7 +30,6 @@ import (
"testing"
"time"

"github.com/ethereum/go-ethereum/cmd/evm/internal/compiler"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
Expand Down Expand Up @@ -221,7 +221,7 @@ func runCmd(ctx *cli.Context) error {
}

if runtimeConfig.EVMConfig.EnableOpcodeOptimizations {
compiler2.GetOpcodeProcessorInstance().EnableOptimization()
compiler2.EnableOptimization()
}
if cpuProfilePath := ctx.String(CPUProfileFlag.Name); cpuProfilePath != "" {
f, err := os.Create(cpuProfilePath)
Expand Down
4 changes: 2 additions & 2 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -1926,7 +1926,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if ctx.IsSet(VMOpcodeOptimizeFlag.Name) {
// TODO(fjl): force-enable this in --dev mode
cfg.EnableOpcodeOptimizing = ctx.Bool(VMOpcodeOptimizeFlag.Name)
compiler.GetOpcodeProcessorInstance().EnableOptimization()
compiler.EnableOptimization()
}

if ctx.IsSet(RPCGlobalGasCapFlag.Name) {
Expand Down Expand Up @@ -2376,7 +2376,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
EnableOpcodeOptimizations: ctx.Bool(VMOpcodeOptimizeFlag.Name)}

if vmcfg.EnableOpcodeOptimizations {
compiler.GetOpcodeProcessorInstance()
compiler.EnableOptimization()
}
// Disable transaction indexing/unindexing by default.
chain, err := core.NewBlockChain(chainDb, cache, gspec, nil, engine, vmcfg, nil, nil)
Expand Down
53 changes: 24 additions & 29 deletions core/opcodeCompiler/compiler/OpCodeCache.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ type OpCodeCache struct {
}

func (c *OpCodeCache) GetCachedCode(address common.Address, codeHash common.Hash) OptCode {

c.codeCacheMutex.RLock()

processedCode, ok := c.opcodesCache[address][codeHash]
if !ok {
processedCode = nil
Expand Down Expand Up @@ -80,34 +78,35 @@ func (c *OpCodeCache) UpdateCodeCache(address common.Address, code OptCode, code
return nil
}

var once sync.Once
var opcodeCache *OpCodeCache

const codeCacheFileName = "codecache.json"

func getOpCodeCacheInstance() *OpCodeCache {
once.Do(func() {
opcodeCache = &OpCodeCache{
opcodesCache: make(map[common.Address]map[common.Hash]OptCode, CodeCacheGCThreshold>>10),
codeCacheMutex: sync.RWMutex{},
}
// Try load code cache
loadCodeCacheFromFile(codeCacheFileName, opcodeCache)
// Handle Sigusr2 signal
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGUSR2)
go func() {
for { // Infinite loop to wait for signals
signal := <-sigCh
switch signal {
case syscall.SIGUSR2:
opcodeCache.codeCacheMutex.RLock()
dumpCodeCache(codeCacheFileName, opcodeCache.opcodesCache)
opcodeCache.codeCacheMutex.RUnlock()
}
func init() {
opcodeCache = &OpCodeCache{
opcodesCache: make(map[common.Address]map[common.Hash]OptCode, CodeCacheGCThreshold>>10),
codeCacheMutex: sync.RWMutex{},
}

// Try load code cache
loadCodeCacheFromFile(codeCacheFileName, opcodeCache)
// Handle Sigusr2 signal
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGUSR2)
go func() {
for { // Infinite loop to wait for signals
signal := <-sigCh
switch signal {
case syscall.SIGUSR2:
opcodeCache.codeCacheMutex.RLock()
dumpCodeCache(codeCacheFileName, opcodeCache.opcodesCache)
opcodeCache.codeCacheMutex.RUnlock()
}
}()
})
}
}()
}

func getOpCodeCacheInstance() *OpCodeCache {
return opcodeCache
}

Expand All @@ -120,10 +119,6 @@ func dumpCodeCache(filename string, codeCache map[common.Address]map[common.Hash
return
}

// Print JSON to standard output
//fmt.Println("Data JSON:")
// fmt.Println(string(jsonData))

log.Info("OpcodeCache Dump:", "File", filename)
// Optional: write JSON to file
err = writeToFile(filename, jsonData)
Expand Down
104 changes: 49 additions & 55 deletions core/opcodeCompiler/compiler/opcodeProcessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,22 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/holiman/uint256"
"runtime"
"sync"
)

type CodeType uint8

var ErrFailPreprocessing = errors.New("fail to do preprocessing")
var ErrOptiDisabled = errors.New("Opcode optimization is disabled")

var initOnce sync.Once
var opcodeProcessor *OpcodeProcessor
var opCodeOptimizationInited bool

const taskChannelSize = 1024 * 1024

type OpcodeProcessor struct {
var (
enabled bool
codeCache *OpCodeCache
taskChannel chan optimizeTask
}
)

type OpCodeProcessorConfig struct {
DoOpcodeFusion bool
Expand All @@ -44,128 +42,124 @@ type optimizeTask struct {
rawCode []byte
}

func GetOpcodeProcessorInstance() *OpcodeProcessor {
initOnce.Do(func() {
opcodeProcessor = &OpcodeProcessor{
enabled: false,
codeCache: nil,
taskChannel: make(chan optimizeTask, taskChannelSize),
}
// start task processors.
taskNumber := runtime.NumCPU() * 3 / 8
if taskNumber < 1 {
taskNumber = 1
}
func init() {
if opCodeOptimizationInited {
return
}
opCodeOptimizationInited = true
enabled = false
codeCache = nil
taskChannel = make(chan optimizeTask, taskChannelSize)
// start task processors.
taskNumber := runtime.NumCPU() * 3 / 8
if taskNumber < 1 {
taskNumber = 1
}
codeCache = getOpCodeCacheInstance()

for i := 0; i < taskNumber; i++ {
go opcodeProcessor.taskProcessor()
}
})
return opcodeProcessor
for i := 0; i < taskNumber; i++ {
go taskProcessor()
}
}

func (p *OpcodeProcessor) EnableOptimization() {
if p.enabled {
func EnableOptimization() {
if enabled {
return
}
p.enabled = true
p.codeCache = getOpCodeCacheInstance()
enabled = true
}

func (p *OpcodeProcessor) DisableOptimization() {
p.enabled = false
func DisableOptimization() {
enabled = false
}

// Producer functions
func (p *OpcodeProcessor) LoadOptimizedCode(address common.Address, hash common.Hash) OptCode {
if !p.enabled {
func LoadOptimizedCode(address common.Address, hash common.Hash) OptCode {
if !enabled {
return nil
}
/* Try load from cache */
codeCache := p.codeCache
processedCode := codeCache.GetCachedCode(address, hash)
return processedCode

}

func (p *OpcodeProcessor) GenOrLoadOptimizedCode(address common.Address, code []byte, hash common.Hash) {
func GenOrLoadOptimizedCode(address common.Address, code []byte, hash common.Hash) {
task := optimizeTask{generate, address, hash, code}
p.taskChannel <- task
taskChannel <- task
}

func (p *OpcodeProcessor) FlushCodeCache(address common.Address, hash common.Hash) {
func FlushCodeCache(address common.Address, hash common.Hash) {
task := optimizeTask{flush, address, hash, nil}
p.taskChannel <- task
taskChannel <- task
}

func (p *OpcodeProcessor) RewriteOptimizedCodeForDB(address common.Address, code []byte, hash common.Hash) {
if p.enabled {
func RewriteOptimizedCodeForDB(address common.Address, code []byte, hash common.Hash) {
if enabled {
// p.GenOrRewriteOptimizedCode(address, code, hash)
//
p.GenOrLoadOptimizedCode(address, code, hash)
GenOrLoadOptimizedCode(address, code, hash)
}
}

// Consumer function
func (p *OpcodeProcessor) taskProcessor() {
func taskProcessor() {
for {
task := <-p.taskChannel
task := <-taskChannel
// Process the message here
p.handleOptimizationTask(task)
handleOptimizationTask(task)
}
}

func (p *OpcodeProcessor) handleOptimizationTask(task optimizeTask) {
func handleOptimizationTask(task optimizeTask) {
switch task.taskType {
case generate:
p.TryGenerateOptimizedCode(task.addr, task.rawCode, task.codeHash)
TryGenerateOptimizedCode(task.addr, task.rawCode, task.codeHash)
case flush:
p.DeleteCodeCache(task.addr, task.codeHash)
DeleteCodeCache(task.addr, task.codeHash)
}
}

// GenOrRewriteOptimizedCode generate the optimized code and refresh the codecache.
func (p *OpcodeProcessor) GenOrRewriteOptimizedCode(address common.Address, code []byte, hash common.Hash) (OptCode, error) {
if !p.enabled {
func GenOrRewriteOptimizedCode(address common.Address, code []byte, hash common.Hash) (OptCode, error) {
if !enabled {
return nil, ErrOptiDisabled
}
processedCode, err := processByteCodes(code)
if err != nil {
log.Error("Can not generate optimized code: %s\n", err.Error())
return nil, err
}
codeCache := p.codeCache
codeCache := codeCache
err = codeCache.UpdateCodeCache(address, processedCode, hash)
if err != nil {
log.Error("Not update code cache", "err", err)
}
return processedCode, err
}

func (p *OpcodeProcessor) TryGenerateOptimizedCode(address common.Address, code []byte, hash common.Hash) (OptCode, bool, error) {
if !p.enabled {
func TryGenerateOptimizedCode(address common.Address, code []byte, hash common.Hash) (OptCode, bool, error) {
if !enabled {
return nil, false, ErrOptiDisabled
}
/* Try load from cache */
codeCache := p.codeCache
processedCode := codeCache.GetCachedCode(address, hash)
hit := false
var err error = nil
if processedCode == nil || len(processedCode) == 0 {
processedCode, err = p.GenOrRewriteOptimizedCode(address, code, hash)
processedCode, err = GenOrRewriteOptimizedCode(address, code, hash)
hit = false
} else {
hit = true
}
return processedCode, hit, err
}

func (p *OpcodeProcessor) DeleteCodeCache(addr common.Address, hash common.Hash) {
if !p.enabled {
func DeleteCodeCache(addr common.Address, hash common.Hash) {
if enabled {
return
}
// flush in case there are invalid cached code
p.codeCache.RemoveCachedCode(addr, hash)
codeCache.RemoveCachedCode(addr, hash)
}

func processByteCodes(code []byte) (OptCode, error) {
Expand Down
2 changes: 1 addition & 1 deletion core/state/journal.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ func (ch nonceChange) dirtied() *common.Address {

func (ch codeChange) revert(s *StateDB) {
s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode)
compiler.GetOpcodeProcessorInstance().RewriteOptimizedCodeForDB(*ch.account, ch.prevcode, common.BytesToHash(ch.prevhash))
compiler.RewriteOptimizedCodeForDB(*ch.account, ch.prevcode, common.BytesToHash(ch.prevhash))
}

func (ch codeChange) dirtied() *common.Address {
Expand Down
2 changes: 1 addition & 1 deletion core/state/state_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ func (s *stateObject) setCode(codeHash common.Hash, code []byte) {
s.code = code
s.data.CodeHash = codeHash[:]
s.dirtyCode = true
compiler.GetOpcodeProcessorInstance().RewriteOptimizedCodeForDB(s.address, code, codeHash)
compiler.RewriteOptimizedCodeForDB(s.address, code, codeHash)
}

func (s *stateObject) SetNonce(nonce uint64) {
Expand Down
2 changes: 1 addition & 1 deletion core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common
func (s *StateDB) Suicide(addr common.Address) bool {
stateObject := s.getStateObject(addr)
// every time set code in DB. regenerate the optimized code in code cache.
compiler.GetOpcodeProcessorInstance().FlushCodeCache(addr, common.Hash{})
compiler.FlushCodeCache(addr, common.Hash{})
if stateObject == nil {
return false
}
Expand Down
16 changes: 7 additions & 9 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig
evm.depth = 0
evm.interpreter = NewEVMInterpreter(evm)
if config.EnableOpcodeOptimizations {
compiler.GetOpcodeProcessorInstance().EnableOptimization()
compiler.EnableOptimization()
}
return evm
}
Expand Down Expand Up @@ -449,14 +449,12 @@ func tryGetOptimizedCode(evm *EVM, addrCopy common.Address) (bool, []byte) {
optimized := false
if evm.Config.EnableOpcodeOptimizations {
codeHash := evm.StateDB.GetCodeHash(addrCopy)
if codeHash != (common.Hash{}) {
optCode := compiler.GetOpcodeProcessorInstance().LoadOptimizedCode(addrCopy, codeHash)
if len(optCode) != 0 {
code = optCode
optimized = true
} else {
compiler.GetOpcodeProcessorInstance().GenOrLoadOptimizedCode(addrCopy, code, codeHash)
}
optCode := compiler.LoadOptimizedCode(addrCopy, codeHash)
if len(optCode) != 0 {
code = optCode
optimized = true
} else {
compiler.GenOrLoadOptimizedCode(addrCopy, code, codeHash)
}
}
return optimized, code
Expand Down
Loading

0 comments on commit e6584c3

Please sign in to comment.