Skip to content

Commit

Permalink
perf: cache codehash to speedup coverage tracking (#472)
Browse files Browse the repository at this point in the history
  • Loading branch information
samalws-tob authored Sep 9, 2024
1 parent 7816944 commit f508070
Showing 1 changed file with 21 additions and 1 deletion.
22 changes: 21 additions & 1 deletion fuzzing/coverage/coverage_tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ type CoverageTracer struct {

// nativeTracer is the underlying tracer used to capture EVM execution.
nativeTracer *chain.TestChainTracer

// codeHashCache is a cache for values returned by getContractCoverageMapHash,
// so that this expensive calculation doesn't need to be done every opcode.
// The [2] array is to differentiate between contract init (0) vs runtime (1),
// since init vs runtime produces different results from getContractCoverageMapHash.
// The Hash key is a contract's codehash, which uniquely identifies it.
codeHashCache [2]map[common.Hash]common.Hash
}

// coverageTracerCallFrameState tracks state across call frames in the tracer.
Expand All @@ -71,6 +78,7 @@ func NewCoverageTracer() *CoverageTracer {
tracer := &CoverageTracer{
coverageMaps: NewCoverageMaps(),
callFrameStates: make([]*coverageTracerCallFrameState, 0),
codeHashCache: [2]map[common.Hash]common.Hash{make(map[common.Hash]common.Hash), make(map[common.Hash]common.Hash)},
}
nativeTracer := &tracers.Tracer{
Hooks: &tracing.Hooks{
Expand Down Expand Up @@ -159,11 +167,23 @@ func (t *CoverageTracer) OnOpcode(pc uint64, op byte, gas, cost uint64, scope tr
scopeContext := scope.(*vm.ScopeContext)
code := scopeContext.Contract.Code
codeSize := len(code)
isCreate := callFrameState.create
gethCodeHash := scopeContext.Contract.CodeHash

cacheArrayKey := 1
if isCreate {
cacheArrayKey = 0
}

if codeSize > 0 {

// Obtain our contract coverage map lookup hash.
if callFrameState.lookupHash == nil {
lookupHash := getContractCoverageMapHash(code, callFrameState.create)
lookupHash, cacheHit := t.codeHashCache[cacheArrayKey][gethCodeHash]
if !cacheHit {
lookupHash = getContractCoverageMapHash(code, isCreate)
t.codeHashCache[cacheArrayKey][gethCodeHash] = lookupHash
}
callFrameState.lookupHash = &lookupHash
}

Expand Down

0 comments on commit f508070

Please sign in to comment.