]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: relax address-of escape analysis
authorRuss Cox <rsc@golang.org>
Fri, 14 Feb 2014 00:59:09 +0000 (19:59 -0500)
committerRuss Cox <rsc@golang.org>
Fri, 14 Feb 2014 00:59:09 +0000 (19:59 -0500)
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
test/escape2.go

index c038dfc589ccd004e75ade5964dfd501aff73243..5a1a9ed21cff8306715fd5a280d03f0fa8d927d2 100644 (file)
@@ -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;
index 73342fd2bc6326cd32cd6b7bf23112134180016e..047adf5149d2fb7544cf50ee5a8af5bf694e9ada 100644 (file)
@@ -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"
+               }
+       }
+}