summaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2018-12-17 14:17:20 -0500
committerAustin Clements <austin@google.com>2018-12-17 21:24:06 +0000
commit3c255e8bc6964ebee580b44835ddbe95c893e29f (patch)
tree36a201966cbb0918fa2faa9f7ad5c5916a6dc180 /src/runtime
parent503091a77c43263a5ce86f9358de3445524627b7 (diff)
downloadgo-git-3c255e8bc6964ebee580b44835ddbe95c893e29f.tar.gz
runtime: record extra information in throwOnGCWork crashes
Currently we only know the slot address and the value being written in the throwOnGCWork crash tracebacks, and we have to infer the old value from what's dumped by gcWork.checkPut. Sometimes these old values don't make sense, like when we see a write of a nil pointer to a freshly-allocated object, yet we observe marking a value (where did that pointer come from?). This CL adds the old value of the slot and the first two pointers in the buffer to the traceback. For #27993. Change-Id: Ib70eead1afb9c06e8099e520172c3a2acaa45f80 Reviewed-on: https://go-review.googlesource.com/c/154597 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Michael Knyszek <mknyszek@google.com>
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/mwbbuf.go24
1 files changed, 23 insertions, 1 deletions
diff --git a/src/runtime/mwbbuf.go b/src/runtime/mwbbuf.go
index 6f01bf68fd..78ce54452d 100644
--- a/src/runtime/mwbbuf.go
+++ b/src/runtime/mwbbuf.go
@@ -197,10 +197,32 @@ func wbBufFlush(dst *uintptr, src uintptr) {
// Switch to the system stack so we don't have to worry about
// the untyped stack slots or safe points.
systemstack(func() {
- wbBufFlush1(getg().m.p.ptr())
+ if debugCachedWork {
+ // For debugging, include the old value of the
+ // slot and some other data in the traceback.
+ wbBuf := &getg().m.p.ptr().wbBuf
+ var old uintptr
+ if dst != nil {
+ // dst may be nil in direct calls to wbBufFlush.
+ old = *dst
+ }
+ wbBufFlush1Debug(old, wbBuf.buf[0], wbBuf.buf[1], &wbBuf.buf[0], wbBuf.next)
+ } else {
+ wbBufFlush1(getg().m.p.ptr())
+ }
})
}
+// wbBufFlush1Debug is a temporary function for debugging issue
+// #27993. It exists solely to add some context to the traceback.
+//
+//go:nowritebarrierrec
+//go:systemstack
+//go:noinline
+func wbBufFlush1Debug(old, buf1, buf2 uintptr, start *uintptr, next uintptr) {
+ wbBufFlush1(getg().m.p.ptr())
+}
+
// wbBufFlush1 flushes p's write barrier buffer to the GC work queue.
//
// This must not have write barriers because it is part of the write