mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.ssa] Merge remote-tracking branch 'origin/master' into mergebranch
Semi-regular merge from tip to dev.ssa. Conflicts: src/runtime/sys_windows_amd64.s Change-Id: I5f733130049c810e6ceacd46dad85faebca52b29
This commit is contained in:
commit
23d5810c8f
218 changed files with 4017 additions and 811 deletions
190
test/fixedbugs/issue13799.go
Normal file
190
test/fixedbugs/issue13799.go
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
// errorcheck -0 -m -l
|
||||
|
||||
// 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.
|
||||
|
||||
// Test, using compiler diagnostic flags, that the escape analysis is working.
|
||||
// Compiles but does not run. Inlining is disabled.
|
||||
// Registerization is disabled too (-N), which should
|
||||
// have no effect on escape analysis.
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
// Just run test over and over again. This main func is just for
|
||||
// convenience; if test were the main func, we could also trigger
|
||||
// the panic just by running the program over and over again
|
||||
// (sometimes it takes 1 time, sometimes it takes ~4,000+).
|
||||
for iter := 0; ; iter++ {
|
||||
if iter%50 == 0 {
|
||||
fmt.Println(iter) // ERROR "iter escapes to heap$" "main ... argument does not escape$"
|
||||
}
|
||||
test1(iter)
|
||||
test2(iter)
|
||||
test3(iter)
|
||||
test4(iter)
|
||||
test5(iter)
|
||||
test6(iter)
|
||||
}
|
||||
}
|
||||
|
||||
func test1(iter int) {
|
||||
|
||||
const maxI = 500
|
||||
m := make(map[int][]int) // ERROR "make\(map\[int\]\[\]int\) escapes to heap$"
|
||||
|
||||
// The panic seems to be triggered when m is modified inside a
|
||||
// closure that is both recursively called and reassigned to in a
|
||||
// loop.
|
||||
|
||||
// Cause of bug -- escape of closure failed to escape (shared) data structures
|
||||
// of map. Assign to fn declared outside of loop triggers escape of closure.
|
||||
// Heap -> stack pointer eventually causes badness when stack reallocation
|
||||
// occurs.
|
||||
|
||||
var fn func() // ERROR "moved to heap: fn$"
|
||||
for i := 0; i < maxI; i++ { // ERROR "moved to heap: i$"
|
||||
// var fn func() // this makes it work, because fn stays off heap
|
||||
j := 0 // ERROR "moved to heap: j$"
|
||||
fn = func() { // ERROR "func literal escapes to heap$"
|
||||
m[i] = append(m[i], 0) // ERROR "&i escapes to heap$"
|
||||
if j < 25 { // ERROR "&j escapes to heap$"
|
||||
j++
|
||||
fn() // ERROR "&fn escapes to heap$"
|
||||
}
|
||||
}
|
||||
fn()
|
||||
}
|
||||
|
||||
if len(m) != maxI {
|
||||
panic(fmt.Sprintf("iter %d: maxI = %d, len(m) = %d", iter, maxI, len(m))) // ERROR "iter escapes to heap$" "len\(m\) escapes to heap$" "maxI escapes to heap$" "test1 ... argument does not escape$"
|
||||
}
|
||||
}
|
||||
|
||||
func test2(iter int) {
|
||||
|
||||
const maxI = 500
|
||||
m := make(map[int][]int) // ERROR "test2 make\(map\[int\]\[\]int\) does not escape$"
|
||||
|
||||
// var fn func()
|
||||
for i := 0; i < maxI; i++ {
|
||||
var fn func() // this makes it work, because fn stays off heap
|
||||
j := 0
|
||||
fn = func() { // ERROR "test2 func literal does not escape$"
|
||||
m[i] = append(m[i], 0)
|
||||
if j < 25 {
|
||||
j++
|
||||
fn()
|
||||
}
|
||||
}
|
||||
fn()
|
||||
}
|
||||
|
||||
if len(m) != maxI {
|
||||
panic(fmt.Sprintf("iter %d: maxI = %d, len(m) = %d", iter, maxI, len(m))) // ERROR "iter escapes to heap$" "len\(m\) escapes to heap$" "maxI escapes to heap$" "test2 ... argument does not escape$"
|
||||
}
|
||||
}
|
||||
|
||||
func test3(iter int) {
|
||||
|
||||
const maxI = 500
|
||||
var x int // ERROR "moved to heap: x$"
|
||||
m := &x // ERROR "&x escapes to heap$"
|
||||
|
||||
var fn func() // ERROR "moved to heap: fn$"
|
||||
for i := 0; i < maxI; i++ {
|
||||
// var fn func() // this makes it work, because fn stays off heap
|
||||
j := 0 // ERROR "moved to heap: j$"
|
||||
fn = func() { // ERROR "func literal escapes to heap$"
|
||||
if j < 100 { // ERROR "&j escapes to heap$"
|
||||
j++
|
||||
fn() // ERROR "&fn escapes to heap$"
|
||||
} else {
|
||||
*m = *m + 1
|
||||
}
|
||||
}
|
||||
fn()
|
||||
}
|
||||
|
||||
if *m != maxI {
|
||||
panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "test3 ... argument does not escape$"
|
||||
}
|
||||
}
|
||||
|
||||
func test4(iter int) {
|
||||
|
||||
const maxI = 500
|
||||
var x int
|
||||
m := &x // ERROR "test4 &x does not escape$"
|
||||
|
||||
// var fn func()
|
||||
for i := 0; i < maxI; i++ {
|
||||
var fn func() // this makes it work, because fn stays off heap
|
||||
j := 0
|
||||
fn = func() { // ERROR "test4 func literal does not escape$"
|
||||
if j < 100 {
|
||||
j++
|
||||
fn()
|
||||
} else {
|
||||
*m = *m + 1
|
||||
}
|
||||
}
|
||||
fn()
|
||||
}
|
||||
|
||||
if *m != maxI {
|
||||
panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "test4 ... argument does not escape$"
|
||||
}
|
||||
}
|
||||
|
||||
type str struct {
|
||||
m *int
|
||||
}
|
||||
|
||||
func recur1(j int, s *str) { // ERROR "recur1 s does not escape"
|
||||
if j < 100 {
|
||||
j++
|
||||
recur1(j, s)
|
||||
} else {
|
||||
*s.m++
|
||||
}
|
||||
}
|
||||
|
||||
func test5(iter int) {
|
||||
|
||||
const maxI = 500
|
||||
var x int // ERROR "moved to heap: x$"
|
||||
m := &x // ERROR "&x escapes to heap$"
|
||||
|
||||
var fn *str
|
||||
for i := 0; i < maxI; i++ {
|
||||
// var fn *str // this makes it work, because fn stays off heap
|
||||
fn = &str{m} // ERROR "&str literal escapes to heap"
|
||||
recur1(0, fn)
|
||||
}
|
||||
|
||||
if *m != maxI {
|
||||
panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "test5 ... argument does not escape$"
|
||||
}
|
||||
}
|
||||
|
||||
func test6(iter int) {
|
||||
|
||||
const maxI = 500
|
||||
var x int
|
||||
m := &x // ERROR "&x does not escape$"
|
||||
|
||||
// var fn *str
|
||||
for i := 0; i < maxI; i++ {
|
||||
var fn *str // this makes it work, because fn stays off heap
|
||||
fn = &str{m} // ERROR "&str literal does not escape"
|
||||
recur1(0, fn)
|
||||
}
|
||||
|
||||
if *m != maxI {
|
||||
panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "test6 ... argument does not escape$"
|
||||
}
|
||||
}
|
||||
|
|
@ -20,3 +20,5 @@ var x4 = x1 && b2 // ERROR "mismatched types B and B2"
|
|||
var x5 = x2 && b2 // ERROR "mismatched types B and B2"
|
||||
var x6 = b2 && x1 // ERROR "mismatched types B2 and B"
|
||||
var x7 = b2 && x2 // ERROR "mismatched types B2 and B"
|
||||
|
||||
var x8 = b && !B2(true) // ERROR "mismatched types B and B2"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue