1
0
mirror of https://github.com/golang/go synced 2024-11-17 23:04:56 -07:00

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 <austin@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Austin Clements <austin@google.com>
This commit is contained in:
Austin Clements 2023-08-16 12:30:10 -04:00 committed by Gopher Robot
parent 9ac6b00e79
commit e094e80f65

View File

@ -844,6 +844,10 @@ func pcvalueCacheKey(targetpc uintptr) uintptr {
// Returns the PCData value, and the PC where this value starts. // 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) { 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 { if off == 0 {
return -1, 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 // This cache is small enough that full associativity is
// cheaper than doing the hashing for a less associative // cheaper than doing the hashing for a less associative
// cache. // cache.
var checkVal int32
var checkPC uintptr
if cache != nil { if cache != nil {
x := pcvalueCacheKey(targetpc) x := pcvalueCacheKey(targetpc)
for i := range cache.entries[x] { for i := range cache.entries[x] {
@ -864,10 +870,15 @@ func pcvalue(f funcInfo, off uint32, targetpc uintptr, cache *pcvalueCache, stri
// fail in the first clause. // fail in the first clause.
ent := &cache.entries[x][i] ent := &cache.entries[x][i]
if ent.off == off && ent.targetpc == targetpc { if ent.off == off && ent.targetpc == targetpc {
if debugCheckCache {
checkVal, checkPC = ent.val, ent.valPC
break
} else {
return ent.val, ent.valPC return ent.val, ent.valPC
} }
} }
} }
}
if !f.valid() { if !f.valid() {
if strict && panicking.Load() == 0 { if strict && panicking.Load() == 0 {
@ -894,7 +905,12 @@ func pcvalue(f funcInfo, off uint32, targetpc uintptr, cache *pcvalueCache, stri
// larger than the cache. // larger than the cache.
// Put the new element at the beginning, // Put the new element at the beginning,
// since it is the most likely to be newly used. // 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) x := pcvalueCacheKey(targetpc)
e := &cache.entries[x] e := &cache.entries[x]
ci := fastrandn(uint32(len(cache.entries[x]))) ci := fastrandn(uint32(len(cache.entries[x])))