]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/gc: improve escape analysis for &T{...}
authorDmitry Vyukov <dvyukov@google.com>
Mon, 19 Jan 2015 20:46:22 +0000 (23:46 +0300)
committerDmitry Vyukov <dvyukov@google.com>
Wed, 28 Jan 2015 16:59:01 +0000 (16:59 +0000)
Currently all PTRLIT element initializers escape. There is no reason for that.
This change links STRUCTLIT to PTRLIT; STRUCTLIT element initializers are
already linked to the STRUCTLIT. As the result, PTRLIT element initializers
escape when PTRLIT itself escapes.

Change-Id: I89ecd8677cbf81addcfd469cd2fd461c0e9bf7dd
Reviewed-on: https://go-review.googlesource.com/3031
Reviewed-by: Russ Cox <rsc@golang.org>
src/cmd/gc/esc.c
test/escape2.go
test/escape2n.go

index 7c7095c8209005669855fe37822c4118ae235c07..2fdbd998702028c688feef4e8c560ce1e9cbc119 100644 (file)
@@ -615,15 +615,15 @@ esc(EscState *e, Node *n, Node *up)
                for(ll=n->list; ll; ll=ll->next)
                        escassign(e, n, ll->n->right);
                break;
-       
+
        case OPTRLIT:
                n->esc = EscNone;  // until proven otherwise
                e->noesc = list(e->noesc, n);
                n->escloopdepth = e->loopdepth;
-               // Contents make it to memory, lose track.
-               escassign(e, &e->theSink, n->left);
+               // Link OSTRUCTLIT to OPTRLIT; if OPTRLIT escapes, OSTRUCTLIT elements do too.
+               escassign(e, n, n->left);
                break;
-       
+
        case OCALLPART:
                n->esc = EscNone; // until proven otherwise
                e->noesc = list(e->noesc, n);
@@ -730,6 +730,7 @@ escassign(EscState *e, Node *dst, Node *src)
        case OCONVNOP:
        case OMAPLIT:
        case OSTRUCTLIT:
+       case OPTRLIT:
        case OCALLPART:
                break;
 
index 6a46ce86abd4173cc549967658f1107cbb278c31..357ce4a8a85c5cd4a3b8da3d00fa31b5f3a294ec 100644 (file)
@@ -1492,3 +1492,30 @@ func g() (x interface{}) { // ERROR "moved to heap: x"
        x = &x // ERROR "&x escapes to heap"
        return
 }
+
+var sink interface{}
+
+type Lit struct {
+       p *int
+}
+
+func ptrlitNoescape() {
+       // Both literal and element do not escape.
+       i := 0
+       x := &Lit{&i} // ERROR "&Lit literal does not escape" "&i does not escape"
+       _ = x
+}
+
+func ptrlitNoEscape2() {
+       // Literal does not escape, but element does.
+       i := 0 // ERROR "moved to heap: i"
+       x := &Lit{&i} // ERROR "&Lit literal does not escape" "&i escapes to heap"
+       sink = *x
+}
+
+func ptrlitEscape() {
+       // Both literal and element escape.
+       i := 0 // ERROR "moved to heap: i"
+       x := &Lit{&i} // ERROR "&Lit literal escapes to heap" "&i escapes to heap"
+       sink = x
+}
index 002a78ea50d14f49024e1a7e0e869d13dae13e83..3e9bb709c9a82aad5bd6fc6b6fddc01c51255cd8 100644 (file)
@@ -1492,3 +1492,30 @@ func g() (x interface{}) { // ERROR "moved to heap: x"
        x = &x // ERROR "&x escapes to heap"
        return
 }
+
+var sink interface{}
+
+type Lit struct {
+       p *int
+}
+
+func ptrlitNoescape() {
+       // Both literal and element do not escape.
+       i := 0
+       x := &Lit{&i} // ERROR "&Lit literal does not escape" "&i does not escape"
+       _ = x
+}
+
+func ptrlitNoEscape2() {
+       // Literal does not escape, but element does.
+       i := 0 // ERROR "moved to heap: i"
+       x := &Lit{&i} // ERROR "&Lit literal does not escape" "&i escapes to heap"
+       sink = *x
+}
+
+func ptrlitEscape() {
+       // Both literal and element escape.
+       i := 0 // ERROR "moved to heap: i"
+       x := &Lit{&i} // ERROR "&Lit literal escapes to heap" "&i escapes to heap"
+       sink = x
+}