aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mgcmark.go
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2019-06-08 17:20:57 +0000
committerKeith Randall <khr@golang.org>2019-06-10 16:19:39 +0000
commit8f296f59de0703b0559474beb434a265e277bdca (patch)
tree4ffd97168a989aa958ef2055f07759f29a09210b /src/runtime/mgcmark.go
parentdaf944a531fecf2431b60da608e70680f4927412 (diff)
downloadgo-8f296f59de0703b0559474beb434a265e277bdca.tar.gz
go-8f296f59de0703b0559474beb434a265e277bdca.zip
Revert "Revert "cmd/compile,runtime: allocate defer records on the stack""
This reverts CL 180761 Reason for revert: Reinstate the stack-allocated defer CL. There was nothing wrong with the CL proper, but stack allocation of defers exposed two other issues. Issue #32477: Fix has been submitted as CL 181258. Issue #32498: Possible fix is CL 181377 (not submitted yet). Change-Id: I32b3365d5026600069291b068bbba6cb15295eb3 Reviewed-on: https://go-review.googlesource.com/c/go/+/181378 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/runtime/mgcmark.go')
-rw-r--r--src/runtime/mgcmark.go20
1 files changed, 18 insertions, 2 deletions
diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go
index efa007aa97..2c63724472 100644
--- a/src/runtime/mgcmark.go
+++ b/src/runtime/mgcmark.go
@@ -712,15 +712,31 @@ func scanstack(gp *g, gcw *gcWork) {
// Find additional pointers that point into the stack from the heap.
// Currently this includes defers and panics. See also function copystack.
+
+ // Find and trace all defer arguments.
tracebackdefers(gp, scanframe, nil)
+
+ // Find and trace other pointers in defer records.
for d := gp._defer; d != nil; d = d.link {
- // tracebackdefers above does not scan the func value, which could
- // be a stack allocated closure. See issue 30453.
if d.fn != nil {
+ // tracebackdefers above does not scan the func value, which could
+ // be a stack allocated closure. See issue 30453.
scanblock(uintptr(unsafe.Pointer(&d.fn)), sys.PtrSize, &oneptrmask[0], gcw, &state)
}
+ if d.link != nil {
+ // The link field of a stack-allocated defer record might point
+ // to a heap-allocated defer record. Keep that heap record live.
+ scanblock(uintptr(unsafe.Pointer(&d.link)), sys.PtrSize, &oneptrmask[0], gcw, &state)
+ }
+ // Retain defers records themselves.
+ // Defer records might not be reachable from the G through regular heap
+ // tracing because the defer linked list might weave between the stack and the heap.
+ if d.heap {
+ scanblock(uintptr(unsafe.Pointer(&d)), sys.PtrSize, &oneptrmask[0], gcw, &state)
+ }
}
if gp._panic != nil {
+ // Panics are always stack allocated.
state.putPtr(uintptr(unsafe.Pointer(gp._panic)))
}