]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: record &x[0] as taking address of x, if x is an array
authorRuss Cox <rsc@golang.org>
Sun, 16 Feb 2014 01:01:15 +0000 (20:01 -0500)
committerRuss Cox <rsc@golang.org>
Sun, 16 Feb 2014 01:01:15 +0000 (20:01 -0500)
Not recording the address being taken was causing
the liveness analysis not to preserve x in the absence
of direct references to x, which in turn was making the
net test fail with GOGC=0.

In addition to the test, this fixes a bug wherein
        GOGC=0 go test -short net
crashed if liveness analysis was in use (like at tip, not like Go 1.2).

TBR=ken2
CC=golang-codereviews
https://golang.org/cl/64470043

src/cmd/gc/go.h
src/cmd/gc/typecheck.c
src/cmd/gc/walk.c
test/fixedbugs/bug483.go [new file with mode: 0644]

index 049809e61a96194cc5348a48e592ee439572102e..e5d12a83450f6c2ada2c2437ce01ce90d2eb936e 100644 (file)
@@ -1452,6 +1452,7 @@ void      walkstmt(Node **np);
 void   walkstmtlist(NodeList *l);
 Node*  conv(Node*, Type*);
 int    candiscard(Node*);
+Node*  outervalue(Node*);
 
 /*
  *     arch-specific ggen.c/gsubr.c/gobj.c/pgen.c/plive.c
index 9e1ec1012489fb7d97499b05b21f31069907fc62..0ef497f62dfb6adcc0ed54ca5ee0c0696ebe517c 100644 (file)
@@ -721,7 +721,8 @@ reswitch:
                if(n->left->type == T)
                        goto error;
                checklvalue(n->left, "take the address of");
-               for(l=n->left; l->op == ODOT; l=l->left)
+               r = outervalue(n->left);
+               for(l = n->left; l != r; l = l->left)
                        l->addrtaken = 1;
                if(l->orig != l && l->op == ONAME)
                        fatal("found non-orig name node %N", l);
index e9f4c25c4b93bbb68d882295d83efd04284216fd..fe07490cbdb4b33e91fa87807edcc9c22c7f9ef4 100644 (file)
@@ -2205,7 +2205,7 @@ reorder3save(Node **np, NodeList *all, NodeList *stop, NodeList **early)
  * what's the outer value that a write to n affects?
  * outer value means containing struct or array.
  */
-static Node*
+Node*
 outervalue(Node *n)
 {      
        for(;;) {
diff --git a/test/fixedbugs/bug483.go b/test/fixedbugs/bug483.go
new file mode 100644 (file)
index 0000000..2372e89
--- /dev/null
@@ -0,0 +1,36 @@
+// run
+
+// Copyright 2014 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.
+
+// Test for a garbage collection bug involving not
+// marking x as having its address taken by &x[0]
+// when x is an array value.
+
+package main
+
+import (
+       "bytes"
+       "fmt"
+       "runtime"
+)
+
+func main() {
+       var x = [4]struct{ x, y interface{} }{
+               {"a", "b"},
+               {"c", "d"},
+               {"e", "f"},
+               {"g", "h"},
+       }
+
+       var buf bytes.Buffer
+       for _, z := range x {
+               runtime.GC()
+               fmt.Fprintf(&buf, "%s %s ", z.x.(string), z.y.(string))
+       }
+
+       if buf.String() != "a b c d e f g h " {
+               println("BUG wrong output\n", buf.String())
+       }
+}