]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: make KeepAlive work on stack object
authorCherry Zhang <cherryyz@google.com>
Thu, 28 Feb 2019 01:43:29 +0000 (20:43 -0500)
committerCherry Zhang <cherryyz@google.com>
Fri, 1 Mar 2019 15:36:52 +0000 (15:36 +0000)
Currently, runtime.KeepAlive applied on a stack object doesn't
actually keeps the stack object alive, and the heap object
referenced from it could be collected. This is because the
address of the stack object is rematerializeable, and we just
ignored KeepAlive on rematerializeable values. This CL fixes it.

Fixes #30476.

Change-Id: Ic1f75ee54ed94ea79bd46a8ddcd9e81d01556d1d
Reviewed-on: https://go-review.googlesource.com/c/164537
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/ssa/regalloc.go
test/fixedbugs/issue30476.go [new file with mode: 0644]

index 8946cf6b5c0838c1d8d6431dde37b288311248eb..a26547931657307d5b2677f80e8aaf583290cc1e 100644 (file)
@@ -1220,6 +1220,13 @@ func (s *regAllocState) regalloc(f *Func) {
                                        // This forces later liveness analysis to make the
                                        // value live at this point.
                                        v.SetArg(0, s.makeSpill(a, b))
+                               } else if _, ok := a.Aux.(GCNode); ok && vi.rematerializeable {
+                                       // Rematerializeable value with a gc.Node. This is the address of
+                                       // a stack object (e.g. an LEAQ). Keep the object live.
+                                       // Change it to VarLive, which is what plive expects for locals.
+                                       v.Op = OpVarLive
+                                       v.SetArgs1(v.Args[1])
+                                       v.Aux = a.Aux
                                } else {
                                        // In-register and rematerializeable values are already live.
                                        // These are typically rematerializeable constants like nil,
diff --git a/test/fixedbugs/issue30476.go b/test/fixedbugs/issue30476.go
new file mode 100644 (file)
index 0000000..a2147ec
--- /dev/null
@@ -0,0 +1,30 @@
+// run
+
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 30476: KeepAlive didn't keep stack object alive.
+
+package main
+
+import "runtime"
+
+func main() {
+       x := new([10]int)
+       runtime.SetFinalizer(x, func(*[10]int) { panic("FAIL: finalizer runs") })
+       p := &T{x, 0}
+       use(p)
+       runtime.GC()
+       runtime.GC()
+       runtime.GC()
+       runtime.KeepAlive(p)
+}
+
+type T struct {
+       x *[10]int
+       y int
+}
+
+//go:noinline
+func use(*T) {}