From: Russ Cox Date: Fri, 14 Feb 2014 00:59:09 +0000 (-0500) Subject: cmd/gc: relax address-of escape analysis X-Git-Tag: go1.3beta1~713 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=e5d742fcadf9677a40336d6cecd3ff464a94730f;p=gostls13.git cmd/gc: relax address-of escape analysis Make the loop nesting depth of &x depend on where x is declared, not on where the &x appears. The latter is only a conservative estimate of the former. Being more careful can avoid some variables escaping, and it is easier to reason about. It would have avoided issue 7313, although that was still a bug worth fixing. Not much effect in the tree: one variable in the whole tree is saved from a heap allocation (something in x509 parsing). LGTM=daniel.morsing R=daniel.morsing CC=golang-codereviews https://golang.org/cl/62380043 --- diff --git a/src/cmd/gc/esc.c b/src/cmd/gc/esc.c index c038dfc589..5a1a9ed21c 100644 --- a/src/cmd/gc/esc.c +++ b/src/cmd/gc/esc.c @@ -328,6 +328,7 @@ escfunc(EscState *e, Node *func) ll->n->escloopdepth = 0; break; case PPARAM: + ll->n->escloopdepth = 1; if(ll->n->type && !haspointers(ll->n->type)) break; if(curfn->nbody == nil && !curfn->noescape) @@ -335,7 +336,6 @@ escfunc(EscState *e, Node *func) else ll->n->esc = EscNone; // prime for escflood later e->noesc = list(e->noesc, ll->n); - ll->n->escloopdepth = 1; break; } } @@ -630,7 +630,6 @@ esc(EscState *e, Node *n) escassign(e, n, a); } // fallthrough - case OADDR: case OMAKECHAN: case OMAKEMAP: case OMAKESLICE: @@ -639,6 +638,24 @@ esc(EscState *e, Node *n) n->esc = EscNone; // until proven otherwise e->noesc = list(e->noesc, n); break; + + case OADDR: + n->esc = EscNone; // until proven otherwise + e->noesc = list(e->noesc, n); + // current loop depth is an upper bound on actual loop depth + // of addressed value. + n->escloopdepth = e->loopdepth; + // for &x, use loop depth of x. + if(n->left->op == ONAME) { + switch(n->left->class) { + case PAUTO: + case PPARAM: + case PPARAMOUT: + n->escloopdepth = n->left->escloopdepth; + break; + } + } + break; } lineno = lno; diff --git a/test/escape2.go b/test/escape2.go index 73342fd2bc..047adf5149 100644 --- a/test/escape2.go +++ b/test/escape2.go @@ -1389,3 +1389,13 @@ func foo148(l List) { // ERROR " l does not escape" for p := &l; p.Next != nil; p = p.Next { // ERROR "&l does not escape" } } + +// related: address of variable should have depth of variable, not of loop + +func foo149(l List) { // ERROR " l does not escape" + var p *List + for { + for p = &l; p.Next != nil; p = p.Next { // ERROR "&l does not escape" + } + } +}