Commit 1b87f012 authored by Dmitry Vyukov's avatar Dmitry Vyukov

cmd/gc: improve escape analysis for &T{...}

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/3031Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
parent 2059ffbc
......@@ -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;
......
......@@ -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
}
......@@ -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
}
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