mirror of
https://github.com/golang/go
synced 2024-11-21 23:44:39 -07:00
gc: fix escape analysis + inlining + closure bug
R=ken2 CC=golang-dev, lvd https://golang.org/cl/5693056
This commit is contained in:
parent
d45ee4cb5f
commit
075eef4018
@ -59,7 +59,7 @@ static int dstcount, edgecount; // diagnostic
|
|||||||
static NodeList* noesc; // list of possible non-escaping nodes, for printing
|
static NodeList* noesc; // list of possible non-escaping nodes, for printing
|
||||||
|
|
||||||
void
|
void
|
||||||
escapes(void)
|
escapes(NodeList *all)
|
||||||
{
|
{
|
||||||
NodeList *l;
|
NodeList *l;
|
||||||
|
|
||||||
@ -70,9 +70,10 @@ escapes(void)
|
|||||||
theSink.escloopdepth = -1;
|
theSink.escloopdepth = -1;
|
||||||
|
|
||||||
safetag = strlit("noescape");
|
safetag = strlit("noescape");
|
||||||
|
noesc = nil;
|
||||||
|
|
||||||
// flow-analyze top level functions
|
// flow-analyze functions
|
||||||
for(l=xtop; l; l=l->next)
|
for(l=all; l; l=l->next)
|
||||||
if(l->n->op == ODCLFUNC || l->n->op == OCLOSURE)
|
if(l->n->op == ODCLFUNC || l->n->op == OCLOSURE)
|
||||||
escfunc(l->n);
|
escfunc(l->n);
|
||||||
|
|
||||||
@ -84,7 +85,7 @@ escapes(void)
|
|||||||
escflood(l->n);
|
escflood(l->n);
|
||||||
|
|
||||||
// for all top level functions, tag the typenodes corresponding to the param nodes
|
// for all top level functions, tag the typenodes corresponding to the param nodes
|
||||||
for(l=xtop; l; l=l->next)
|
for(l=all; l; l=l->next)
|
||||||
if(l->n->op == ODCLFUNC)
|
if(l->n->op == ODCLFUNC)
|
||||||
esctag(l->n);
|
esctag(l->n);
|
||||||
|
|
||||||
|
@ -955,7 +955,7 @@ NodeList* variter(NodeList *vl, Node *t, NodeList *el);
|
|||||||
/*
|
/*
|
||||||
* esc.c
|
* esc.c
|
||||||
*/
|
*/
|
||||||
void escapes(void);
|
void escapes(NodeList*);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* export.c
|
* export.c
|
||||||
|
@ -186,7 +186,7 @@ int
|
|||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int i, c;
|
int i, c;
|
||||||
NodeList *l;
|
NodeList *l, *batch;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
#ifdef SIGBUS
|
#ifdef SIGBUS
|
||||||
@ -390,7 +390,7 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
// Phase 5: escape analysis.
|
// Phase 5: escape analysis.
|
||||||
if(!debug['N'])
|
if(!debug['N'])
|
||||||
escapes();
|
escapes(xtop);
|
||||||
|
|
||||||
// Phase 6: Compile top level functions.
|
// Phase 6: Compile top level functions.
|
||||||
for(l=xtop; l; l=l->next)
|
for(l=xtop; l; l=l->next)
|
||||||
@ -401,14 +401,17 @@ main(int argc, char *argv[])
|
|||||||
fninit(xtop);
|
fninit(xtop);
|
||||||
|
|
||||||
// Phase 6b: Compile all closures.
|
// Phase 6b: Compile all closures.
|
||||||
|
// Can generate more closures, so run in batches.
|
||||||
while(closures) {
|
while(closures) {
|
||||||
l = closures;
|
batch = closures;
|
||||||
closures = nil;
|
closures = nil;
|
||||||
for(; l; l=l->next) {
|
if(debug['l'])
|
||||||
if (debug['l'])
|
for(l=batch; l; l=l->next)
|
||||||
inlcalls(l->n);
|
inlcalls(l->n);
|
||||||
|
if(!debug['N'])
|
||||||
|
escapes(batch);
|
||||||
|
for(l=batch; l; l=l->next)
|
||||||
funccompile(l->n, 1);
|
funccompile(l->n, 1);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Phase 7: check external declarations.
|
// Phase 7: check external declarations.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Test, using compiler diagnostic flags, that the escape analysis is working.
|
// Test, using compiler diagnostic flags, that the escape analysis is working.
|
||||||
// Compiles but does not run.
|
// Compiles but does not run. Inlining is disabled.
|
||||||
|
|
||||||
package foo
|
package foo
|
||||||
|
|
||||||
|
33
test/escape4.go
Normal file
33
test/escape4.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// errchk -0 $G -m $D/$F.go
|
||||||
|
|
||||||
|
// Copyright 2010 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Test, using compiler diagnostic flags, that the escape analysis is working.
|
||||||
|
// Compiles but does not run. Inlining is enabled.
|
||||||
|
|
||||||
|
package foo
|
||||||
|
|
||||||
|
var p *int
|
||||||
|
|
||||||
|
func alloc(x int) *int { // ERROR "can inline alloc" "moved to heap: x"
|
||||||
|
return &x // ERROR "&x escapes to heap"
|
||||||
|
}
|
||||||
|
|
||||||
|
var f func()
|
||||||
|
|
||||||
|
func f1() {
|
||||||
|
p = alloc(2) // ERROR "inlining call to alloc" "&x escapes to heap" "moved to heap: x"
|
||||||
|
|
||||||
|
// Escape analysis used to miss inlined code in closures.
|
||||||
|
|
||||||
|
func() { // ERROR "func literal does not escape"
|
||||||
|
p = alloc(3) // ERROR "inlining call to alloc" "&x escapes to heap" "moved to heap: x"
|
||||||
|
}()
|
||||||
|
|
||||||
|
f = func() { // ERROR "func literal escapes to heap"
|
||||||
|
p = alloc(3) // ERROR "inlining call to alloc" "&x escapes to heap" "moved to heap: x"
|
||||||
|
}
|
||||||
|
f()
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user