]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: don't combine load+op if the op has SymAddr arguments
authorKeith Randall <khr@google.com>
Wed, 12 Dec 2018 00:12:57 +0000 (16:12 -0800)
committerKeith Randall <khr@golang.org>
Wed, 12 Dec 2018 21:13:15 +0000 (21:13 +0000)
By combining the load+op, we may force the op to happen earlier in
the store chain. That might force the SymAddr operation earlier, and
in particular earlier than its corresponding VarDef. That leads to
an invalid schedule, so avoid that.

This is kind of a hack to work around the issue presented. I think
the underlying problem, that LEAQ is not directly ordered with respect
to its vardef, is the real problem. The benefit of this CL is that
it fixes the immediate issue, is small, and obviously won't break
anything. A real fix for this issue is much more invasive.

The go binary is unchanged in size.
This situation just doesn't occur very often.

Fixes #28445

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

index 61a749ba0dcda4dad5529cf55af05c8fbdae4881..b48a9ea87e799fae6c66b7bf6e279e5b3a6cb50f 100644 (file)
@@ -306,6 +306,8 @@ func (lv *Liveness) valueEffects(v *ssa.Value) (int32, liveEffect) {
        //
        // Addr is a read also, as any subseqent holder of the pointer must be able
        // to see all the values (including initialization) written so far.
+       // This also prevents a variable from "coming back from the dead" and presenting
+       // stale pointers to the garbage collector. See issue 28445.
        if e&(ssa.SymRead|ssa.SymAddr) != 0 {
                effect |= uevar
        }
index 6ea46e7327fdb9af6ba2edd2e5f5de12b4f64b61..1fd335b3e7f0c5968326fd748211592243be4900 100644 (file)
@@ -264,6 +264,20 @@ func canMergeLoad(target, load *Value) bool {
                        // to be very rare.
                        return false
                }
+               if v.Op.SymEffect()&SymAddr != 0 {
+                       // This case prevents an operation that calculates the
+                       // address of a local variable from being forced to schedule
+                       // before its corresponding VarDef.
+                       // See issue 28445.
+                       //   v1 = LOAD ...
+                       //   v2 = VARDEF
+                       //   v3 = LEAQ
+                       //   v4 = CMPQ v1 v3
+                       // We don't want to combine the CMPQ with the load, because
+                       // that would force the CMPQ to schedule before the VARDEF, which
+                       // in turn requires the LEAQ to schedule before the VARDEF.
+                       return false
+               }
                if v.Type.IsMemory() {
                        if memPreds == nil {
                                // Initialise a map containing memory states
diff --git a/test/fixedbugs/issue28445.go b/test/fixedbugs/issue28445.go
new file mode 100644 (file)
index 0000000..5726140
--- /dev/null
@@ -0,0 +1,16 @@
+// 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 p
+
+var fp = (**float64)(nil)
+
+func f() {
+       switch fp {
+       case new(*float64):
+               println()
+       }
+}