]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix runtime.KeepAlive
authorKeith Randall <khr@golang.org>
Sat, 28 Oct 2017 17:14:08 +0000 (10:14 -0700)
committerKeith Randall <khr@golang.org>
Mon, 30 Oct 2017 19:55:02 +0000 (19:55 +0000)
KeepAlive needs to introduce a use of the spill of the
value it is keeping alive.  Without that, we don't guarantee
that the spill dominates the KeepAlive.

This bug was probably introduced with the code to move spills
down to the dominator of the restores, instead of always spilling
just after the value itself (CL 34822).

Fixes #22458.

Change-Id: I94955a21960448ffdacc4df775fe1213967b1d4c
Reviewed-on: https://go-review.googlesource.com/74210
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: David Chase <drchase@google.com>
src/cmd/compile/internal/ssa/regalloc.go
test/fixedbugs/issue22458.go [new file with mode: 0644]

index 7faf2f13feb68434b03732d1545671f27825e470..bc0a972da46a542e59d2bcb6f9d0c6e6a170fbaf 100644 (file)
@@ -1133,12 +1133,15 @@ func (s *regAllocState) regalloc(f *Func) {
                        if v.Op == OpKeepAlive {
                                // Make sure the argument to v is still live here.
                                s.advanceUses(v)
-                               vi := &s.values[v.Args[0].ID]
-                               if vi.spill != nil {
+                               a := v.Args[0]
+                               vi := &s.values[a.ID]
+                               if vi.regs == 0 && !vi.rematerializeable {
                                        // Use the spill location.
-                                       v.SetArg(0, vi.spill)
+                                       // This forces later liveness analysis to make the
+                                       // value live at this point.
+                                       v.SetArg(0, s.makeSpill(a, b))
                                } else {
-                                       // No need to keep unspilled values live.
+                                       // In-register and rematerializeable values are already live.
                                        // These are typically rematerializeable constants like nil,
                                        // or values of a variable that were modified since the last call.
                                        v.Op = OpCopy
diff --git a/test/fixedbugs/issue22458.go b/test/fixedbugs/issue22458.go
new file mode 100644 (file)
index 0000000..5c89929
--- /dev/null
@@ -0,0 +1,26 @@
+// compile
+
+// Copyright 2017 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.
+
+// Make sure KeepAlive introduces a use of the spilled variable.
+
+package main
+
+import "runtime"
+
+type node struct {
+        next *node
+}
+
+var x bool
+
+func main() {
+        var head *node
+        for x {
+                head = &node{head}
+        }
+
+        runtime.KeepAlive(head)
+}