Commit e5d742fc authored by Russ Cox's avatar Russ Cox

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
parent e0bb5ba5
......@@ -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;
......
......@@ -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"
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment