mirror of
https://github.com/golang/go
synced 2024-11-05 18:36:08 +00:00
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:
parent
6428a8b437
commit
5be61b18d4
8 changed files with 80 additions and 17 deletions
|
@ -644,8 +644,6 @@ var compiling_runtime int
|
|||
|
||||
var compiling_wrappers int
|
||||
|
||||
var inl_nonlocal int
|
||||
|
||||
var use_writebarrier int
|
||||
|
||||
var pure_go int
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
9
test/fixedbugs/issue11053.dir/p.go
Normal file
9
test/fixedbugs/issue11053.dir/p.go
Normal 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
|
||||
}
|
51
test/fixedbugs/issue11053.dir/p_test.go
Normal file
51
test/fixedbugs/issue11053.dir/p_test.go
Normal 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)
|
||||
}
|
||||
}
|
10
test/fixedbugs/issue11053.go
Normal file
10
test/fixedbugs/issue11053.go
Normal 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
|
3
test/fixedbugs/issue11053.out
Normal file
3
test/fixedbugs/issue11053.out
Normal file
|
@ -0,0 +1,3 @@
|
|||
Starting
|
||||
Before, *resp.V= 42
|
||||
After, *resp.V= 42
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue