From e094e80f65f77bf83e2962dc5150915711f2166d Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Wed, 16 Aug 2023 12:30:10 -0400 Subject: [PATCH] runtime: add self-check mode to cache in pcvalue This would have helped with debugging the failures caused by CL 515276. Change-Id: Id641949d8bcd763de7f93778ad9bd3fdde95dcb2 Reviewed-on: https://go-review.googlesource.com/c/go/+/520062 Auto-Submit: Austin Clements Reviewed-by: Michael Knyszek TryBot-Result: Gopher Robot Run-TryBot: Austin Clements --- src/runtime/symtab.go | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index ff5f5f7f0e..d828c37a75 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -844,6 +844,10 @@ func pcvalueCacheKey(targetpc uintptr) uintptr { // Returns the PCData value, and the PC where this value starts. func pcvalue(f funcInfo, off uint32, targetpc uintptr, cache *pcvalueCache, strict bool) (int32, uintptr) { + // If true, when we get a cache hit, still look up the data and make sure it + // matches the cached contents. + const debugCheckCache = false + if off == 0 { return -1, 0 } @@ -854,6 +858,8 @@ func pcvalue(f funcInfo, off uint32, targetpc uintptr, cache *pcvalueCache, stri // This cache is small enough that full associativity is // cheaper than doing the hashing for a less associative // cache. + var checkVal int32 + var checkPC uintptr if cache != nil { x := pcvalueCacheKey(targetpc) for i := range cache.entries[x] { @@ -864,7 +870,12 @@ func pcvalue(f funcInfo, off uint32, targetpc uintptr, cache *pcvalueCache, stri // fail in the first clause. ent := &cache.entries[x][i] if ent.off == off && ent.targetpc == targetpc { - return ent.val, ent.valPC + if debugCheckCache { + checkVal, checkPC = ent.val, ent.valPC + break + } else { + return ent.val, ent.valPC + } } } } @@ -894,7 +905,12 @@ func pcvalue(f funcInfo, off uint32, targetpc uintptr, cache *pcvalueCache, stri // larger than the cache. // Put the new element at the beginning, // since it is the most likely to be newly used. - if cache != nil { + if debugCheckCache && checkPC != 0 { + if checkVal != val || checkPC != prevpc { + print("runtime: table value ", val, "@", prevpc, " != cache value ", checkVal, "@", checkPC, " at PC ", targetpc, " off ", off, "\n") + throw("bad pcvalue cache") + } + } else if cache != nil { x := pcvalueCacheKey(targetpc) e := &cache.entries[x] ci := fastrandn(uint32(len(cache.entries[x])))