aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCherry Zhang <cherryyz@google.com>2019-02-27 20:43:29 -0500
committerBrad Fitzpatrick <bradfitz@golang.org>2019-03-13 20:59:47 +0000
commit6fc1242ea8f8bbacd88cb834ef61dbe9e84a8514 (patch)
treef6ed0157aa1bb98470f8297579777d5ddb980115
parentf9d0594a471841f6ddd97a38f822da4f3461232f (diff)
downloadgo-6fc1242ea8f8bbacd88cb834ef61dbe9e84a8514.tar.gz
go-6fc1242ea8f8bbacd88cb834ef61dbe9e84a8514.zip
[release-branch.go1.12] cmd/compile: make KeepAlive work on stack object
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. Updates #30476. Fixes #30478. 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> (cherry picked from commit 40df9cc6062492cd323f2251dd1583d200d1207e) Reviewed-on: https://go-review.googlesource.com/c/go/+/164627
-rw-r--r--src/cmd/compile/internal/ssa/regalloc.go7
-rw-r--r--test/fixedbugs/issue30476.go30
2 files changed, 37 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go
index 8946cf6b5c..a265479316 100644
--- a/src/cmd/compile/internal/ssa/regalloc.go
+++ b/src/cmd/compile/internal/ssa/regalloc.go
@@ -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
index 0000000000..a2147ec0c1
--- /dev/null
+++ b/test/fixedbugs/issue30476.go
@@ -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) {}