diff options
author | Keith Randall <khr@golang.org> | 2019-06-08 17:20:57 +0000 |
---|---|---|
committer | Keith Randall <khr@golang.org> | 2019-06-10 16:19:39 +0000 |
commit | 8f296f59de0703b0559474beb434a265e277bdca (patch) | |
tree | 4ffd97168a989aa958ef2055f07759f29a09210b /src/runtime/mgcmark.go | |
parent | daf944a531fecf2431b60da608e70680f4927412 (diff) | |
download | go-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.go | 20 |
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))) } |