]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: handle degenerate write barrier case
authorKeith Randall <khr@google.com>
Thu, 12 Jul 2018 18:44:05 +0000 (11:44 -0700)
committerKeith Randall <khr@golang.org>
Thu, 12 Jul 2018 19:06:09 +0000 (19:06 +0000)
If both branches of a write barrier test go to the same block,
then there's no unsafe points.

This can only happen if the resulting memory state is somehow dead,
which can only occur in degenerate cases, like infinite loops. No
point in cleaning up the useless branch in these situations.

Fixes #26024.

Change-Id: I93a7df9fdf2fc94c6c4b1fe61180dc4fd4a0871f
Reviewed-on: https://go-review.googlesource.com/123655
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/compile/internal/gc/plive.go
test/fixedbugs/issue26024.go [new file with mode: 0644]

index 88b438063709297aeb23d23d8ca2d30e3a7c1a22..f78d051b060c7a664c2f2ba7f1858947299ab36d 100644 (file)
@@ -692,6 +692,11 @@ func (lv *Liveness) markUnsafePoints() {
                        lv.f.Fatalf("expected branch at write barrier block %v", wbBlock)
                }
                s0, s1 := wbBlock.Succs[0].Block(), wbBlock.Succs[1].Block()
+               if s0 == s1 {
+                       // There's no difference between write barrier on and off.
+                       // Thus there's no unsafe locations. See issue 26024.
+                       continue
+               }
                if s0.Kind != ssa.BlockPlain || s1.Kind != ssa.BlockPlain {
                        lv.f.Fatalf("expected successors of write barrier block %v to be plain", wbBlock)
                }
diff --git a/test/fixedbugs/issue26024.go b/test/fixedbugs/issue26024.go
new file mode 100644 (file)
index 0000000..78877b2
--- /dev/null
@@ -0,0 +1,28 @@
+// compile
+// Copyright 2018 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.
+
+package r
+
+// f compiles into code where no stores remain in the two successors
+// of a write barrier block; i.e., they are empty. Pre-fix, this
+// results in an unexpected input to markUnsafePoints, that expects to
+// see a pair of non-empty plain blocks.
+func f() {
+       var i int
+       var s string
+       for len(s) < len(s) {
+               i++
+               s = "a"
+       }
+       var b bool
+       var sa []string
+       for true {
+               sa = []string{""}
+               for b || i == 0 {
+               }
+               b = !b
+               _ = sa
+       }
+}