cmd/gc: record &x[0] as taking address of x, if x is an array

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
This commit is contained in:
Russ Cox 2014-02-15 20:01:15 -05:00
parent 8b6ef69e23
commit 1a3ee6794c
4 changed files with 40 additions and 2 deletions

View 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

View 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);

View 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(;;) {

36
test/fixedbugs/bug483.go Normal file
View file

@ -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())
}
}