From e5d742fcadf9677a40336d6cecd3ff464a94730f Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 13 Feb 2014 19:59:09 -0500 Subject: [PATCH] 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 --- src/cmd/gc/esc.c | 21 +++++++++++++++++++-- test/escape2.go | 10 ++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) 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" + } + } +} -- 2.48.1