cmd/compile: run escape analysis after method wrapper generation

Also modified test/run.go to ignore messages prefixed <autogenerated>
because those cannot be described with "// ERROR ...", and backed out
patch from issue #9537 because it is no longer necessary.  The reasons
described in the 9537 discussion for why escape analysis cannot run
late no longer hold, happily.

Fixes #11053.

Change-Id: Icb14eccdf2e8cde3d0f8fb8a216b765400a96385
Reviewed-on: https://go-review.googlesource.com/11088
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: David Chase <drchase@google.com>
This commit is contained in:
David Chase 2015-06-16 18:28:01 -04:00
parent 6428a8b437
commit 5be61b18d4
8 changed files with 80 additions and 17 deletions

View file

@ -644,8 +644,6 @@ var compiling_runtime int
var compiling_wrappers int
var inl_nonlocal int
var use_writebarrier int
var pure_go int

View file

@ -831,12 +831,10 @@ func inlvar(var_ *Node) *Node {
n.Name.Curfn = Curfn // the calling function, not the called one
n.Addrtaken = var_.Addrtaken
// Esc pass wont run if we're inlining into a iface wrapper.
// Luckily, we can steal the results from the target func.
// If inlining a function defined in another package after
// escape analysis is done, treat all local vars as escaping.
// See issue 9537.
if var_.Esc == EscHeap || (inl_nonlocal != 0 && var_.Op == ONAME) {
// This may no longer be necessary now that we run escape analysis
// after wrapper generation, but for 1.5 this is conservatively left
// unchanged. See bugs 11053 and 9537.
if var_.Esc == EscHeap {
addrescapes(n)
}

View file

@ -2494,15 +2494,8 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
typecheck(&fn, Etop)
typechecklist(fn.Nbody, Etop)
// Set inl_nonlocal to whether we are calling a method on a
// type defined in a different package. Checked in inlvar.
if !methodrcvr.Local {
inl_nonlocal = 1
}
inlcalls(fn)
inl_nonlocal = 0
escAnalyze(list1(fn), false)
Curfn = nil
funccompile(fn)

View file

@ -0,0 +1,9 @@
// Copyright 2015 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.
package p
func Int32(i int32) *int32 {
return &i
}

View file

@ -0,0 +1,51 @@
// Copyright 2015 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.
package main
import (
"fmt"
"p"
)
type I interface {
Add(out *P)
}
type P struct {
V *int32
}
type T struct{}
var x int32 = 42
func Int32x(i int32) *int32 {
return &i
}
func (T) Add(out *P) {
out.V = p.Int32(x) // inlined, p.i.2 moved to heap
}
var PP P
var out *P = &PP
func F(s I) interface{} {
s.Add(out) // not inlined.
return out
}
var s T
func main() {
println("Starting")
fmt.Sprint(new(int32))
resp := F(s).(*P)
println("Before, *resp.V=", *resp.V) // Trashes *resp.V in process of printing.
println("After, *resp.V=", *resp.V)
if got, want := *resp.V, int32(42); got != want {
fmt.Printf("FAIL, got %v, want %v", got, want)
}
}

View file

@ -0,0 +1,10 @@
// rundir
// Copyright 2015 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.
// Issue 11053: Compiler does not run escape analysis on an inlined
// generated method wrapper.
package ignored

View file

@ -0,0 +1,3 @@
Starting
Before, *resp.V= 42
After, *resp.V= 42

View file

@ -729,6 +729,7 @@ func (t *test) expectedOutput() string {
func splitOutput(out string) []string {
// 6g error messages continue onto additional lines with leading tabs.
// Split the output at the beginning of each line that doesn't begin with a tab.
// <autogenerated> lines are impossible to match so those are filtered out.
var res []string
for _, line := range strings.Split(out, "\n") {
if strings.HasSuffix(line, "\r") { // remove '\r', output by compiler on windows
@ -736,7 +737,7 @@ func splitOutput(out string) []string {
}
if strings.HasPrefix(line, "\t") {
res[len(res)-1] += "\n" + line
} else if strings.HasPrefix(line, "go tool") {
} else if strings.HasPrefix(line, "go tool") || strings.HasPrefix(line, "<autogenerated>") {
continue
} else if strings.TrimSpace(line) != "" {
res = append(res, line)